| /*********************************************************** |
| Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam, |
| The Netherlands. |
| |
| All Rights Reserved |
| |
| Permission to use, copy, modify, and distribute this software and its |
| documentation for any purpose and without fee is hereby granted, |
| provided that the above copyright notice appear in all copies and that |
| both that copyright notice and this permission notice appear in |
| supporting documentation, and that the names of Stichting Mathematisch |
| Centrum or CWI not be used in advertising or publicity pertaining to |
| distribution of the software without specific, written prior permission. |
| |
| STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO |
| THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND |
| FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE |
| FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
| WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
| ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT |
| OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
| |
| ******************************************************************/ |
| |
| /* POSIX module implementation */ |
| |
| /* This file is also used for Windows NT and MS-Win. In that case the module |
| actually calls itself 'nt', not 'posix', and a few functions are |
| either unimplemented or implemented differently. The source |
| assumes that for Windows NT, the macro 'NT' is defined independent |
| of the compiler used. Different compilers define their own feature |
| test macro, e.g. '__BORLANDC__' or '_MSC_VER'. */ |
| |
| /* See also ../Dos/dosmodule.c */ |
| |
| #include "allobjects.h" |
| #include "modsupport.h" |
| #include "ceval.h" |
| |
| #include <string.h> |
| #include <errno.h> |
| #include <sys/types.h> |
| #include <sys/stat.h> |
| #ifdef HAVE_SYS_WAIT_H |
| #include <sys/wait.h> /* For WNOHANG */ |
| #endif |
| |
| #include "mytime.h" /* For clock_t on some systems */ |
| |
| #ifdef HAVE_FCNTL_H |
| #include <fcntl.h> |
| #endif /* HAVE_FCNTL_H */ |
| |
| /* Various compilers have only certain posix functions */ |
| #ifdef __WATCOMC__ /* Watcom compiler */ |
| #define HAVE_GETCWD 1 |
| #define HAVE_OPENDIR 1 |
| #define HAVE_SYSTEM 1 |
| #if defined(__OS2__) |
| #define HAVE_EXECV 1 |
| #define HAVE_WAIT 1 |
| #endif |
| #include <process.h> |
| #else |
| #ifdef __BORLANDC__ /* Borland compiler */ |
| #define HAVE_EXECV 1 |
| #define HAVE_GETCWD 1 |
| #define HAVE_GETEGID 1 |
| #define HAVE_GETEUID 1 |
| #define HAVE_GETGID 1 |
| #define HAVE_GETPPID 1 |
| #define HAVE_GETUID 1 |
| #define HAVE_KILL 1 |
| #define HAVE_OPENDIR 1 |
| #define HAVE_PIPE 1 |
| #define HAVE_POPEN 1 |
| #define HAVE_SYSTEM 1 |
| #define HAVE_WAIT 1 |
| #else |
| #ifdef _MSC_VER /* Microsoft compiler */ |
| #ifdef NT |
| #define HAVE_EXECV 1 |
| #define HAVE_PIPE 1 |
| #define HAVE_POPEN 1 |
| #define HAVE_SYSTEM 1 |
| #else /* 16-bit Windows */ |
| #endif /* NT */ |
| #else /* all other compilers */ |
| /* Unix functions that the configure script doesn't check for */ |
| #define HAVE_EXECV 1 |
| #define HAVE_FORK 1 |
| #define HAVE_GETCWD 1 |
| #define HAVE_GETEGID 1 |
| #define HAVE_GETEUID 1 |
| #define HAVE_GETGID 1 |
| #define HAVE_GETPPID 1 |
| #define HAVE_GETUID 1 |
| #define HAVE_KILL 1 |
| #define HAVE_OPENDIR 1 |
| #define HAVE_PIPE 1 |
| #define HAVE_POPEN 1 |
| #define HAVE_SYSTEM 1 |
| #define HAVE_WAIT 1 |
| #endif /* _MSC_VER */ |
| #endif /* __BORLANDC__ */ |
| #endif /* ! __WATCOMC__ */ |
| |
| #ifndef _MSC_VER |
| |
| #ifdef HAVE_UNISTD_H |
| #include <unistd.h> |
| #endif |
| |
| #ifdef NeXT |
| /* NeXT's <unistd.h> and <utime.h> aren't worth much */ |
| #undef HAVE_UNISTD_H |
| #undef HAVE_UTIME_H |
| /* #undef HAVE_GETCWD */ |
| #endif |
| |
| #ifdef HAVE_UNISTD_H |
| /* XXX These are for SunOS4.1.3 but shouldn't hurt elsewhere */ |
| extern int rename(); |
| extern int pclose(); |
| extern int lstat(); |
| extern int symlink(); |
| #else /* !HAVE_UNISTD_H */ |
| #if defined(__WATCOMC__) |
| extern int mkdir PROTO((const char *)); |
| #else |
| extern int mkdir PROTO((const char *, mode_t)); |
| #endif |
| extern int chdir PROTO((const char *)); |
| extern int rmdir PROTO((const char *)); |
| extern int chmod PROTO((const char *, mode_t)); |
| extern int chown PROTO((const char *, uid_t, gid_t)); |
| extern char *getcwd PROTO((char *, int)); |
| extern char *strerror PROTO((int)); |
| extern int link PROTO((const char *, const char *)); |
| extern int rename PROTO((const char *, const char *)); |
| extern int stat PROTO((const char *, struct stat *)); |
| extern int unlink PROTO((const char *)); |
| extern int pclose PROTO((FILE *)); |
| #ifdef HAVE_SYMLINK |
| extern int symlink PROTO((const char *, const char *)); |
| #endif /* HAVE_SYMLINK */ |
| #ifdef HAVE_LSTAT |
| extern int lstat PROTO((const char *, struct stat *)); |
| #endif /* HAVE_LSTAT */ |
| #endif /* !HAVE_UNISTD_H */ |
| |
| #endif /* !_MSC_VER */ |
| |
| #ifdef HAVE_UTIME_H |
| #include <utime.h> |
| #endif /* HAVE_UTIME_H */ |
| |
| #ifdef HAVE_SYS_UTIME_H |
| #include <sys/utime.h> |
| #define HAVE_UTIME_H /* pretend we do for the rest of this file */ |
| #endif /* HAVE_SYS_UTIME_H */ |
| |
| #ifdef HAVE_SYS_TIMES_H |
| #include <sys/times.h> |
| #endif /* HAVE_SYS_TIMES_H */ |
| |
| #ifdef HAVE_SYS_PARAM_H |
| #include <sys/param.h> |
| #endif /* HAVE_SYS_PARAM_H */ |
| |
| #ifdef HAVE_SYS_UTSNAME_H |
| #include <sys/utsname.h> |
| #endif /* HAVE_SYS_UTSNAME_H */ |
| |
| #ifndef MAXPATHLEN |
| #define MAXPATHLEN 1024 |
| #endif /* MAXPATHLEN */ |
| |
| #ifdef HAVE_DIRENT_H |
| #include <dirent.h> |
| #define NAMLEN(dirent) strlen((dirent)->d_name) |
| #else |
| #ifdef __WATCOMC__ |
| #include <direct.h> |
| #define NAMLEN(dirent) strlen((dirent)->d_name) |
| #else |
| #define dirent direct |
| #define NAMLEN(dirent) (dirent)->d_namlen |
| #endif |
| #ifdef HAVE_SYS_NDIR_H |
| #include <sys/ndir.h> |
| #endif |
| #ifdef HAVE_SYS_DIR_H |
| #include <sys/dir.h> |
| #endif |
| #ifdef HAVE_NDIR_H |
| #include <ndir.h> |
| #endif |
| #endif |
| |
| #ifdef _MSC_VER |
| #include <direct.h> |
| #include <io.h> |
| #include <process.h> |
| #include <windows.h> |
| #ifdef NT |
| #define popen _popen |
| #define pclose _pclose |
| #else /* 16-bit Windows */ |
| #include <dos.h> |
| #include <ctype.h> |
| #endif /* NT */ |
| #endif /* _MSC_VER */ |
| |
| #ifdef OS2 |
| #include <io.h> |
| #endif /* OS2 */ |
| |
| /* Return a dictionary corresponding to the POSIX environment table */ |
| |
| #if !defined(_MSC_VER) && !defined(__WATCOMC__) |
| extern char **environ; |
| #endif /* !_MSC_VER */ |
| |
| static object * |
| convertenviron() |
| { |
| object *d; |
| char **e; |
| d = newdictobject(); |
| if (d == NULL) |
| return NULL; |
| if (environ == NULL) |
| return d; |
| /* XXX This part ignores errors */ |
| for (e = environ; *e != NULL; e++) { |
| object *v; |
| char *p = strchr(*e, '='); |
| if (p == NULL) |
| continue; |
| v = newstringobject(p+1); |
| if (v == NULL) |
| continue; |
| *p = '\0'; |
| (void) dictinsert(d, *e, v); |
| *p = '='; |
| DECREF(v); |
| } |
| return d; |
| } |
| |
| |
| static object *PosixError; /* Exception posix.error */ |
| |
| /* Set a POSIX-specific error from errno, and return NULL */ |
| |
| static object * posix_error() |
| { |
| return err_errno(PosixError); |
| } |
| |
| |
| /* POSIX generic methods */ |
| |
| static object * |
| posix_1str(args, func) |
| object *args; |
| int (*func) FPROTO((const char *)); |
| { |
| char *path1; |
| int res; |
| if (!getargs(args, "s", &path1)) |
| return NULL; |
| BGN_SAVE |
| res = (*func)(path1); |
| END_SAVE |
| if (res < 0) |
| return posix_error(); |
| INCREF(None); |
| return None; |
| } |
| |
| static object * |
| posix_2str(args, func) |
| object *args; |
| int (*func) FPROTO((const char *, const char *)); |
| { |
| char *path1, *path2; |
| int res; |
| if (!getargs(args, "(ss)", &path1, &path2)) |
| return NULL; |
| BGN_SAVE |
| res = (*func)(path1, path2); |
| END_SAVE |
| if (res < 0) |
| return posix_error(); |
| INCREF(None); |
| return None; |
| } |
| |
| static object * |
| posix_strint(args, func) |
| object *args; |
| int (*func) FPROTO((const char *, int)); |
| { |
| char *path; |
| int i; |
| int res; |
| if (!getargs(args, "(si)", &path, &i)) |
| return NULL; |
| BGN_SAVE |
| res = (*func)(path, i); |
| END_SAVE |
| if (res < 0) |
| return posix_error(); |
| INCREF(None); |
| return None; |
| } |
| |
| static object * |
| posix_strintint(args, func) |
| object *args; |
| int (*func) FPROTO((const char *, int, int)); |
| { |
| char *path; |
| int i,i2; |
| int res; |
| if (!getargs(args, "(sii)", &path, &i, &i2)) |
| return NULL; |
| BGN_SAVE |
| res = (*func)(path, i, i2); |
| END_SAVE |
| if (res < 0) |
| return posix_error(); |
| INCREF(None); |
| return None; |
| } |
| |
| static object * |
| posix_do_stat(self, args, statfunc) |
| object *self; |
| object *args; |
| int (*statfunc) FPROTO((const char *, struct stat *)); |
| { |
| struct stat st; |
| char *path; |
| int res; |
| if (!getargs(args, "s", &path)) |
| return NULL; |
| BGN_SAVE |
| res = (*statfunc)(path, &st); |
| END_SAVE |
| if (res != 0) |
| return posix_error(); |
| return mkvalue("(llllllllll)", |
| (long)st.st_mode, |
| (long)st.st_ino, |
| (long)st.st_dev, |
| (long)st.st_nlink, |
| (long)st.st_uid, |
| (long)st.st_gid, |
| (long)st.st_size, |
| (long)st.st_atime, |
| (long)st.st_mtime, |
| (long)st.st_ctime); |
| } |
| |
| |
| /* POSIX methods */ |
| |
| static object * |
| posix_chdir(self, args) |
| object *self; |
| object *args; |
| { |
| return posix_1str(args, chdir); |
| } |
| |
| static object * |
| posix_chmod(self, args) |
| object *self; |
| object *args; |
| { |
| return posix_strint(args, chmod); |
| } |
| |
| #ifdef HAVE_CHOWN |
| static object * |
| posix_chown(self, args) |
| object *self; |
| object *args; |
| { |
| return posix_strintint(args, chown); |
| } |
| #endif /* HAVE_CHOWN */ |
| |
| #ifdef HAVE_GETCWD |
| static object * |
| posix_getcwd(self, args) |
| object *self; |
| object *args; |
| { |
| char buf[1026]; |
| char *res; |
| if (!getnoarg(args)) |
| return NULL; |
| BGN_SAVE |
| res = getcwd(buf, sizeof buf); |
| END_SAVE |
| if (res == NULL) |
| return posix_error(); |
| return newstringobject(buf); |
| } |
| #endif |
| |
| #ifdef HAVE_LINK |
| static object * |
| posix_link(self, args) |
| object *self; |
| object *args; |
| { |
| return posix_2str(args, link); |
| } |
| #endif /* HAVE_LINK */ |
| |
| static object * |
| posix_listdir(self, args) |
| object *self; |
| object *args; |
| { |
| #if defined(NT) && !defined(HAVE_OPENDIR) |
| |
| char *name; |
| int len; |
| object *d, *v; |
| HANDLE hFindFile; |
| WIN32_FIND_DATA FileData; |
| char namebuf[MAX_PATH+5]; |
| |
| if (!getargs(args, "s#", &name, &len)) |
| return NULL; |
| if (len >= MAX_PATH) { |
| err_setstr(ValueError, "path too long"); |
| return NULL; |
| } |
| strcpy(namebuf, name); |
| if (namebuf[len-1] != '/' && namebuf[len-1] != '\\') |
| namebuf[len++] = '/'; |
| strcpy(namebuf + len, "*.*"); |
| |
| if ((d = newlistobject(0)) == NULL) |
| return NULL; |
| |
| hFindFile = FindFirstFile(namebuf, &FileData); |
| if (hFindFile == INVALID_HANDLE_VALUE) { |
| errno = GetLastError(); |
| return posix_error(); |
| } |
| do { |
| if (FileData.cFileName[0] == '.' && |
| (FileData.cFileName[1] == '\0' || |
| FileData.cFileName[1] == '.' && |
| FileData.cFileName[2] == '\0')) |
| continue; |
| v = newstringobject(FileData.cFileName); |
| if (v == NULL) { |
| DECREF(d); |
| d = NULL; |
| break; |
| } |
| if (addlistitem(d, v) != 0) { |
| DECREF(v); |
| DECREF(d); |
| d = NULL; |
| break; |
| } |
| DECREF(v); |
| } while (FindNextFile(hFindFile, &FileData) == TRUE); |
| |
| if (FindClose(hFindFile) == FALSE) { |
| errno = GetLastError(); |
| return posix_error(); |
| } |
| |
| return d; |
| |
| #else /* !NT */ |
| #ifdef _MSC_VER /* 16-bit Windows */ |
| |
| #ifndef MAX_PATH |
| #define MAX_PATH 250 |
| #endif |
| char *name, *pt; |
| int len; |
| object *d, *v; |
| char namebuf[MAX_PATH+5]; |
| struct _find_t ep; |
| |
| if (!getargs(args, "s#", &name, &len)) |
| return NULL; |
| if (len >= MAX_PATH) { |
| err_setstr(ValueError, "path too long"); |
| return NULL; |
| } |
| strcpy(namebuf, name); |
| for (pt = namebuf; *pt; pt++) |
| if (*pt == '/') |
| *pt = '\\'; |
| if (namebuf[len-1] != '\\') |
| namebuf[len++] = '\\'; |
| strcpy(namebuf + len, "*.*"); |
| |
| if ((d = newlistobject(0)) == NULL) |
| return NULL; |
| |
| if (_dos_findfirst(namebuf, _A_RDONLY | |
| _A_HIDDEN | _A_SYSTEM | _A_SUBDIR, &ep) != 0){ |
| errno = ENOENT; |
| return posix_error(); |
| } |
| do { |
| if (ep.name[0] == '.' && |
| (ep.name[1] == '\0' || |
| ep.name[1] == '.' && |
| ep.name[2] == '\0')) |
| continue; |
| strcpy(namebuf, ep.name); |
| for (pt = namebuf; *pt; pt++) |
| if (isupper(*pt)) |
| *pt = tolower(*pt); |
| v = newstringobject(namebuf); |
| if (v == NULL) { |
| DECREF(d); |
| d = NULL; |
| break; |
| } |
| if (addlistitem(d, v) != 0) { |
| DECREF(v); |
| DECREF(d); |
| d = NULL; |
| break; |
| } |
| DECREF(v); |
| } while (_dos_findnext(&ep) == 0); |
| |
| return d; |
| |
| #else |
| |
| char *name; |
| object *d, *v; |
| DIR *dirp; |
| struct dirent *ep; |
| if (!getargs(args, "s", &name)) |
| return NULL; |
| BGN_SAVE |
| if ((dirp = opendir(name)) == NULL) { |
| RET_SAVE |
| return posix_error(); |
| } |
| if ((d = newlistobject(0)) == NULL) { |
| closedir(dirp); |
| RET_SAVE |
| return NULL; |
| } |
| while ((ep = readdir(dirp)) != NULL) { |
| if (ep->d_name[0] == '.' && |
| (NAMLEN(ep) == 1 || |
| ep->d_name[1] == '.' && NAMLEN(ep) == 2)) |
| continue; |
| v = newsizedstringobject(ep->d_name, NAMLEN(ep)); |
| if (v == NULL) { |
| DECREF(d); |
| d = NULL; |
| break; |
| } |
| if (addlistitem(d, v) != 0) { |
| DECREF(v); |
| DECREF(d); |
| d = NULL; |
| break; |
| } |
| DECREF(v); |
| } |
| closedir(dirp); |
| END_SAVE |
| |
| return d; |
| |
| #endif /* !_MSC_VER */ |
| #endif /* !NT */ |
| } |
| |
| static object * |
| posix_mkdir(self, args) |
| object *self; |
| object *args; |
| { |
| int res; |
| char *path; |
| int mode = 0777; |
| if (!newgetargs(args, "s|i", &path, &mode)) |
| return NULL; |
| BGN_SAVE |
| #if defined(__WATCOMC__) |
| res = mkdir(path); |
| #else |
| res = mkdir(path, mode); |
| #endif |
| END_SAVE |
| if (res < 0) |
| return posix_error(); |
| INCREF(None); |
| return None; |
| } |
| |
| #ifdef HAVE_NICE |
| static object * |
| posix_nice(self, args) |
| object *self; |
| object *args; |
| { |
| int increment, value; |
| |
| if (!getargs(args, "i", &increment)) |
| return NULL; |
| value = nice(increment); |
| if (value == -1) |
| return posix_error(); |
| return newintobject((long) value); |
| } |
| #endif /* HAVE_NICE */ |
| |
| static object * |
| posix_rename(self, args) |
| object *self; |
| object *args; |
| { |
| return posix_2str(args, rename); |
| } |
| |
| static object * |
| posix_rmdir(self, args) |
| object *self; |
| object *args; |
| { |
| return posix_1str(args, rmdir); |
| } |
| |
| static object * |
| posix_stat(self, args) |
| object *self; |
| object *args; |
| { |
| return posix_do_stat(self, args, stat); |
| } |
| |
| #ifdef HAVE_SYSTEM |
| static object * |
| posix_system(self, args) |
| object *self; |
| object *args; |
| { |
| char *command; |
| long sts; |
| if (!getargs(args, "s", &command)) |
| return NULL; |
| BGN_SAVE |
| sts = system(command); |
| END_SAVE |
| return newintobject(sts); |
| } |
| #endif |
| |
| static object * |
| posix_umask(self, args) |
| object *self; |
| object *args; |
| { |
| int i; |
| if (!getintarg(args, &i)) |
| return NULL; |
| i = umask(i); |
| if (i < 0) |
| return posix_error(); |
| return newintobject((long)i); |
| } |
| |
| static object * |
| posix_unlink(self, args) |
| object *self; |
| object *args; |
| { |
| return posix_1str(args, unlink); |
| } |
| |
| #ifdef HAVE_UNAME |
| static object * |
| posix_uname(self, args) |
| object *self; |
| object *args; |
| { |
| struct utsname u; |
| object *v; |
| int res; |
| if (!getnoarg(args)) |
| return NULL; |
| BGN_SAVE |
| res = uname(&u); |
| END_SAVE |
| if (res < 0) |
| return posix_error(); |
| return mkvalue("(sssss)", |
| u.sysname, |
| u.nodename, |
| u.release, |
| u.version, |
| u.machine); |
| } |
| #endif /* HAVE_UNAME */ |
| |
| static object * |
| posix_utime(self, args) |
| object *self; |
| object *args; |
| { |
| char *path; |
| long atime, mtime; |
| int res; |
| |
| #ifdef HAVE_UTIME_H |
| struct utimbuf buf; |
| #define ATIME buf.actime |
| #define MTIME buf.modtime |
| #define UTIME_ARG &buf |
| #else /* HAVE_UTIME_H */ |
| time_t buf[2]; |
| #define ATIME buf[0] |
| #define MTIME buf[1] |
| #define UTIME_ARG buf |
| #endif /* HAVE_UTIME_H */ |
| |
| if (!getargs(args, "(s(ll))", &path, &atime, &mtime)) |
| return NULL; |
| ATIME = atime; |
| MTIME = mtime; |
| BGN_SAVE |
| res = utime(path, UTIME_ARG); |
| END_SAVE |
| if (res < 0) |
| return posix_error(); |
| INCREF(None); |
| return None; |
| #undef UTIME_ARG |
| #undef ATIME |
| #undef MTIME |
| } |
| |
| |
| /* Process operations */ |
| |
| static object * |
| posix__exit(self, args) |
| object *self; |
| object *args; |
| { |
| int sts; |
| if (!getintarg(args, &sts)) |
| return NULL; |
| _exit(sts); |
| /* NOTREACHED */ |
| } |
| |
| #ifdef HAVE_EXECV |
| static object * |
| posix_execv(self, args) |
| object *self; |
| object *args; |
| { |
| char *path; |
| object *argv; |
| char **argvlist; |
| int i, argc; |
| object *(*getitem) PROTO((object *, int)); |
| |
| /* execv has two arguments: (path, argv), where |
| argv is a list or tuple of strings. */ |
| |
| if (!getargs(args, "(sO)", &path, &argv)) |
| return NULL; |
| if (is_listobject(argv)) { |
| argc = getlistsize(argv); |
| getitem = getlistitem; |
| } |
| else if (is_tupleobject(argv)) { |
| argc = gettuplesize(argv); |
| getitem = gettupleitem; |
| } |
| else { |
| badarg: |
| err_badarg(); |
| return NULL; |
| } |
| |
| argvlist = NEW(char *, argc+1); |
| if (argvlist == NULL) |
| return NULL; |
| for (i = 0; i < argc; i++) { |
| if (!getargs((*getitem)(argv, i), "s", &argvlist[i])) { |
| DEL(argvlist); |
| goto badarg; |
| } |
| } |
| argvlist[argc] = NULL; |
| |
| #ifdef BAD_EXEC_PROTOTYPES |
| execv(path, (const char **) argvlist); |
| #else /* BAD_EXEC_PROTOTYPES */ |
| execv(path, argvlist); |
| #endif /* BAD_EXEC_PROTOTYPES */ |
| |
| /* If we get here it's definitely an error */ |
| |
| DEL(argvlist); |
| return posix_error(); |
| } |
| |
| static object * |
| posix_execve(self, args) |
| object *self; |
| object *args; |
| { |
| char *path; |
| object *argv, *env; |
| char **argvlist; |
| char **envlist; |
| object *key, *val; |
| int i, pos, argc, envc; |
| object *(*getitem) PROTO((object *, int)); |
| |
| /* execve has three arguments: (path, argv, env), where |
| argv is a list or tuple of strings and env is a dictionary |
| like posix.environ. */ |
| |
| if (!getargs(args, "(sOO)", &path, &argv, &env)) |
| return NULL; |
| if (is_listobject(argv)) { |
| argc = getlistsize(argv); |
| getitem = getlistitem; |
| } |
| else if (is_tupleobject(argv)) { |
| argc = gettuplesize(argv); |
| getitem = gettupleitem; |
| } |
| else { |
| err_setstr(TypeError, "argv must be tuple or list"); |
| return NULL; |
| } |
| if (!is_dictobject(env)) { |
| err_setstr(TypeError, "env must be dictionary"); |
| return NULL; |
| } |
| |
| argvlist = NEW(char *, argc+1); |
| if (argvlist == NULL) { |
| err_nomem(); |
| return NULL; |
| } |
| for (i = 0; i < argc; i++) { |
| if (!getargs((*getitem)(argv, i), |
| "s;argv must be list of strings", |
| &argvlist[i])) { |
| goto fail_1; |
| } |
| } |
| argvlist[argc] = NULL; |
| |
| i = getmappingsize(env); |
| envlist = NEW(char *, i + 1); |
| if (envlist == NULL) { |
| err_nomem(); |
| goto fail_1; |
| } |
| pos = 0; |
| envc = 0; |
| while (mappinggetnext(env, &pos, &key, &val)) { |
| char *p, *k, *v; |
| if (!getargs(key, "s;non-string key in env", &k) || |
| !getargs(val, "s;non-string value in env", &v)) { |
| goto fail_2; |
| } |
| p = NEW(char, getstringsize(key) + getstringsize(val) + 2); |
| if (p == NULL) { |
| err_nomem(); |
| goto fail_2; |
| } |
| sprintf(p, "%s=%s", k, v); |
| envlist[envc++] = p; |
| } |
| envlist[envc] = 0; |
| |
| |
| #ifdef BAD_EXEC_PROTOTYPES |
| execve(path, (const char **)argvlist, envlist); |
| #else /* BAD_EXEC_PROTOTYPES */ |
| execve(path, argvlist, envlist); |
| #endif /* BAD_EXEC_PROTOTYPES */ |
| |
| /* If we get here it's definitely an error */ |
| |
| (void) posix_error(); |
| |
| fail_2: |
| while (--envc >= 0) |
| DEL(envlist[envc]); |
| DEL(envlist); |
| fail_1: |
| DEL(argvlist); |
| |
| return NULL; |
| } |
| #endif /* HAVE_EXECV */ |
| |
| #ifdef HAVE_FORK |
| static object * |
| posix_fork(self, args) |
| object *self; |
| object *args; |
| { |
| int pid; |
| if (!getnoarg(args)) |
| return NULL; |
| pid = fork(); |
| if (pid == -1) |
| return posix_error(); |
| return newintobject((long)pid); |
| } |
| #endif |
| |
| #ifdef HAVE_GETEGID |
| static object * |
| posix_getegid(self, args) |
| object *self; |
| object *args; |
| { |
| if (!getnoarg(args)) |
| return NULL; |
| return newintobject((long)getegid()); |
| } |
| #endif |
| |
| #ifdef HAVE_GETEUID |
| static object * |
| posix_geteuid(self, args) |
| object *self; |
| object *args; |
| { |
| if (!getnoarg(args)) |
| return NULL; |
| return newintobject((long)geteuid()); |
| } |
| #endif |
| |
| #ifdef HAVE_GETGID |
| static object * |
| posix_getgid(self, args) |
| object *self; |
| object *args; |
| { |
| if (!getnoarg(args)) |
| return NULL; |
| return newintobject((long)getgid()); |
| } |
| #endif |
| |
| static object * |
| posix_getpid(self, args) |
| object *self; |
| object *args; |
| { |
| if (!getnoarg(args)) |
| return NULL; |
| return newintobject((long)getpid()); |
| } |
| |
| #ifdef HAVE_GETPGRP |
| static object * |
| posix_getpgrp(self, args) |
| object *self; |
| object *args; |
| { |
| if (!getnoarg(args)) |
| return NULL; |
| #ifdef GETPGRP_HAVE_ARG |
| return newintobject((long)getpgrp(0)); |
| #else /* GETPGRP_HAVE_ARG */ |
| return newintobject((long)getpgrp()); |
| #endif /* GETPGRP_HAVE_ARG */ |
| } |
| #endif /* HAVE_GETPGRP */ |
| |
| #ifdef HAVE_SETPGRP |
| static object * |
| posix_setpgrp(self, args) |
| object *self; |
| object *args; |
| { |
| if (!getnoarg(args)) |
| return NULL; |
| #ifdef SETPGRP_HAVE_ARG |
| if (setpgrp(0, 0) < 0) |
| #else /* SETPGRP_HAVE_ARG */ |
| if (setpgrp() < 0) |
| #endif /* SETPGRP_HAVE_ARG */ |
| return posix_error(); |
| INCREF(None); |
| return None; |
| } |
| |
| #endif /* HAVE_SETPGRP */ |
| |
| #ifdef HAVE_GETPPID |
| static object * |
| posix_getppid(self, args) |
| object *self; |
| object *args; |
| { |
| if (!getnoarg(args)) |
| return NULL; |
| return newintobject((long)getppid()); |
| } |
| #endif |
| |
| #ifdef HAVE_GETUID |
| static object * |
| posix_getuid(self, args) |
| object *self; |
| object *args; |
| { |
| if (!getnoarg(args)) |
| return NULL; |
| return newintobject((long)getuid()); |
| } |
| #endif |
| |
| #ifdef HAVE_KILL |
| static object * |
| posix_kill(self, args) |
| object *self; |
| object *args; |
| { |
| int pid, sig; |
| if (!getargs(args, "(ii)", &pid, &sig)) |
| return NULL; |
| if (kill(pid, sig) == -1) |
| return posix_error(); |
| INCREF(None); |
| return None; |
| } |
| #endif |
| |
| #ifdef HAVE_POPEN |
| static object * |
| posix_popen(self, args) |
| object *self; |
| object *args; |
| { |
| char *name; |
| char *mode = "r"; |
| int bufsize = -1; |
| FILE *fp; |
| object *f; |
| if (!newgetargs(args, "s|si", &name, &mode, &bufsize)) |
| return NULL; |
| BGN_SAVE |
| fp = popen(name, mode); |
| END_SAVE |
| if (fp == NULL) |
| return posix_error(); |
| f = newopenfileobject(fp, name, mode, pclose); |
| if (f != NULL) |
| setfilebufsize(f, bufsize); |
| return f; |
| } |
| #endif /* HAVE_POPEN */ |
| |
| #ifdef HAVE_SETUID |
| static object * |
| posix_setuid(self, args) |
| object *self; |
| object *args; |
| { |
| int uid; |
| if (!getargs(args, "i", &uid)) |
| return NULL; |
| if (setuid(uid) < 0) |
| return posix_error(); |
| INCREF(None); |
| return None; |
| } |
| #endif /* HAVE_SETUID */ |
| |
| #ifdef HAVE_SETGID |
| static object * |
| posix_setgid(self, args) |
| object *self; |
| object *args; |
| { |
| int gid; |
| if (!getargs(args, "i", &gid)) |
| return NULL; |
| if (setgid(gid) < 0) |
| return posix_error(); |
| INCREF(None); |
| return None; |
| } |
| #endif /* HAVE_SETGID */ |
| |
| #ifdef HAVE_WAITPID |
| static object * |
| posix_waitpid(self, args) |
| object *self; |
| object *args; |
| { |
| int pid, options, sts; |
| if (!getargs(args, "(ii)", &pid, &options)) |
| return NULL; |
| BGN_SAVE |
| pid = waitpid(pid, &sts, options); |
| END_SAVE |
| if (pid == -1) |
| return posix_error(); |
| else |
| return mkvalue("ii", pid, sts); |
| } |
| #endif /* HAVE_WAITPID */ |
| |
| #ifdef HAVE_WAIT |
| static object * |
| posix_wait(self, args) |
| object *self; |
| object *args; |
| { |
| int pid, sts; |
| BGN_SAVE |
| pid = wait(&sts); |
| END_SAVE |
| if (pid == -1) |
| return posix_error(); |
| else |
| return mkvalue("ii", pid, sts); |
| } |
| #endif |
| |
| static object * |
| posix_lstat(self, args) |
| object *self; |
| object *args; |
| { |
| #ifdef HAVE_LSTAT |
| return posix_do_stat(self, args, lstat); |
| #else /* !HAVE_LSTAT */ |
| return posix_do_stat(self, args, stat); |
| #endif /* !HAVE_LSTAT */ |
| } |
| |
| #ifdef HAVE_READLINK |
| static object * |
| posix_readlink(self, args) |
| object *self; |
| object *args; |
| { |
| char buf[MAXPATHLEN]; |
| char *path; |
| int n; |
| if (!getargs(args, "s", &path)) |
| return NULL; |
| BGN_SAVE |
| n = readlink(path, buf, (int) sizeof buf); |
| END_SAVE |
| if (n < 0) |
| return posix_error(); |
| return newsizedstringobject(buf, n); |
| } |
| #endif /* HAVE_READLINK */ |
| |
| #ifdef HAVE_SYMLINK |
| static object * |
| posix_symlink(self, args) |
| object *self; |
| object *args; |
| { |
| return posix_2str(args, symlink); |
| } |
| #endif /* HAVE_SYMLINK */ |
| |
| #ifdef HAVE_TIMES |
| #ifndef HZ |
| #define HZ 60 /* Universal constant :-) */ |
| #endif /* HZ */ |
| static object * |
| posix_times(self, args) |
| object *self; |
| object *args; |
| { |
| struct tms t; |
| clock_t c; |
| if (!getnoarg(args)) |
| return NULL; |
| errno = 0; |
| c = times(&t); |
| if (c == (clock_t) -1) |
| return posix_error(); |
| return mkvalue("ddddd", |
| (double)t.tms_utime / HZ, |
| (double)t.tms_stime / HZ, |
| (double)t.tms_cutime / HZ, |
| (double)t.tms_cstime / HZ, |
| (double)c / HZ); |
| } |
| #endif /* HAVE_TIMES */ |
| #if defined(NT) && !defined(HAVE_TIMES) |
| #define HAVE_TIMES /* so the method table will pick it up */ |
| static object * |
| posix_times(self, args) |
| object *self; |
| object *args; |
| { |
| FILETIME create, exit, kernel, user; |
| HANDLE hProc; |
| if (!getnoarg(args)) |
| return NULL; |
| hProc = GetCurrentProcess(); |
| GetProcessTimes(hProc,&create, &exit, &kernel, &user); |
| return mkvalue("ddddd", |
| (double)(kernel.dwHighDateTime*2E32+kernel.dwLowDateTime) / 2E6, |
| (double)(user.dwHighDateTime*2E32+user.dwLowDateTime) / 2E6, |
| (double)0, |
| (double)0, |
| (double)0); |
| } |
| #endif /* NT */ |
| |
| #ifdef HAVE_SETSID |
| static object * |
| posix_setsid(self, args) |
| object *self; |
| object *args; |
| { |
| if (!getnoarg(args)) |
| return NULL; |
| if (setsid() < 0) |
| return posix_error(); |
| INCREF(None); |
| return None; |
| } |
| #endif /* HAVE_SETSID */ |
| |
| #ifdef HAVE_SETPGID |
| static object * |
| posix_setpgid(self, args) |
| object *self; |
| object *args; |
| { |
| int pid, pgrp; |
| if (!getargs(args, "(ii)", &pid, &pgrp)) |
| return NULL; |
| if (setpgid(pid, pgrp) < 0) |
| return posix_error(); |
| INCREF(None); |
| return None; |
| } |
| #endif /* HAVE_SETPGID */ |
| |
| #ifdef HAVE_TCGETPGRP |
| static object * |
| posix_tcgetpgrp(self, args) |
| object *self; |
| object *args; |
| { |
| int fd, pgid; |
| if (!getargs(args, "i", &fd)) |
| return NULL; |
| pgid = tcgetpgrp(fd); |
| if (pgid < 0) |
| return posix_error(); |
| return newintobject((long)pgid); |
| } |
| #endif /* HAVE_TCGETPGRP */ |
| |
| #ifdef HAVE_TCSETPGRP |
| static object * |
| posix_tcsetpgrp(self, args) |
| object *self; |
| object *args; |
| { |
| int fd, pgid; |
| if (!getargs(args, "(ii)", &fd, &pgid)) |
| return NULL; |
| if (tcsetpgrp(fd, pgid) < 0) |
| return posix_error(); |
| INCREF(None); |
| return None; |
| } |
| #endif /* HAVE_TCSETPGRP */ |
| |
| /* Functions acting on file descriptors */ |
| |
| static object * |
| posix_open(self, args) |
| object *self; |
| object *args; |
| { |
| char *file; |
| int flag; |
| int mode = 0777; |
| int fd; |
| if (!getargs(args, "(si)", &file, &flag)) { |
| err_clear(); |
| if (!getargs(args, "(sii)", &file, &flag, &mode)) |
| return NULL; |
| } |
| BGN_SAVE |
| fd = open(file, flag, mode); |
| END_SAVE |
| if (fd < 0) |
| return posix_error(); |
| return newintobject((long)fd); |
| } |
| |
| static object * |
| posix_close(self, args) |
| object *self; |
| object *args; |
| { |
| int fd, res; |
| if (!getargs(args, "i", &fd)) |
| return NULL; |
| BGN_SAVE |
| res = close(fd); |
| END_SAVE |
| if (res < 0) |
| return posix_error(); |
| INCREF(None); |
| return None; |
| } |
| |
| static object * |
| posix_dup(self, args) |
| object *self; |
| object *args; |
| { |
| int fd; |
| if (!getargs(args, "i", &fd)) |
| return NULL; |
| BGN_SAVE |
| fd = dup(fd); |
| END_SAVE |
| if (fd < 0) |
| return posix_error(); |
| return newintobject((long)fd); |
| } |
| |
| static object * |
| posix_dup2(self, args) |
| object *self; |
| object *args; |
| { |
| int fd, fd2, res; |
| if (!getargs(args, "(ii)", &fd, &fd2)) |
| return NULL; |
| BGN_SAVE |
| res = dup2(fd, fd2); |
| END_SAVE |
| if (res < 0) |
| return posix_error(); |
| INCREF(None); |
| return None; |
| } |
| |
| static object * |
| posix_lseek(self, args) |
| object *self; |
| object *args; |
| { |
| int fd, how; |
| long pos, res; |
| if (!getargs(args, "(ili)", &fd, &pos, &how)) |
| return NULL; |
| #ifdef SEEK_SET |
| /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */ |
| switch (how) { |
| case 0: how = SEEK_SET; break; |
| case 1: how = SEEK_CUR; break; |
| case 2: how = SEEK_END; break; |
| } |
| #endif /* SEEK_END */ |
| BGN_SAVE |
| res = lseek(fd, pos, how); |
| END_SAVE |
| if (res < 0) |
| return posix_error(); |
| return newintobject(res); |
| } |
| |
| static object * |
| posix_read(self, args) |
| object *self; |
| object *args; |
| { |
| int fd, size; |
| object *buffer; |
| if (!getargs(args, "(ii)", &fd, &size)) |
| return NULL; |
| buffer = newsizedstringobject((char *)NULL, size); |
| if (buffer == NULL) |
| return NULL; |
| BGN_SAVE |
| size = read(fd, getstringvalue(buffer), size); |
| END_SAVE |
| if (size < 0) { |
| DECREF(buffer); |
| return posix_error(); |
| } |
| resizestring(&buffer, size); |
| return buffer; |
| } |
| |
| static object * |
| posix_write(self, args) |
| object *self; |
| object *args; |
| { |
| int fd, size; |
| char *buffer; |
| if (!getargs(args, "(is#)", &fd, &buffer, &size)) |
| return NULL; |
| BGN_SAVE |
| size = write(fd, buffer, size); |
| END_SAVE |
| if (size < 0) |
| return posix_error(); |
| return newintobject((long)size); |
| } |
| |
| static object * |
| posix_fstat(self, args) |
| object *self; |
| object *args; |
| { |
| int fd; |
| struct stat st; |
| int res; |
| if (!getargs(args, "i", &fd)) |
| return NULL; |
| BGN_SAVE |
| res = fstat(fd, &st); |
| END_SAVE |
| if (res != 0) |
| return posix_error(); |
| return mkvalue("(llllllllll)", |
| (long)st.st_mode, |
| (long)st.st_ino, |
| (long)st.st_dev, |
| (long)st.st_nlink, |
| (long)st.st_uid, |
| (long)st.st_gid, |
| (long)st.st_size, |
| (long)st.st_atime, |
| (long)st.st_mtime, |
| (long)st.st_ctime); |
| } |
| |
| static object * |
| posix_fdopen(self, args) |
| object *self; |
| object *args; |
| { |
| extern int fclose PROTO((FILE *)); |
| int fd; |
| char *mode = "r"; |
| int bufsize = -1; |
| FILE *fp; |
| object *f; |
| if (!newgetargs(args, "i|si", &fd, &mode, &bufsize)) |
| return NULL; |
| BGN_SAVE |
| fp = fdopen(fd, mode); |
| END_SAVE |
| if (fp == NULL) |
| return posix_error(); |
| f = newopenfileobject(fp, "(fdopen)", mode, fclose); |
| if (f != NULL) |
| setfilebufsize(f, bufsize); |
| return f; |
| } |
| |
| #ifdef HAVE_PIPE |
| static object * |
| posix_pipe(self, args) |
| object *self; |
| object *args; |
| { |
| #if !defined(NT) |
| int fds[2]; |
| int res; |
| if (!getargs(args, "")) |
| return NULL; |
| BGN_SAVE |
| res = pipe(fds); |
| END_SAVE |
| if (res != 0) |
| return posix_error(); |
| return mkvalue("(ii)", fds[0], fds[1]); |
| #else /* NT */ |
| HANDLE read, write; |
| BOOL ok; |
| if (!getargs(args, "")) |
| return NULL; |
| BGN_SAVE |
| ok = CreatePipe( &read, &write, NULL, 0); |
| END_SAVE |
| if (!ok) |
| return posix_error(); |
| return mkvalue("(ii)", read, write); |
| #endif /* NT */ |
| } |
| #endif /* HAVE_PIPE */ |
| |
| #ifdef HAVE_MKFIFO |
| static object * |
| posix_mkfifo(self, args) |
| object *self; |
| object *args; |
| { |
| char *file; |
| int mode = 0666; |
| int res; |
| if (!newgetargs(args, "s|i", &file, &mode)) |
| return NULL; |
| BGN_SAVE |
| res = mkfifo(file, mode); |
| END_SAVE |
| if (res < 0) |
| return posix_error(); |
| INCREF(None); |
| return None; |
| } |
| #endif |
| |
| #ifdef HAVE_FTRUNCATE |
| static object * |
| posix_ftruncate(self, args) |
| object *self; /* Not used */ |
| object *args; |
| { |
| int fd; |
| long length; |
| int res; |
| |
| if (!getargs(args, "(il)", &fd, &length)) |
| return NULL; |
| |
| BGN_SAVE |
| res = ftruncate(fd, length); |
| END_SAVE |
| if (res < 0) { |
| err_errno(IOError); |
| return NULL; |
| } |
| INCREF(None); |
| return None; |
| } |
| #endif |
| |
| static struct methodlist posix_methods[] = { |
| {"chdir", posix_chdir}, |
| {"chmod", posix_chmod}, |
| #ifdef HAVE_CHOWN |
| {"chown", posix_chown}, |
| #endif /* HAVE_CHOWN */ |
| #ifdef HAVE_GETCWD |
| {"getcwd", posix_getcwd}, |
| #endif |
| #ifdef HAVE_LINK |
| {"link", posix_link}, |
| #endif /* HAVE_LINK */ |
| {"listdir", posix_listdir}, |
| {"lstat", posix_lstat}, |
| {"mkdir", posix_mkdir, 1}, |
| #ifdef HAVE_NICE |
| {"nice", posix_nice}, |
| #endif /* HAVE_NICE */ |
| #ifdef HAVE_READLINK |
| {"readlink", posix_readlink}, |
| #endif /* HAVE_READLINK */ |
| {"rename", posix_rename}, |
| {"rmdir", posix_rmdir}, |
| {"stat", posix_stat}, |
| #ifdef HAVE_SYMLINK |
| {"symlink", posix_symlink}, |
| #endif /* HAVE_SYMLINK */ |
| #ifdef HAVE_SYSTEM |
| {"system", posix_system}, |
| #endif |
| {"umask", posix_umask}, |
| #ifdef HAVE_UNAME |
| {"uname", posix_uname}, |
| #endif /* HAVE_UNAME */ |
| {"unlink", posix_unlink}, |
| {"remove", posix_unlink}, |
| {"utime", posix_utime}, |
| #ifdef HAVE_TIMES |
| {"times", posix_times}, |
| #endif /* HAVE_TIMES */ |
| {"_exit", posix__exit}, |
| #ifdef HAVE_EXECV |
| {"execv", posix_execv}, |
| {"execve", posix_execve}, |
| #endif /* HAVE_EXECV */ |
| #ifdef HAVE_FORK |
| {"fork", posix_fork}, |
| #endif /* HAVE_FORK */ |
| #ifdef HAVE_GETEGID |
| {"getegid", posix_getegid}, |
| #endif /* HAVE_GETEGID */ |
| #ifdef HAVE_GETEUID |
| {"geteuid", posix_geteuid}, |
| #endif /* HAVE_GETEUID */ |
| #ifdef HAVE_GETGID |
| {"getgid", posix_getgid}, |
| #endif /* HAVE_GETGID */ |
| {"getpid", posix_getpid}, |
| #ifdef HAVE_GETPGRP |
| {"getpgrp", posix_getpgrp}, |
| #endif /* HAVE_GETPGRP */ |
| #ifdef HAVE_GETPPID |
| {"getppid", posix_getppid}, |
| #endif /* HAVE_GETPPID */ |
| #ifdef HAVE_GETUID |
| {"getuid", posix_getuid}, |
| #endif /* HAVE_GETUID */ |
| #ifdef HAVE_KILL |
| {"kill", posix_kill}, |
| #endif /* HAVE_KILL */ |
| #ifdef HAVE_POPEN |
| {"popen", posix_popen, 1}, |
| #endif /* HAVE_POPEN */ |
| #ifdef HAVE_SETUID |
| {"setuid", posix_setuid}, |
| #endif /* HAVE_SETUID */ |
| #ifdef HAVE_SETGID |
| {"setgid", posix_setgid}, |
| #endif /* HAVE_SETGID */ |
| #ifdef HAVE_SETPGRP |
| {"setpgrp", posix_setpgrp}, |
| #endif /* HAVE_SETPGRP */ |
| #ifdef HAVE_WAIT |
| {"wait", posix_wait}, |
| #endif /* HAVE_WAIT */ |
| #ifdef HAVE_WAITPID |
| {"waitpid", posix_waitpid}, |
| #endif /* HAVE_WAITPID */ |
| #ifdef HAVE_SETSID |
| {"setsid", posix_setsid}, |
| #endif /* HAVE_SETSID */ |
| #ifdef HAVE_SETPGID |
| {"setpgid", posix_setpgid}, |
| #endif /* HAVE_SETPGID */ |
| #ifdef HAVE_TCGETPGRP |
| {"tcgetpgrp", posix_tcgetpgrp}, |
| #endif /* HAVE_TCGETPGRP */ |
| #ifdef HAVE_TCSETPGRP |
| {"tcsetpgrp", posix_tcsetpgrp}, |
| #endif /* HAVE_TCSETPGRP */ |
| {"open", posix_open}, |
| {"close", posix_close}, |
| {"dup", posix_dup}, |
| {"dup2", posix_dup2}, |
| {"lseek", posix_lseek}, |
| {"read", posix_read}, |
| {"write", posix_write}, |
| {"fstat", posix_fstat}, |
| {"fdopen", posix_fdopen, 1}, |
| #ifdef HAVE_PIPE |
| {"pipe", posix_pipe}, |
| #endif |
| #ifdef HAVE_MKFIFO |
| {"mkfifo", posix_mkfifo, 1}, |
| #endif |
| #ifdef HAVE_FTRUNCATE |
| {"ftruncate", posix_ftruncate, 1}, |
| #endif |
| {NULL, NULL} /* Sentinel */ |
| }; |
| |
| |
| #ifdef NT |
| void |
| initnt() |
| { |
| object *m, *d, *v; |
| |
| m = initmodule("nt", posix_methods); |
| d = getmoduledict(m); |
| |
| /* Initialize nt.environ dictionary */ |
| v = convertenviron(); |
| if (v == NULL || dictinsert(d, "environ", v) != 0) |
| fatal("can't define nt.environ"); |
| DECREF(v); |
| |
| /* Initialize nt.error exception */ |
| PosixError = newstringobject("nt.error"); |
| if (PosixError == NULL || dictinsert(d, "error", PosixError) != 0) |
| fatal("can't define nt.error"); |
| } |
| #else /* !_MSC_VER */ |
| void |
| initposix() |
| { |
| object *m, *d, *v; |
| |
| m = initmodule("posix", posix_methods); |
| d = getmoduledict(m); |
| |
| /* Initialize posix.environ dictionary */ |
| v = convertenviron(); |
| if (v == NULL || dictinsert(d, "environ", v) != 0) |
| fatal("can't define posix.environ"); |
| DECREF(v); |
| |
| #ifdef WNOHANG |
| /* Export WNOHANG symbol */ |
| v = newintobject((long)WNOHANG); |
| if (v == NULL || dictinsert(d, "WNOHANG", v) != 0) |
| fatal("can't define posix.WNOHANG"); |
| DECREF(v); |
| #endif |
| |
| /* Initialize posix.error exception */ |
| PosixError = newstringobject("posix.error"); |
| if (PosixError == NULL || dictinsert(d, "error", PosixError) != 0) |
| fatal("can't define posix.error"); |
| } |
| #endif /* !_MSC_VER */ |