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