posixmodule.c revision a4916fa54f007ec9f8b376e087b6a4493122d277
1/*********************************************************** 2Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam, 3The Netherlands. 4 5 All Rights Reserved 6 7Permission to use, copy, modify, and distribute this software and its 8documentation for any purpose and without fee is hereby granted, 9provided that the above copyright notice appear in all copies and that 10both that copyright notice and this permission notice appear in 11supporting documentation, and that the names of Stichting Mathematisch 12Centrum or CWI not be used in advertising or publicity pertaining to 13distribution of the software without specific, written prior permission. 14 15STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO 16THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 17FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE 18FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 19WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 20ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 21OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 22 23******************************************************************/ 24 25/* POSIX module implementation */ 26 27/* This file is also used for Windows NT and MS-Win. In that case the module 28 actually calls itself 'nt', not 'posix', and a few functions are 29 either unimplemented or implemented differently. The source 30 assumes that for Windows NT, the macro 'NT' is defined independent 31 of the compiler used. Different compilers define their own feature 32 test macro, e.g. '__BORLANDC__' or '_MSC_VER'. */ 33 34/* See also ../Dos/dosmodule.c */ 35 36#include "allobjects.h" 37#include "modsupport.h" 38#include "ceval.h" 39 40#include <string.h> 41#include <errno.h> 42#include <sys/types.h> 43#include <sys/stat.h> 44#ifdef HAVE_SYS_WAIT_H 45#include <sys/wait.h> /* For WNOHANG */ 46#endif 47 48#include "mytime.h" /* For clock_t on some systems */ 49 50#ifdef HAVE_FCNTL_H 51#include <fcntl.h> 52#endif /* HAVE_FCNTL_H */ 53 54/* Various compilers have only certain posix functions */ 55#ifdef __WATCOMC__ /* Watcom compiler */ 56#define HAVE_GETCWD 1 57#define HAVE_OPENDIR 1 58#define HAVE_SYSTEM 1 59#if defined(__OS2__) 60#define HAVE_EXECV 1 61#define HAVE_WAIT 1 62#endif 63#include <process.h> 64#else 65#ifdef __BORLANDC__ /* Borland compiler */ 66#define HAVE_EXECV 1 67#define HAVE_GETCWD 1 68#define HAVE_GETEGID 1 69#define HAVE_GETEUID 1 70#define HAVE_GETGID 1 71#define HAVE_GETPPID 1 72#define HAVE_GETUID 1 73#define HAVE_KILL 1 74#define HAVE_OPENDIR 1 75#define HAVE_PIPE 1 76#define HAVE_POPEN 1 77#define HAVE_SYSTEM 1 78#define HAVE_WAIT 1 79#else 80#ifdef _MSC_VER /* Microsoft compiler */ 81#ifdef NT 82#define HAVE_EXECV 1 83#define HAVE_PIPE 1 84#define HAVE_POPEN 1 85#define HAVE_SYSTEM 1 86#else /* 16-bit Windows */ 87#endif /* NT */ 88#else /* all other compilers */ 89/* Unix functions that the configure script doesn't check for */ 90#define HAVE_EXECV 1 91#define HAVE_FORK 1 92#define HAVE_GETCWD 1 93#define HAVE_GETEGID 1 94#define HAVE_GETEUID 1 95#define HAVE_GETGID 1 96#define HAVE_GETPPID 1 97#define HAVE_GETUID 1 98#define HAVE_KILL 1 99#define HAVE_OPENDIR 1 100#define HAVE_PIPE 1 101#define HAVE_POPEN 1 102#define HAVE_SYSTEM 1 103#define HAVE_WAIT 1 104#endif /* _MSC_VER */ 105#endif /* __BORLANDC__ */ 106#endif /* ! __WATCOMC__ */ 107 108#ifndef _MSC_VER 109 110#ifdef HAVE_UNISTD_H 111#include <unistd.h> 112#endif 113 114#ifdef NeXT 115/* NeXT's <unistd.h> and <utime.h> aren't worth much */ 116#undef HAVE_UNISTD_H 117#undef HAVE_UTIME_H 118/* #undef HAVE_GETCWD */ 119#endif 120 121#ifdef HAVE_UNISTD_H 122/* XXX These are for SunOS4.1.3 but shouldn't hurt elsewhere */ 123extern int rename(); 124extern int pclose(); 125extern int lstat(); 126extern int symlink(); 127#else /* !HAVE_UNISTD_H */ 128#if defined(__WATCOMC__) 129extern int mkdir PROTO((const char *)); 130#else 131extern int mkdir PROTO((const char *, mode_t)); 132#endif 133extern int chdir PROTO((const char *)); 134extern int rmdir PROTO((const char *)); 135extern int chmod PROTO((const char *, mode_t)); 136extern int chown PROTO((const char *, uid_t, gid_t)); 137extern char *getcwd PROTO((char *, int)); 138extern char *strerror PROTO((int)); 139extern int link PROTO((const char *, const char *)); 140extern int rename PROTO((const char *, const char *)); 141extern int stat PROTO((const char *, struct stat *)); 142extern int unlink PROTO((const char *)); 143extern int pclose PROTO((FILE *)); 144#ifdef HAVE_SYMLINK 145extern int symlink PROTO((const char *, const char *)); 146#endif /* HAVE_SYMLINK */ 147#ifdef HAVE_LSTAT 148extern int lstat PROTO((const char *, struct stat *)); 149#endif /* HAVE_LSTAT */ 150#endif /* !HAVE_UNISTD_H */ 151 152#endif /* !_MSC_VER */ 153 154#ifdef HAVE_UTIME_H 155#include <utime.h> 156#endif /* HAVE_UTIME_H */ 157 158#ifdef HAVE_SYS_UTIME_H 159#include <sys/utime.h> 160#define HAVE_UTIME_H /* pretend we do for the rest of this file */ 161#endif /* HAVE_SYS_UTIME_H */ 162 163#ifdef HAVE_SYS_TIMES_H 164#include <sys/times.h> 165#endif /* HAVE_SYS_TIMES_H */ 166 167#ifdef HAVE_SYS_PARAM_H 168#include <sys/param.h> 169#endif /* HAVE_SYS_PARAM_H */ 170 171#ifdef HAVE_SYS_UTSNAME_H 172#include <sys/utsname.h> 173#endif /* HAVE_SYS_UTSNAME_H */ 174 175#ifndef MAXPATHLEN 176#define MAXPATHLEN 1024 177#endif /* MAXPATHLEN */ 178 179#ifdef HAVE_DIRENT_H 180#include <dirent.h> 181#define NAMLEN(dirent) strlen((dirent)->d_name) 182#else 183#ifdef __WATCOMC__ 184#include <direct.h> 185#define NAMLEN(dirent) strlen((dirent)->d_name) 186#else 187#define dirent direct 188#define NAMLEN(dirent) (dirent)->d_namlen 189#endif 190#ifdef HAVE_SYS_NDIR_H 191#include <sys/ndir.h> 192#endif 193#ifdef HAVE_SYS_DIR_H 194#include <sys/dir.h> 195#endif 196#ifdef HAVE_NDIR_H 197#include <ndir.h> 198#endif 199#endif 200 201#ifdef _MSC_VER 202#include <direct.h> 203#include <io.h> 204#include <process.h> 205#include <windows.h> 206#ifdef NT 207#define popen _popen 208#define pclose _pclose 209#else /* 16-bit Windows */ 210#include <dos.h> 211#include <ctype.h> 212#endif /* NT */ 213#endif /* _MSC_VER */ 214 215#ifdef OS2 216#include <io.h> 217#endif /* OS2 */ 218 219/* Return a dictionary corresponding to the POSIX environment table */ 220 221#if !defined(_MSC_VER) && !defined(__WATCOMC__) 222extern char **environ; 223#endif /* !_MSC_VER */ 224 225static object * 226convertenviron() 227{ 228 object *d; 229 char **e; 230 d = newdictobject(); 231 if (d == NULL) 232 return NULL; 233 if (environ == NULL) 234 return d; 235 /* XXX This part ignores errors */ 236 for (e = environ; *e != NULL; e++) { 237 object *v; 238 char *p = strchr(*e, '='); 239 if (p == NULL) 240 continue; 241 v = newstringobject(p+1); 242 if (v == NULL) 243 continue; 244 *p = '\0'; 245 (void) dictinsert(d, *e, v); 246 *p = '='; 247 DECREF(v); 248 } 249 return d; 250} 251 252 253static object *PosixError; /* Exception posix.error */ 254 255/* Set a POSIX-specific error from errno, and return NULL */ 256 257static object * posix_error() 258{ 259 return err_errno(PosixError); 260} 261 262 263/* POSIX generic methods */ 264 265static object * 266posix_1str(args, func) 267 object *args; 268 int (*func) FPROTO((const char *)); 269{ 270 char *path1; 271 int res; 272 if (!getargs(args, "s", &path1)) 273 return NULL; 274 BGN_SAVE 275 res = (*func)(path1); 276 END_SAVE 277 if (res < 0) 278 return posix_error(); 279 INCREF(None); 280 return None; 281} 282 283static object * 284posix_2str(args, func) 285 object *args; 286 int (*func) FPROTO((const char *, const char *)); 287{ 288 char *path1, *path2; 289 int res; 290 if (!getargs(args, "(ss)", &path1, &path2)) 291 return NULL; 292 BGN_SAVE 293 res = (*func)(path1, path2); 294 END_SAVE 295 if (res < 0) 296 return posix_error(); 297 INCREF(None); 298 return None; 299} 300 301static object * 302posix_strint(args, func) 303 object *args; 304 int (*func) FPROTO((const char *, int)); 305{ 306 char *path; 307 int i; 308 int res; 309 if (!getargs(args, "(si)", &path, &i)) 310 return NULL; 311 BGN_SAVE 312 res = (*func)(path, i); 313 END_SAVE 314 if (res < 0) 315 return posix_error(); 316 INCREF(None); 317 return None; 318} 319 320static object * 321posix_strintint(args, func) 322 object *args; 323 int (*func) FPROTO((const char *, int, int)); 324{ 325 char *path; 326 int i,i2; 327 int res; 328 if (!getargs(args, "(sii)", &path, &i, &i2)) 329 return NULL; 330 BGN_SAVE 331 res = (*func)(path, i, i2); 332 END_SAVE 333 if (res < 0) 334 return posix_error(); 335 INCREF(None); 336 return None; 337} 338 339static object * 340posix_do_stat(self, args, statfunc) 341 object *self; 342 object *args; 343 int (*statfunc) FPROTO((const char *, struct stat *)); 344{ 345 struct stat st; 346 char *path; 347 int res; 348 if (!getargs(args, "s", &path)) 349 return NULL; 350 BGN_SAVE 351 res = (*statfunc)(path, &st); 352 END_SAVE 353 if (res != 0) 354 return posix_error(); 355 return mkvalue("(llllllllll)", 356 (long)st.st_mode, 357 (long)st.st_ino, 358 (long)st.st_dev, 359 (long)st.st_nlink, 360 (long)st.st_uid, 361 (long)st.st_gid, 362 (long)st.st_size, 363 (long)st.st_atime, 364 (long)st.st_mtime, 365 (long)st.st_ctime); 366} 367 368 369/* POSIX methods */ 370 371static object * 372posix_chdir(self, args) 373 object *self; 374 object *args; 375{ 376 return posix_1str(args, chdir); 377} 378 379static object * 380posix_chmod(self, args) 381 object *self; 382 object *args; 383{ 384 return posix_strint(args, chmod); 385} 386 387#ifdef HAVE_CHOWN 388static object * 389posix_chown(self, args) 390 object *self; 391 object *args; 392{ 393 return posix_strintint(args, chown); 394} 395#endif /* HAVE_CHOWN */ 396 397#ifdef HAVE_GETCWD 398static object * 399posix_getcwd(self, args) 400 object *self; 401 object *args; 402{ 403 char buf[1026]; 404 char *res; 405 if (!getnoarg(args)) 406 return NULL; 407 BGN_SAVE 408 res = getcwd(buf, sizeof buf); 409 END_SAVE 410 if (res == NULL) 411 return posix_error(); 412 return newstringobject(buf); 413} 414#endif 415 416#ifdef HAVE_LINK 417static object * 418posix_link(self, args) 419 object *self; 420 object *args; 421{ 422 return posix_2str(args, link); 423} 424#endif /* HAVE_LINK */ 425 426static object * 427posix_listdir(self, args) 428 object *self; 429 object *args; 430{ 431#if defined(NT) && !defined(HAVE_OPENDIR) 432 433 char *name; 434 int len; 435 object *d, *v; 436 HANDLE hFindFile; 437 WIN32_FIND_DATA FileData; 438 char namebuf[MAX_PATH+5]; 439 440 if (!getargs(args, "s#", &name, &len)) 441 return NULL; 442 if (len >= MAX_PATH) { 443 err_setstr(ValueError, "path too long"); 444 return NULL; 445 } 446 strcpy(namebuf, name); 447 if (namebuf[len-1] != '/' && namebuf[len-1] != '\\') 448 namebuf[len++] = '/'; 449 strcpy(namebuf + len, "*.*"); 450 451 if ((d = newlistobject(0)) == NULL) 452 return NULL; 453 454 hFindFile = FindFirstFile(namebuf, &FileData); 455 if (hFindFile == INVALID_HANDLE_VALUE) { 456 errno = GetLastError(); 457 return posix_error(); 458 } 459 do { 460 if (FileData.cFileName[0] == '.' && 461 (FileData.cFileName[1] == '\0' || 462 FileData.cFileName[1] == '.' && 463 FileData.cFileName[2] == '\0')) 464 continue; 465 v = newstringobject(FileData.cFileName); 466 if (v == NULL) { 467 DECREF(d); 468 d = NULL; 469 break; 470 } 471 if (addlistitem(d, v) != 0) { 472 DECREF(v); 473 DECREF(d); 474 d = NULL; 475 break; 476 } 477 DECREF(v); 478 } while (FindNextFile(hFindFile, &FileData) == TRUE); 479 480 if (FindClose(hFindFile) == FALSE) { 481 errno = GetLastError(); 482 return posix_error(); 483 } 484 485 return d; 486 487#else /* !NT */ 488#ifdef _MSC_VER /* 16-bit Windows */ 489 490#ifndef MAX_PATH 491#define MAX_PATH 250 492#endif 493 char *name, *pt; 494 int len; 495 object *d, *v; 496 char namebuf[MAX_PATH+5]; 497 struct _find_t ep; 498 499 if (!getargs(args, "s#", &name, &len)) 500 return NULL; 501 if (len >= MAX_PATH) { 502 err_setstr(ValueError, "path too long"); 503 return NULL; 504 } 505 strcpy(namebuf, name); 506 for (pt = namebuf; *pt; pt++) 507 if (*pt == '/') 508 *pt = '\\'; 509 if (namebuf[len-1] != '\\') 510 namebuf[len++] = '\\'; 511 strcpy(namebuf + len, "*.*"); 512 513 if ((d = newlistobject(0)) == NULL) 514 return NULL; 515 516 if (_dos_findfirst(namebuf, _A_RDONLY | 517 _A_HIDDEN | _A_SYSTEM | _A_SUBDIR, &ep) != 0){ 518 errno = ENOENT; 519 return posix_error(); 520 } 521 do { 522 if (ep.name[0] == '.' && 523 (ep.name[1] == '\0' || 524 ep.name[1] == '.' && 525 ep.name[2] == '\0')) 526 continue; 527 strcpy(namebuf, ep.name); 528 for (pt = namebuf; *pt; pt++) 529 if (isupper(*pt)) 530 *pt = tolower(*pt); 531 v = newstringobject(namebuf); 532 if (v == NULL) { 533 DECREF(d); 534 d = NULL; 535 break; 536 } 537 if (addlistitem(d, v) != 0) { 538 DECREF(v); 539 DECREF(d); 540 d = NULL; 541 break; 542 } 543 DECREF(v); 544 } while (_dos_findnext(&ep) == 0); 545 546 return d; 547 548#else 549 550 char *name; 551 object *d, *v; 552 DIR *dirp; 553 struct dirent *ep; 554 if (!getargs(args, "s", &name)) 555 return NULL; 556 BGN_SAVE 557 if ((dirp = opendir(name)) == NULL) { 558 RET_SAVE 559 return posix_error(); 560 } 561 if ((d = newlistobject(0)) == NULL) { 562 closedir(dirp); 563 RET_SAVE 564 return NULL; 565 } 566 while ((ep = readdir(dirp)) != NULL) { 567 if (ep->d_name[0] == '.' && 568 (NAMLEN(ep) == 1 || 569 ep->d_name[1] == '.' && NAMLEN(ep) == 2)) 570 continue; 571 v = newsizedstringobject(ep->d_name, NAMLEN(ep)); 572 if (v == NULL) { 573 DECREF(d); 574 d = NULL; 575 break; 576 } 577 if (addlistitem(d, v) != 0) { 578 DECREF(v); 579 DECREF(d); 580 d = NULL; 581 break; 582 } 583 DECREF(v); 584 } 585 closedir(dirp); 586 END_SAVE 587 588 return d; 589 590#endif /* !_MSC_VER */ 591#endif /* !NT */ 592} 593 594static object * 595posix_mkdir(self, args) 596 object *self; 597 object *args; 598{ 599 int res; 600 char *path; 601 int mode = 0777; 602 if (!newgetargs(args, "s|i", &path, &mode)) 603 return NULL; 604 BGN_SAVE 605#if defined(__WATCOMC__) 606 res = mkdir(path); 607#else 608 res = mkdir(path, mode); 609#endif 610 END_SAVE 611 if (res < 0) 612 return posix_error(); 613 INCREF(None); 614 return None; 615} 616 617#ifdef HAVE_NICE 618static object * 619posix_nice(self, args) 620 object *self; 621 object *args; 622{ 623 int increment, value; 624 625 if (!getargs(args, "i", &increment)) 626 return NULL; 627 value = nice(increment); 628 if (value == -1) 629 return posix_error(); 630 return newintobject((long) value); 631} 632#endif /* HAVE_NICE */ 633 634static object * 635posix_rename(self, args) 636 object *self; 637 object *args; 638{ 639 return posix_2str(args, rename); 640} 641 642static object * 643posix_rmdir(self, args) 644 object *self; 645 object *args; 646{ 647 return posix_1str(args, rmdir); 648} 649 650static object * 651posix_stat(self, args) 652 object *self; 653 object *args; 654{ 655 return posix_do_stat(self, args, stat); 656} 657 658#ifdef HAVE_SYSTEM 659static object * 660posix_system(self, args) 661 object *self; 662 object *args; 663{ 664 char *command; 665 long sts; 666 if (!getargs(args, "s", &command)) 667 return NULL; 668 BGN_SAVE 669 sts = system(command); 670 END_SAVE 671 return newintobject(sts); 672} 673#endif 674 675static object * 676posix_umask(self, args) 677 object *self; 678 object *args; 679{ 680 int i; 681 if (!getintarg(args, &i)) 682 return NULL; 683 i = umask(i); 684 if (i < 0) 685 return posix_error(); 686 return newintobject((long)i); 687} 688 689static object * 690posix_unlink(self, args) 691 object *self; 692 object *args; 693{ 694 return posix_1str(args, unlink); 695} 696 697#ifdef HAVE_UNAME 698static object * 699posix_uname(self, args) 700 object *self; 701 object *args; 702{ 703 struct utsname u; 704 object *v; 705 int res; 706 if (!getnoarg(args)) 707 return NULL; 708 BGN_SAVE 709 res = uname(&u); 710 END_SAVE 711 if (res < 0) 712 return posix_error(); 713 return mkvalue("(sssss)", 714 u.sysname, 715 u.nodename, 716 u.release, 717 u.version, 718 u.machine); 719} 720#endif /* HAVE_UNAME */ 721 722static object * 723posix_utime(self, args) 724 object *self; 725 object *args; 726{ 727 char *path; 728 long atime, mtime; 729 int res; 730 731#ifdef HAVE_UTIME_H 732 struct utimbuf buf; 733#define ATIME buf.actime 734#define MTIME buf.modtime 735#define UTIME_ARG &buf 736#else /* HAVE_UTIME_H */ 737 time_t buf[2]; 738#define ATIME buf[0] 739#define MTIME buf[1] 740#define UTIME_ARG buf 741#endif /* HAVE_UTIME_H */ 742 743 if (!getargs(args, "(s(ll))", &path, &atime, &mtime)) 744 return NULL; 745 ATIME = atime; 746 MTIME = mtime; 747 BGN_SAVE 748 res = utime(path, UTIME_ARG); 749 END_SAVE 750 if (res < 0) 751 return posix_error(); 752 INCREF(None); 753 return None; 754#undef UTIME_ARG 755#undef ATIME 756#undef MTIME 757} 758 759 760/* Process operations */ 761 762static object * 763posix__exit(self, args) 764 object *self; 765 object *args; 766{ 767 int sts; 768 if (!getintarg(args, &sts)) 769 return NULL; 770 _exit(sts); 771 /* NOTREACHED */ 772} 773 774#ifdef HAVE_EXECV 775static object * 776posix_execv(self, args) 777 object *self; 778 object *args; 779{ 780 char *path; 781 object *argv; 782 char **argvlist; 783 int i, argc; 784 object *(*getitem) PROTO((object *, int)); 785 786 /* execv has two arguments: (path, argv), where 787 argv is a list or tuple of strings. */ 788 789 if (!getargs(args, "(sO)", &path, &argv)) 790 return NULL; 791 if (is_listobject(argv)) { 792 argc = getlistsize(argv); 793 getitem = getlistitem; 794 } 795 else if (is_tupleobject(argv)) { 796 argc = gettuplesize(argv); 797 getitem = gettupleitem; 798 } 799 else { 800 badarg: 801 err_badarg(); 802 return NULL; 803 } 804 805 argvlist = NEW(char *, argc+1); 806 if (argvlist == NULL) 807 return NULL; 808 for (i = 0; i < argc; i++) { 809 if (!getargs((*getitem)(argv, i), "s", &argvlist[i])) { 810 DEL(argvlist); 811 goto badarg; 812 } 813 } 814 argvlist[argc] = NULL; 815 816#ifdef BAD_EXEC_PROTOTYPES 817 execv(path, (const char **) argvlist); 818#else /* BAD_EXEC_PROTOTYPES */ 819 execv(path, argvlist); 820#endif /* BAD_EXEC_PROTOTYPES */ 821 822 /* If we get here it's definitely an error */ 823 824 DEL(argvlist); 825 return posix_error(); 826} 827 828static object * 829posix_execve(self, args) 830 object *self; 831 object *args; 832{ 833 char *path; 834 object *argv, *env; 835 char **argvlist; 836 char **envlist; 837 object *key, *val; 838 int i, pos, argc, envc; 839 object *(*getitem) PROTO((object *, int)); 840 841 /* execve has three arguments: (path, argv, env), where 842 argv is a list or tuple of strings and env is a dictionary 843 like posix.environ. */ 844 845 if (!getargs(args, "(sOO)", &path, &argv, &env)) 846 return NULL; 847 if (is_listobject(argv)) { 848 argc = getlistsize(argv); 849 getitem = getlistitem; 850 } 851 else if (is_tupleobject(argv)) { 852 argc = gettuplesize(argv); 853 getitem = gettupleitem; 854 } 855 else { 856 err_setstr(TypeError, "argv must be tuple or list"); 857 return NULL; 858 } 859 if (!is_dictobject(env)) { 860 err_setstr(TypeError, "env must be dictionary"); 861 return NULL; 862 } 863 864 argvlist = NEW(char *, argc+1); 865 if (argvlist == NULL) { 866 err_nomem(); 867 return NULL; 868 } 869 for (i = 0; i < argc; i++) { 870 if (!getargs((*getitem)(argv, i), 871 "s;argv must be list of strings", 872 &argvlist[i])) { 873 goto fail_1; 874 } 875 } 876 argvlist[argc] = NULL; 877 878 i = getmappingsize(env); 879 envlist = NEW(char *, i + 1); 880 if (envlist == NULL) { 881 err_nomem(); 882 goto fail_1; 883 } 884 pos = 0; 885 envc = 0; 886 while (mappinggetnext(env, &pos, &key, &val)) { 887 char *p, *k, *v; 888 if (!getargs(key, "s;non-string key in env", &k) || 889 !getargs(val, "s;non-string value in env", &v)) { 890 goto fail_2; 891 } 892 p = NEW(char, getstringsize(key) + getstringsize(val) + 2); 893 if (p == NULL) { 894 err_nomem(); 895 goto fail_2; 896 } 897 sprintf(p, "%s=%s", k, v); 898 envlist[envc++] = p; 899 } 900 envlist[envc] = 0; 901 902 903#ifdef BAD_EXEC_PROTOTYPES 904 execve(path, (const char **)argvlist, envlist); 905#else /* BAD_EXEC_PROTOTYPES */ 906 execve(path, argvlist, envlist); 907#endif /* BAD_EXEC_PROTOTYPES */ 908 909 /* If we get here it's definitely an error */ 910 911 (void) posix_error(); 912 913 fail_2: 914 while (--envc >= 0) 915 DEL(envlist[envc]); 916 DEL(envlist); 917 fail_1: 918 DEL(argvlist); 919 920 return NULL; 921} 922#endif /* HAVE_EXECV */ 923 924#ifdef HAVE_FORK 925static object * 926posix_fork(self, args) 927 object *self; 928 object *args; 929{ 930 int pid; 931 if (!getnoarg(args)) 932 return NULL; 933 pid = fork(); 934 if (pid == -1) 935 return posix_error(); 936 return newintobject((long)pid); 937} 938#endif 939 940#ifdef HAVE_GETEGID 941static object * 942posix_getegid(self, args) 943 object *self; 944 object *args; 945{ 946 if (!getnoarg(args)) 947 return NULL; 948 return newintobject((long)getegid()); 949} 950#endif 951 952#ifdef HAVE_GETEUID 953static object * 954posix_geteuid(self, args) 955 object *self; 956 object *args; 957{ 958 if (!getnoarg(args)) 959 return NULL; 960 return newintobject((long)geteuid()); 961} 962#endif 963 964#ifdef HAVE_GETGID 965static object * 966posix_getgid(self, args) 967 object *self; 968 object *args; 969{ 970 if (!getnoarg(args)) 971 return NULL; 972 return newintobject((long)getgid()); 973} 974#endif 975 976static object * 977posix_getpid(self, args) 978 object *self; 979 object *args; 980{ 981 if (!getnoarg(args)) 982 return NULL; 983 return newintobject((long)getpid()); 984} 985 986#ifdef HAVE_GETPGRP 987static object * 988posix_getpgrp(self, args) 989 object *self; 990 object *args; 991{ 992 if (!getnoarg(args)) 993 return NULL; 994#ifdef GETPGRP_HAVE_ARG 995 return newintobject((long)getpgrp(0)); 996#else /* GETPGRP_HAVE_ARG */ 997 return newintobject((long)getpgrp()); 998#endif /* GETPGRP_HAVE_ARG */ 999} 1000#endif /* HAVE_GETPGRP */ 1001 1002#ifdef HAVE_SETPGRP 1003static object * 1004posix_setpgrp(self, args) 1005 object *self; 1006 object *args; 1007{ 1008 if (!getnoarg(args)) 1009 return NULL; 1010#ifdef SETPGRP_HAVE_ARG 1011 if (setpgrp(0, 0) < 0) 1012#else /* SETPGRP_HAVE_ARG */ 1013 if (setpgrp() < 0) 1014#endif /* SETPGRP_HAVE_ARG */ 1015 return posix_error(); 1016 INCREF(None); 1017 return None; 1018} 1019 1020#endif /* HAVE_SETPGRP */ 1021 1022#ifdef HAVE_GETPPID 1023static object * 1024posix_getppid(self, args) 1025 object *self; 1026 object *args; 1027{ 1028 if (!getnoarg(args)) 1029 return NULL; 1030 return newintobject((long)getppid()); 1031} 1032#endif 1033 1034#ifdef HAVE_GETUID 1035static object * 1036posix_getuid(self, args) 1037 object *self; 1038 object *args; 1039{ 1040 if (!getnoarg(args)) 1041 return NULL; 1042 return newintobject((long)getuid()); 1043} 1044#endif 1045 1046#ifdef HAVE_KILL 1047static object * 1048posix_kill(self, args) 1049 object *self; 1050 object *args; 1051{ 1052 int pid, sig; 1053 if (!getargs(args, "(ii)", &pid, &sig)) 1054 return NULL; 1055 if (kill(pid, sig) == -1) 1056 return posix_error(); 1057 INCREF(None); 1058 return None; 1059} 1060#endif 1061 1062#ifdef HAVE_POPEN 1063static object * 1064posix_popen(self, args) 1065 object *self; 1066 object *args; 1067{ 1068 char *name; 1069 char *mode = "r"; 1070 int bufsize = -1; 1071 FILE *fp; 1072 object *f; 1073 if (!newgetargs(args, "s|si", &name, &mode, &bufsize)) 1074 return NULL; 1075 BGN_SAVE 1076 fp = popen(name, mode); 1077 END_SAVE 1078 if (fp == NULL) 1079 return posix_error(); 1080 f = newopenfileobject(fp, name, mode, pclose); 1081 if (f != NULL) 1082 setfilebufsize(f, bufsize); 1083 return f; 1084} 1085#endif /* HAVE_POPEN */ 1086 1087#ifdef HAVE_SETUID 1088static object * 1089posix_setuid(self, args) 1090 object *self; 1091 object *args; 1092{ 1093 int uid; 1094 if (!getargs(args, "i", &uid)) 1095 return NULL; 1096 if (setuid(uid) < 0) 1097 return posix_error(); 1098 INCREF(None); 1099 return None; 1100} 1101#endif /* HAVE_SETUID */ 1102 1103#ifdef HAVE_SETGID 1104static object * 1105posix_setgid(self, args) 1106 object *self; 1107 object *args; 1108{ 1109 int gid; 1110 if (!getargs(args, "i", &gid)) 1111 return NULL; 1112 if (setgid(gid) < 0) 1113 return posix_error(); 1114 INCREF(None); 1115 return None; 1116} 1117#endif /* HAVE_SETGID */ 1118 1119#ifdef HAVE_WAITPID 1120static object * 1121posix_waitpid(self, args) 1122 object *self; 1123 object *args; 1124{ 1125 int pid, options, sts; 1126 if (!getargs(args, "(ii)", &pid, &options)) 1127 return NULL; 1128 BGN_SAVE 1129 pid = waitpid(pid, &sts, options); 1130 END_SAVE 1131 if (pid == -1) 1132 return posix_error(); 1133 else 1134 return mkvalue("ii", pid, sts); 1135} 1136#endif /* HAVE_WAITPID */ 1137 1138#ifdef HAVE_WAIT 1139static object * 1140posix_wait(self, args) 1141 object *self; 1142 object *args; 1143{ 1144 int pid, sts; 1145 BGN_SAVE 1146 pid = wait(&sts); 1147 END_SAVE 1148 if (pid == -1) 1149 return posix_error(); 1150 else 1151 return mkvalue("ii", pid, sts); 1152} 1153#endif 1154 1155static object * 1156posix_lstat(self, args) 1157 object *self; 1158 object *args; 1159{ 1160#ifdef HAVE_LSTAT 1161 return posix_do_stat(self, args, lstat); 1162#else /* !HAVE_LSTAT */ 1163 return posix_do_stat(self, args, stat); 1164#endif /* !HAVE_LSTAT */ 1165} 1166 1167#ifdef HAVE_READLINK 1168static object * 1169posix_readlink(self, args) 1170 object *self; 1171 object *args; 1172{ 1173 char buf[MAXPATHLEN]; 1174 char *path; 1175 int n; 1176 if (!getargs(args, "s", &path)) 1177 return NULL; 1178 BGN_SAVE 1179 n = readlink(path, buf, (int) sizeof buf); 1180 END_SAVE 1181 if (n < 0) 1182 return posix_error(); 1183 return newsizedstringobject(buf, n); 1184} 1185#endif /* HAVE_READLINK */ 1186 1187#ifdef HAVE_SYMLINK 1188static object * 1189posix_symlink(self, args) 1190 object *self; 1191 object *args; 1192{ 1193 return posix_2str(args, symlink); 1194} 1195#endif /* HAVE_SYMLINK */ 1196 1197#ifdef HAVE_TIMES 1198#ifndef HZ 1199#define HZ 60 /* Universal constant :-) */ 1200#endif /* HZ */ 1201static object * 1202posix_times(self, args) 1203 object *self; 1204 object *args; 1205{ 1206 struct tms t; 1207 clock_t c; 1208 if (!getnoarg(args)) 1209 return NULL; 1210 errno = 0; 1211 c = times(&t); 1212 if (c == (clock_t) -1) 1213 return posix_error(); 1214 return mkvalue("ddddd", 1215 (double)t.tms_utime / HZ, 1216 (double)t.tms_stime / HZ, 1217 (double)t.tms_cutime / HZ, 1218 (double)t.tms_cstime / HZ, 1219 (double)c / HZ); 1220} 1221#endif /* HAVE_TIMES */ 1222#if defined(NT) && !defined(HAVE_TIMES) 1223#define HAVE_TIMES /* so the method table will pick it up */ 1224static object * 1225posix_times(self, args) 1226 object *self; 1227 object *args; 1228{ 1229 FILETIME create, exit, kernel, user; 1230 HANDLE hProc; 1231 if (!getnoarg(args)) 1232 return NULL; 1233 hProc = GetCurrentProcess(); 1234 GetProcessTimes(hProc,&create, &exit, &kernel, &user); 1235 return mkvalue("ddddd", 1236 (double)(kernel.dwHighDateTime*2E32+kernel.dwLowDateTime) / 2E6, 1237 (double)(user.dwHighDateTime*2E32+user.dwLowDateTime) / 2E6, 1238 (double)0, 1239 (double)0, 1240 (double)0); 1241} 1242#endif /* NT */ 1243 1244#ifdef HAVE_SETSID 1245static object * 1246posix_setsid(self, args) 1247 object *self; 1248 object *args; 1249{ 1250 if (!getnoarg(args)) 1251 return NULL; 1252 if (setsid() < 0) 1253 return posix_error(); 1254 INCREF(None); 1255 return None; 1256} 1257#endif /* HAVE_SETSID */ 1258 1259#ifdef HAVE_SETPGID 1260static object * 1261posix_setpgid(self, args) 1262 object *self; 1263 object *args; 1264{ 1265 int pid, pgrp; 1266 if (!getargs(args, "(ii)", &pid, &pgrp)) 1267 return NULL; 1268 if (setpgid(pid, pgrp) < 0) 1269 return posix_error(); 1270 INCREF(None); 1271 return None; 1272} 1273#endif /* HAVE_SETPGID */ 1274 1275#ifdef HAVE_TCGETPGRP 1276static object * 1277posix_tcgetpgrp(self, args) 1278 object *self; 1279 object *args; 1280{ 1281 int fd, pgid; 1282 if (!getargs(args, "i", &fd)) 1283 return NULL; 1284 pgid = tcgetpgrp(fd); 1285 if (pgid < 0) 1286 return posix_error(); 1287 return newintobject((long)pgid); 1288} 1289#endif /* HAVE_TCGETPGRP */ 1290 1291#ifdef HAVE_TCSETPGRP 1292static object * 1293posix_tcsetpgrp(self, args) 1294 object *self; 1295 object *args; 1296{ 1297 int fd, pgid; 1298 if (!getargs(args, "(ii)", &fd, &pgid)) 1299 return NULL; 1300 if (tcsetpgrp(fd, pgid) < 0) 1301 return posix_error(); 1302 INCREF(None); 1303 return None; 1304} 1305#endif /* HAVE_TCSETPGRP */ 1306 1307/* Functions acting on file descriptors */ 1308 1309static object * 1310posix_open(self, args) 1311 object *self; 1312 object *args; 1313{ 1314 char *file; 1315 int flag; 1316 int mode = 0777; 1317 int fd; 1318 if (!getargs(args, "(si)", &file, &flag)) { 1319 err_clear(); 1320 if (!getargs(args, "(sii)", &file, &flag, &mode)) 1321 return NULL; 1322 } 1323 BGN_SAVE 1324 fd = open(file, flag, mode); 1325 END_SAVE 1326 if (fd < 0) 1327 return posix_error(); 1328 return newintobject((long)fd); 1329} 1330 1331static object * 1332posix_close(self, args) 1333 object *self; 1334 object *args; 1335{ 1336 int fd, res; 1337 if (!getargs(args, "i", &fd)) 1338 return NULL; 1339 BGN_SAVE 1340 res = close(fd); 1341 END_SAVE 1342 if (res < 0) 1343 return posix_error(); 1344 INCREF(None); 1345 return None; 1346} 1347 1348static object * 1349posix_dup(self, args) 1350 object *self; 1351 object *args; 1352{ 1353 int fd; 1354 if (!getargs(args, "i", &fd)) 1355 return NULL; 1356 BGN_SAVE 1357 fd = dup(fd); 1358 END_SAVE 1359 if (fd < 0) 1360 return posix_error(); 1361 return newintobject((long)fd); 1362} 1363 1364static object * 1365posix_dup2(self, args) 1366 object *self; 1367 object *args; 1368{ 1369 int fd, fd2, res; 1370 if (!getargs(args, "(ii)", &fd, &fd2)) 1371 return NULL; 1372 BGN_SAVE 1373 res = dup2(fd, fd2); 1374 END_SAVE 1375 if (res < 0) 1376 return posix_error(); 1377 INCREF(None); 1378 return None; 1379} 1380 1381static object * 1382posix_lseek(self, args) 1383 object *self; 1384 object *args; 1385{ 1386 int fd, how; 1387 long pos, res; 1388 if (!getargs(args, "(ili)", &fd, &pos, &how)) 1389 return NULL; 1390#ifdef SEEK_SET 1391 /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */ 1392 switch (how) { 1393 case 0: how = SEEK_SET; break; 1394 case 1: how = SEEK_CUR; break; 1395 case 2: how = SEEK_END; break; 1396 } 1397#endif /* SEEK_END */ 1398 BGN_SAVE 1399 res = lseek(fd, pos, how); 1400 END_SAVE 1401 if (res < 0) 1402 return posix_error(); 1403 return newintobject(res); 1404} 1405 1406static object * 1407posix_read(self, args) 1408 object *self; 1409 object *args; 1410{ 1411 int fd, size; 1412 object *buffer; 1413 if (!getargs(args, "(ii)", &fd, &size)) 1414 return NULL; 1415 buffer = newsizedstringobject((char *)NULL, size); 1416 if (buffer == NULL) 1417 return NULL; 1418 BGN_SAVE 1419 size = read(fd, getstringvalue(buffer), size); 1420 END_SAVE 1421 if (size < 0) { 1422 DECREF(buffer); 1423 return posix_error(); 1424 } 1425 resizestring(&buffer, size); 1426 return buffer; 1427} 1428 1429static object * 1430posix_write(self, args) 1431 object *self; 1432 object *args; 1433{ 1434 int fd, size; 1435 char *buffer; 1436 if (!getargs(args, "(is#)", &fd, &buffer, &size)) 1437 return NULL; 1438 BGN_SAVE 1439 size = write(fd, buffer, size); 1440 END_SAVE 1441 if (size < 0) 1442 return posix_error(); 1443 return newintobject((long)size); 1444} 1445 1446static object * 1447posix_fstat(self, args) 1448 object *self; 1449 object *args; 1450{ 1451 int fd; 1452 struct stat st; 1453 int res; 1454 if (!getargs(args, "i", &fd)) 1455 return NULL; 1456 BGN_SAVE 1457 res = fstat(fd, &st); 1458 END_SAVE 1459 if (res != 0) 1460 return posix_error(); 1461 return mkvalue("(llllllllll)", 1462 (long)st.st_mode, 1463 (long)st.st_ino, 1464 (long)st.st_dev, 1465 (long)st.st_nlink, 1466 (long)st.st_uid, 1467 (long)st.st_gid, 1468 (long)st.st_size, 1469 (long)st.st_atime, 1470 (long)st.st_mtime, 1471 (long)st.st_ctime); 1472} 1473 1474static object * 1475posix_fdopen(self, args) 1476 object *self; 1477 object *args; 1478{ 1479 extern int fclose PROTO((FILE *)); 1480 int fd; 1481 char *mode = "r"; 1482 int bufsize = -1; 1483 FILE *fp; 1484 object *f; 1485 if (!newgetargs(args, "i|si", &fd, &mode, &bufsize)) 1486 return NULL; 1487 BGN_SAVE 1488 fp = fdopen(fd, mode); 1489 END_SAVE 1490 if (fp == NULL) 1491 return posix_error(); 1492 f = newopenfileobject(fp, "(fdopen)", mode, fclose); 1493 if (f != NULL) 1494 setfilebufsize(f, bufsize); 1495 return f; 1496} 1497 1498#ifdef HAVE_PIPE 1499static object * 1500posix_pipe(self, args) 1501 object *self; 1502 object *args; 1503{ 1504#if !defined(NT) 1505 int fds[2]; 1506 int res; 1507 if (!getargs(args, "")) 1508 return NULL; 1509 BGN_SAVE 1510 res = pipe(fds); 1511 END_SAVE 1512 if (res != 0) 1513 return posix_error(); 1514 return mkvalue("(ii)", fds[0], fds[1]); 1515#else /* NT */ 1516 HANDLE read, write; 1517 BOOL ok; 1518 if (!getargs(args, "")) 1519 return NULL; 1520 BGN_SAVE 1521 ok = CreatePipe( &read, &write, NULL, 0); 1522 END_SAVE 1523 if (!ok) 1524 return posix_error(); 1525 return mkvalue("(ii)", read, write); 1526#endif /* NT */ 1527} 1528#endif /* HAVE_PIPE */ 1529 1530#ifdef HAVE_MKFIFO 1531static object * 1532posix_mkfifo(self, args) 1533 object *self; 1534 object *args; 1535{ 1536 char *file; 1537 int mode = 0666; 1538 int res; 1539 if (!newgetargs(args, "s|i", &file, &mode)) 1540 return NULL; 1541 BGN_SAVE 1542 res = mkfifo(file, mode); 1543 END_SAVE 1544 if (res < 0) 1545 return posix_error(); 1546 INCREF(None); 1547 return None; 1548} 1549#endif 1550 1551#ifdef HAVE_FTRUNCATE 1552static object * 1553posix_ftruncate(self, args) 1554 object *self; /* Not used */ 1555 object *args; 1556{ 1557 int fd; 1558 long length; 1559 int res; 1560 1561 if (!getargs(args, "(il)", &fd, &length)) 1562 return NULL; 1563 1564 BGN_SAVE 1565 res = ftruncate(fd, length); 1566 END_SAVE 1567 if (res < 0) { 1568 err_errno(IOError); 1569 return NULL; 1570 } 1571 INCREF(None); 1572 return None; 1573} 1574#endif 1575 1576static struct methodlist posix_methods[] = { 1577 {"chdir", posix_chdir}, 1578 {"chmod", posix_chmod}, 1579#ifdef HAVE_CHOWN 1580 {"chown", posix_chown}, 1581#endif /* HAVE_CHOWN */ 1582#ifdef HAVE_GETCWD 1583 {"getcwd", posix_getcwd}, 1584#endif 1585#ifdef HAVE_LINK 1586 {"link", posix_link}, 1587#endif /* HAVE_LINK */ 1588 {"listdir", posix_listdir}, 1589 {"lstat", posix_lstat}, 1590 {"mkdir", posix_mkdir, 1}, 1591#ifdef HAVE_NICE 1592 {"nice", posix_nice}, 1593#endif /* HAVE_NICE */ 1594#ifdef HAVE_READLINK 1595 {"readlink", posix_readlink}, 1596#endif /* HAVE_READLINK */ 1597 {"rename", posix_rename}, 1598 {"rmdir", posix_rmdir}, 1599 {"stat", posix_stat}, 1600#ifdef HAVE_SYMLINK 1601 {"symlink", posix_symlink}, 1602#endif /* HAVE_SYMLINK */ 1603#ifdef HAVE_SYSTEM 1604 {"system", posix_system}, 1605#endif 1606 {"umask", posix_umask}, 1607#ifdef HAVE_UNAME 1608 {"uname", posix_uname}, 1609#endif /* HAVE_UNAME */ 1610 {"unlink", posix_unlink}, 1611 {"remove", posix_unlink}, 1612 {"utime", posix_utime}, 1613#ifdef HAVE_TIMES 1614 {"times", posix_times}, 1615#endif /* HAVE_TIMES */ 1616 {"_exit", posix__exit}, 1617#ifdef HAVE_EXECV 1618 {"execv", posix_execv}, 1619 {"execve", posix_execve}, 1620#endif /* HAVE_EXECV */ 1621#ifdef HAVE_FORK 1622 {"fork", posix_fork}, 1623#endif /* HAVE_FORK */ 1624#ifdef HAVE_GETEGID 1625 {"getegid", posix_getegid}, 1626#endif /* HAVE_GETEGID */ 1627#ifdef HAVE_GETEUID 1628 {"geteuid", posix_geteuid}, 1629#endif /* HAVE_GETEUID */ 1630#ifdef HAVE_GETGID 1631 {"getgid", posix_getgid}, 1632#endif /* HAVE_GETGID */ 1633 {"getpid", posix_getpid}, 1634#ifdef HAVE_GETPGRP 1635 {"getpgrp", posix_getpgrp}, 1636#endif /* HAVE_GETPGRP */ 1637#ifdef HAVE_GETPPID 1638 {"getppid", posix_getppid}, 1639#endif /* HAVE_GETPPID */ 1640#ifdef HAVE_GETUID 1641 {"getuid", posix_getuid}, 1642#endif /* HAVE_GETUID */ 1643#ifdef HAVE_KILL 1644 {"kill", posix_kill}, 1645#endif /* HAVE_KILL */ 1646#ifdef HAVE_POPEN 1647 {"popen", posix_popen, 1}, 1648#endif /* HAVE_POPEN */ 1649#ifdef HAVE_SETUID 1650 {"setuid", posix_setuid}, 1651#endif /* HAVE_SETUID */ 1652#ifdef HAVE_SETGID 1653 {"setgid", posix_setgid}, 1654#endif /* HAVE_SETGID */ 1655#ifdef HAVE_SETPGRP 1656 {"setpgrp", posix_setpgrp}, 1657#endif /* HAVE_SETPGRP */ 1658#ifdef HAVE_WAIT 1659 {"wait", posix_wait}, 1660#endif /* HAVE_WAIT */ 1661#ifdef HAVE_WAITPID 1662 {"waitpid", posix_waitpid}, 1663#endif /* HAVE_WAITPID */ 1664#ifdef HAVE_SETSID 1665 {"setsid", posix_setsid}, 1666#endif /* HAVE_SETSID */ 1667#ifdef HAVE_SETPGID 1668 {"setpgid", posix_setpgid}, 1669#endif /* HAVE_SETPGID */ 1670#ifdef HAVE_TCGETPGRP 1671 {"tcgetpgrp", posix_tcgetpgrp}, 1672#endif /* HAVE_TCGETPGRP */ 1673#ifdef HAVE_TCSETPGRP 1674 {"tcsetpgrp", posix_tcsetpgrp}, 1675#endif /* HAVE_TCSETPGRP */ 1676 {"open", posix_open}, 1677 {"close", posix_close}, 1678 {"dup", posix_dup}, 1679 {"dup2", posix_dup2}, 1680 {"lseek", posix_lseek}, 1681 {"read", posix_read}, 1682 {"write", posix_write}, 1683 {"fstat", posix_fstat}, 1684 {"fdopen", posix_fdopen, 1}, 1685#ifdef HAVE_PIPE 1686 {"pipe", posix_pipe}, 1687#endif 1688#ifdef HAVE_MKFIFO 1689 {"mkfifo", posix_mkfifo, 1}, 1690#endif 1691#ifdef HAVE_FTRUNCATE 1692 {"ftruncate", posix_ftruncate, 1}, 1693#endif 1694 {NULL, NULL} /* Sentinel */ 1695}; 1696 1697 1698#ifdef NT 1699void 1700initnt() 1701{ 1702 object *m, *d, *v; 1703 1704 m = initmodule("nt", posix_methods); 1705 d = getmoduledict(m); 1706 1707 /* Initialize nt.environ dictionary */ 1708 v = convertenviron(); 1709 if (v == NULL || dictinsert(d, "environ", v) != 0) 1710 fatal("can't define nt.environ"); 1711 DECREF(v); 1712 1713 /* Initialize nt.error exception */ 1714 PosixError = newstringobject("nt.error"); 1715 if (PosixError == NULL || dictinsert(d, "error", PosixError) != 0) 1716 fatal("can't define nt.error"); 1717} 1718#else /* !_MSC_VER */ 1719void 1720initposix() 1721{ 1722 object *m, *d, *v; 1723 1724 m = initmodule("posix", posix_methods); 1725 d = getmoduledict(m); 1726 1727 /* Initialize posix.environ dictionary */ 1728 v = convertenviron(); 1729 if (v == NULL || dictinsert(d, "environ", v) != 0) 1730 fatal("can't define posix.environ"); 1731 DECREF(v); 1732 1733#ifdef WNOHANG 1734 /* Export WNOHANG symbol */ 1735 v = newintobject((long)WNOHANG); 1736 if (v == NULL || dictinsert(d, "WNOHANG", v) != 0) 1737 fatal("can't define posix.WNOHANG"); 1738 DECREF(v); 1739#endif 1740 1741 /* Initialize posix.error exception */ 1742 PosixError = newstringobject("posix.error"); 1743 if (PosixError == NULL || dictinsert(d, "error", PosixError) != 0) 1744 fatal("can't define posix.error"); 1745} 1746#endif /* !_MSC_VER */ 1747