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