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