]> granicus.if.org Git - python/commitdiff
More rational support for Windows (tested on Roj's NT 3.5 machine only).
authorGuido van Rossum <guido@python.org>
Thu, 20 Jun 1996 16:25:29 +0000 (16:25 +0000)
committerGuido van Rossum <guido@python.org>
Thu, 20 Jun 1996 16:25:29 +0000 (16:25 +0000)
Use PyArg_ParseTuple() where it makes sense.

Modules/socketmodule.c

index ebdda8969db6c207a47bd9c06448efc2aa49f830..5fd12f3ebd372aad16ab7a2a600439176d93d8db 100644 (file)
@@ -31,6 +31,7 @@ Limitations:
 
 - only AF_INET and AF_UNIX address families are supported
 - no read/write operations (use send/recv or makefile instead)
+- additional restrictions apply on Windows
 
 Module interface:
 
@@ -58,6 +59,7 @@ Socket methods:
 - s.close() --> None
 - s.connect(sockaddr) --> None
 - s.fileno() --> file descriptor
+- s.dup() --> same as socket.fromfd(os.dup(s.fileno(), ...)
 - s.getpeername() --> sockaddr
 - s.getsockname() --> sockaddr
 - s.getsockopt(level, optname[, buflen]) --> int or string
@@ -113,7 +115,7 @@ Socket methods:
 #ifdef NT
 /* seem to be a few differences in the API */
 #define close closesocket
-#define NO_DUP /* Define for NT 3.1, Win3.1 and Win95, Undefine for NT3.5 */
+#define NO_DUP /* Actually it exists on NT 3.5, but what the heck... */
 #define FORCE_ANSI_FUNC_DEFS
 #endif
 
@@ -547,9 +549,12 @@ BUILD_FUNC_DEF_2(PySocketSock_getsockopt,PySocketSockObject *,s, PyObject *,args
        int optname;
        int res;
        PyObject *buf;
-       int buflen;
+       int buflen = 0;
 
-       if (PyArg_Parse(args, "(ii)", &level, &optname)) {
+       if (!PyArg_ParseTuple(args, "ii|i", &level, &optname, &buflen))
+               return NULL;
+       
+       if (buflen == 0) {
                int flag = 0;
                int flagsize = sizeof flag;
                res = getsockopt(s->sock_fd, level, optname,
@@ -558,9 +563,6 @@ BUILD_FUNC_DEF_2(PySocketSock_getsockopt,PySocketSockObject *,s, PyObject *,args
                        return PySocket_Err();
                return PyInt_FromLong(flag);
        }
-       PyErr_Clear();
-       if (!PyArg_Parse(args, "(iii)", &level, &optname, &buflen))
-               return NULL;
        if (buflen <= 0 || buflen > 1024) {
                PyErr_SetString(PySocket_Error, "getsockopt buflen out of range");
                return NULL;
@@ -648,6 +650,30 @@ BUILD_FUNC_DEF_2(PySocketSock_fileno,PySocketSockObject *,s, PyObject *,args)
 }
 
 
+#ifndef NO_DUP
+/* s.dup() method */
+
+static PyObject *
+BUILD_FUNC_DEF_2(PySocketSock_dup,PySocketSockObject *,s, PyObject *,args)
+{
+       int newfd;
+       PyObject *sock;
+       if (!PyArg_NoArgs(args))
+               return NULL;
+       newfd = dup(s->sock_fd);
+       if (newfd < 0)
+               return PySocket_Err();
+       sock = (PyObject *) PySocketSock_New(newfd,
+                                       s->sock_family,
+                                       s->sock_type,
+                                       s->sock_proto);
+       if (sock == NULL)
+               close(newfd);
+       return sock;
+}
+#endif
+
+
 /* s.getsockname() method */
 
 static PyObject *
@@ -754,14 +780,10 @@ BUILD_FUNC_DEF_2(PySocketSock_makefile,PySocketSockObject *,s, PyObject *,args)
 static PyObject *
 BUILD_FUNC_DEF_2(PySocketSock_recv,PySocketSockObject *,s, PyObject *,args)
 {
-       int len, n, flags;
+       int len, n, flags = 0;
        PyObject *buf;
-       flags = 0;
-       if (!PyArg_Parse(args, "i", &len)) {
-               PyErr_Clear();
-               if (!PyArg_Parse(args, "(ii)", &len, &flags))
-                       return NULL;
-       }
+       if (!PyArg_ParseTuple(args, "i|i", &len, &flags))
+               return NULL;
        buf = PyString_FromStringAndSize((char *) 0, len);
        if (buf == NULL)
                return NULL;
@@ -785,13 +807,9 @@ BUILD_FUNC_DEF_2(PySocketSock_recvfrom,PySocketSockObject *,s, PyObject *,args)
 {
        char addrbuf[256];
        PyObject *buf, *addr, *ret;
-       int addrlen, len, n, flags;
-       flags = 0;
-       if (!PyArg_Parse(args, "i", &len)) {
-               PyErr_Clear();
-               if (!PyArg_Parse(args, "(ii)", &len, &flags))
-                   return NULL;
-       }
+       int addrlen, len, n, flags = 0;
+       if (!PyArg_ParseTuple(args, "i|i", &len, &flags))
+               return NULL;
        if (!getsockaddrlen(s, &addrlen))
                return NULL;
        buf = PyString_FromStringAndSize((char *) 0, len);
@@ -825,13 +843,9 @@ static PyObject *
 BUILD_FUNC_DEF_2(PySocketSock_send,PySocketSockObject *,s, PyObject *,args)
 {
        char *buf;
-       int len, n, flags;
-       flags = 0;
-       if (!PyArg_Parse(args, "s#", &buf, &len)) {
-               PyErr_Clear();
-               if (!PyArg_Parse(args, "(s#i)", &buf, &len, &flags))
-                       return NULL;
-       }
+       int len, n, flags = 0;
+       if (!PyArg_ParseTuple(args, "s#|i", &buf, &len, &flags))
+               return NULL;
        Py_BEGIN_ALLOW_THREADS
        n = send(s->sock_fd, buf, len, flags);
        Py_END_ALLOW_THREADS
@@ -890,16 +904,16 @@ BUILD_FUNC_DEF_2(PySocketSock_shutdown,PySocketSockObject *,s, PyObject *,args)
 
 static PyMethodDef PySocketSock_methods[] = {
        {"accept",              (PyCFunction)PySocketSock_accept},
-#if 0
-       {"allowbroadcast",      (PyCFunction)PySocketSock_allowbroadcast},
-#endif
        {"setblocking",         (PyCFunction)PySocketSock_setblocking},
        {"setsockopt",          (PyCFunction)PySocketSock_setsockopt},
-       {"getsockopt",          (PyCFunction)PySocketSock_getsockopt},
+       {"getsockopt",          (PyCFunction)PySocketSock_getsockopt, 1},
        {"bind",                (PyCFunction)PySocketSock_bind},
        {"close",               (PyCFunction)PySocketSock_close},
        {"connect",             (PyCFunction)PySocketSock_connect},
        {"fileno",              (PyCFunction)PySocketSock_fileno},
+#ifndef NO_DUP
+       {"dup",                 (PyCFunction)PySocketSock_dup},
+#endif
        {"getsockname",         (PyCFunction)PySocketSock_getsockname},
 #ifdef HAVE_GETPEERNAME
        {"getpeername",         (PyCFunction)PySocketSock_getpeername},
@@ -908,9 +922,9 @@ static PyMethodDef PySocketSock_methods[] = {
 #ifndef NO_DUP
        {"makefile",            (PyCFunction)PySocketSock_makefile, 1},
 #endif
-       {"recv",                (PyCFunction)PySocketSock_recv},
-       {"recvfrom",            (PyCFunction)PySocketSock_recvfrom},
-       {"send",                (PyCFunction)PySocketSock_send},
+       {"recv",                (PyCFunction)PySocketSock_recv, 1},
+       {"recvfrom",            (PyCFunction)PySocketSock_recvfrom, 1},
+       {"send",                (PyCFunction)PySocketSock_send, 1},
        {"sendto",              (PyCFunction)PySocketSock_sendto},
        {"shutdown",            (PyCFunction)PySocketSock_shutdown},
        {NULL,                  NULL}           /* sentinel */
@@ -1099,13 +1113,9 @@ BUILD_FUNC_DEF_2(PySocket_socket,PyObject *,self, PyObject *,args)
 #else
        int fd;
 #endif
-       int family, type, proto;
-       proto = 0;
-       if (!PyArg_Parse(args, "(ii)", &family, &type)) {
-               PyErr_Clear();
-               if (!PyArg_Parse(args, "(iii)", &family, &type, &proto))
-                       return NULL;
-       }
+       int family, type, proto = 0;
+       if (!PyArg_ParseTuple(args, "ii|i", &family, &type, &proto))
+               return NULL;
        Py_BEGIN_ALLOW_THREADS
        fd = socket(family, type, proto);
        Py_END_ALLOW_THREADS
@@ -1138,13 +1148,9 @@ static PyObject *
 BUILD_FUNC_DEF_2(PySocket_fromfd,PyObject *,self, PyObject *,args)
 {
        PySocketSockObject *s;
-       int fd, family, type, proto;
-       proto = 0;
-       if (!PyArg_Parse(args, "(iii)", &fd, &family, &type)) {
-               PyErr_Clear();
-               if (!PyArg_Parse(args, "(iiii)", &fd, &family, &type, &proto))
-                       return NULL;
-       }
+       int fd, family, type, proto = 0;
+       if (!PyArg_ParseTuple(args, "iii|i", &fd, &family, &type, &proto))
+               return NULL;
        /* Dup the fd so it and the socket can be closed independently */
        fd = dup(fd);
        if (fd < 0)
@@ -1159,50 +1165,6 @@ BUILD_FUNC_DEF_2(PySocket_fromfd,PyObject *,self, PyObject *,args)
 }
 #endif /* NO_DUP */
 
-static PyObject * PySocket_WSAStartup(self, args)
-       PyObject *self, *args;
-{
-#ifdef _MSC_VER
-       WSADATA WSAData;
-       int ret;
-
-       if (!PyArg_NoArgs(args))
-               return NULL;
-       ret = WSAStartup(0x0101, &WSAData);     /* request version 1.1 */
-       switch(ret){
-       case WSASYSNOTREADY:
-               PyErr_SetString(PySocket_Error,
-                       "WSAStartup failed: Network not ready\n");
-               break;
-       case WSAVERNOTSUPPORTED:
-       case WSAEINVAL:
-               PyErr_SetString(PySocket_Error,
-                       "WSAStartup failed: Requested version not supported");
-               break;
-       case 0: /* no error */
-               break;
-       default:
-               PyErr_SetString(PySocket_Error,
-                       "WSAStartup failed");
-               break;
-       }
-#endif
-       Py_INCREF(Py_None);
-       return Py_None;
-}
-
-static PyObject * PySocket_WSACleanup(self, args)
-       PyObject *self, *args;
-{
-       if (!PyArg_NoArgs(args))
-               return NULL;
-#ifdef _MSC_VER
-       WSACleanup();
-#endif
-       Py_INCREF(Py_None);
-       return Py_None;
-}
-
 static PyObject *
 BUILD_FUNC_DEF_2(PySocket_ntohs, PyObject *, self, PyObject *, args)
 {
@@ -1258,11 +1220,9 @@ static PyMethodDef PySocket_methods[] = {
        {"gethostbyaddr",       PySocket_gethostbyaddr},
        {"gethostname",         PySocket_gethostname},
        {"getservbyname",       PySocket_getservbyname},
-       {"socket",              PySocket_socket},
-       {"WSAStartup",          PySocket_WSAStartup},
-       {"WSACleanup",          PySocket_WSACleanup},
+       {"socket",              PySocket_socket, 1},
 #ifndef NO_DUP
-       {"fromfd",              PySocket_fromfd},
+       {"fromfd",              PySocket_fromfd, 1},
 #endif
        {"ntohs",               PySocket_ntohs},
        {"ntohl",               PySocket_ntohl},
@@ -1290,16 +1250,76 @@ BUILD_FUNC_DEF_3(insint,PyObject *,d, char *,name, int,value)
 }
 
 
+#ifdef NT
+
+/* Additional initialization and cleanup for NT/Windows */
+
+static void
+NTcleanup()
+{
+       WSACleanup();
+       fprintf(stderr, "WSACleanup called\n");
+}
+
+static int
+NTinit()
+{
+       WSADATA WSAData;
+       int ret;
+       char buf[100];
+       ret = WSAStartup(0x0101, &WSAData);
+       switch (ret) {
+       case 0: /* no error */
+               atexit(NTcleanup);
+               return 1;
+       case WSASYSNOTREADY:
+               PyErr_SetString(PyExc_ImportError,
+                               "WSAStartup failed: network not ready");
+               break;
+       case WSAVERNOTSUPPORTED:
+       case WSAEINVAL:
+               PyErr_SetString(PyExc_ImportError,
+                   "WSAStartup failed: requested version not supported");
+               break;
+       default:
+               sprintf(buf, "WSAStartup failed: error code %d", ret);
+               PyErr_SetString(PyExc_ImportError, buf);
+               break;
+       }
+       return 0;
+}
+
+#endif /* NT */
+
+
 /* Initialize this module.
    This is called when the first 'import socket' is done,
    via a table in config.c, if config.c is compiled with USE_SOCKET
-   defined. */
+   defined.
+
+   For NT (which actually means any Windows variant (?)), this module
+   is actually called "_socket", and there's a wrapper "socket.py"
+   which implements some missing functionality (such as makefile(),
+   dup() and fromfd()).  The import of "_socket" may fail with an
+   ImportError exception if initialization of WINSOCK fails.  When
+   WINSOCK is initialized succesfully, a call to WSACleanup() is
+   scheduled to be made at exit time.  */
 
 void
+#ifdef NT
+init_socket()
+#else
 initsocket()
+#endif
 {
        PyObject *m, *d;
+#ifdef NT
+       if (!NTinit())
+               return;
+       m = Py_InitModule("_socket", PySocket_methods);
+#else
        m = Py_InitModule("socket", PySocket_methods);
+#endif
        d = PyModule_GetDict(m);
        PySocket_Error = PyString_FromString("socket.error");
        if (PySocket_Error == NULL || 
@@ -1553,48 +1573,4 @@ initsocket()
 #ifdef IP_DROP_MEMBERSHIP
        insint(d, "IP_DROP_MEMBERSHIP", IP_DROP_MEMBERSHIP);
 #endif
-
-#ifdef MS_WIN16
-/* All windows sockets require a successful WSAStartup() before use */
-       Py_XDECREF(PySocket_WSAStartup(NULL, NULL));
-#endif
 }
-
-#ifdef NT
-BOOL   WINAPI  DllMain (HANDLE hInst, 
-                       ULONG ul_reason_for_call,
-                       LPVOID lpReserved)
-{
-       const int opt = SO_SYNCHRONOUS_NONALERT;
-       switch (ul_reason_for_call)
-       {
-               case DLL_PROCESS_ATTACH: {
-                       WSADATA WSAData;
-                       BOOL ok = TRUE;
-                       char buf[100] = "Python can't initialize Windows Sockets Module!\n\r";
-                       if (WSAStartup(MAKEWORD(1,1), &WSAData)) {
-                               wsprintf(buf+strlen(buf), "WSAStartup failed (%d)",WSAGetLastError());
-                               ok = FALSE;
-                       }
-                       /*
-                       ** Setup sockets in non-overlapped mode by default
-                       */
-//                     if (ok && setsockopt(INVALID_SOCKET,SOL_SOCKET,SO_OPENTYPE,(const char *)&opt,sizeof(opt)) != 0) {
-//                             wsprintf(buf+strlen(buf),"setsockopt failed (%d)",WSAGetLastError());
-//                             ok = FALSE;
-//                     }
-                       if (!ok) {
-                               MessageBox(NULL,buf,"WinSock Error",MB_OK|MB_SETFOREGROUND);
-                               return FALSE;
-                       }
-                       break;
-               }
-
-               case DLL_PROCESS_DETACH:
-                       WSACleanup();
-                       break;
-
-       }
-       return TRUE;
-}
-#endif /* NT */