1 /* $Header: doio.c,v 3.0.1.13 90/11/10 01:17:37 lwall Locked $
3 * Copyright (c) 1989, Larry Wall
5 * You may distribute under the terms of the GNU General Public License
6 * as specified in the README file that comes with the perl 3.0 kit.
9 * Revision 3.0.1.13 90/11/10 01:17:37 lwall
10 * patch38: -e _ was wrong if last stat failed
11 * patch38: more msdos/os2 upgrades
13 * Revision 3.0.1.12 90/10/20 02:04:18 lwall
14 * patch37: split out separate Sys V IPC features
16 * Revision 3.0.1.11 90/10/15 16:16:11 lwall
17 * patch29: added SysV IPC
18 * patch29: file - didn't auto-close cleanly
19 * patch29: close; core dumped
20 * patch29: more MSDOS and OS/2 updates, from Kai Uwe Rommel
21 * patch29: various portability fixes
22 * patch29: *foo now prints as *package'foo
24 * Revision 3.0.1.10 90/08/13 22:14:29 lwall
25 * patch28: close-on-exec problems on dup'ed file descriptors
26 * patch28: F_FREESP wasn't implemented the way I thought
28 * Revision 3.0.1.9 90/08/09 02:56:19 lwall
29 * patch19: various MSDOS and OS/2 patches folded in
30 * patch19: prints now check error status better
31 * patch19: printing a list with null elements only printed front of list
32 * patch19: on machines with vfork child would allocate memory in parent
33 * patch19: getsockname and getpeername gave bogus warning on error
34 * patch19: MACH doesn't have seekdir or telldir
36 * Revision 3.0.1.8 90/03/27 15:44:02 lwall
37 * patch16: MSDOS support
38 * patch16: support for machines that can't cast negative floats to unsigned ints
39 * patch16: system() can lose arguments passed to shell scripts on SysV machines
41 * Revision 3.0.1.7 90/03/14 12:26:24 lwall
42 * patch15: commands involving execs could cause malloc arena corruption
44 * Revision 3.0.1.6 90/03/12 16:30:07 lwall
45 * patch13: system 'FOO=bar command' didn't invoke sh as it should
47 * Revision 3.0.1.5 90/02/28 17:01:36 lwall
48 * patch9: open(FOO,"$filename\0") will now protect trailing spaces in filename
49 * patch9: removed obsolete checks to avoid opening block devices
50 * patch9: removed references to acusec and modusec that some utime.h's have
51 * patch9: added pipe function
53 * Revision 3.0.1.4 89/12/21 19:55:10 lwall
54 * patch7: select now works on big-endian machines
55 * patch7: errno may now be a macro with an lvalue
56 * patch7: ANSI strerror() is now supported
57 * patch7: Configure now detects DG/UX thingies like [sg]etpgrp2 and utime.h
59 * Revision 3.0.1.3 89/11/17 15:13:06 lwall
60 * patch5: some systems have symlink() but not lstat()
61 * patch5: some systems have dirent.h but not readdir()
63 * Revision 3.0.1.2 89/11/11 04:25:51 lwall
64 * patch2: orthogonalized the file modes some so we can have <& +<& etc.
65 * patch2: do_open() now detects sockets passed to process from parent
66 * patch2: fd's above 2 are now closed on exec
67 * patch2: csh code can now use csh from other than /bin
68 * patch2: getsockopt, get{sock,peer}name didn't define result properly
69 * patch2: warn("shutdown") was replicated
70 * patch2: gethostbyname was misdeclared
71 * patch2: telldir() is sometimes a macro
73 * Revision 3.0.1.1 89/10/26 23:10:05 lwall
74 * patch1: Configure now checks for BSD shadow passwords
76 * Revision 3.0 89/10/18 15:10:54 lwall
85 #include <sys/socket.h>
89 #if defined(SELECT) && (defined(M_UNIX) || defined(M_XENIX))
90 #include <sys/select.h>
119 int laststatval = -1;
122 do_open(stab,name,len)
128 register STIO *stio = stab_io(stab);
129 char *myname = savestr(name);
133 char mode[3]; /* stdio file mode ("r\0" or "r+\0") */
136 forkprocess = 1; /* assume true if no fork */
137 while (len && isspace(name[len-1]))
140 stio = stab_io(stab) = stio_new();
141 else if (stio->ifp) {
142 fd = fileno(stio->ifp);
143 if (stio->type == '|')
144 result = mypclose(stio->ifp);
145 else if (stio->type == '-')
147 else if (stio->ifp != stio->ofp) {
149 result = fclose(stio->ofp);
150 fclose(stio->ifp); /* clear stdio, fd already closed */
153 result = fclose(stio->ifp);
156 result = fclose(stio->ifp);
157 if (result == EOF && fd > 2)
158 fprintf(stderr,"Warning: unable to close filehandle %s properly.\n",
160 stio->ofp = stio->ifp = Nullfp;
162 if (*name == '+' && len > 1 && name[len-1] != '|') { /* scary */
173 for (name++; isspace(*name); name++) ;
176 taintproper("Insecure dependency in piped open");
178 fp = mypopen(name,"w");
181 else if (*name == '>') {
183 taintproper("Insecure dependency in open");
187 mode[0] = stio->type = 'a';
196 while (isspace(*name))
201 stab = stabent(name,FALSE);
202 if (!stab || !stab_io(stab))
204 if (stab_io(stab) && stab_io(stab)->ifp) {
205 fd = fileno(stab_io(stab)->ifp);
206 if (stab_io(stab)->type == 's')
212 fp = fdopen(dup(fd),mode);
215 while (isspace(*name))
217 if (strEQ(name,"-")) {
222 fp = fopen(name,mode);
230 while (isspace(*name))
234 if (strEQ(name,"-")) {
239 fp = fopen(name,mode);
241 else if (name[len-1] == '|') {
244 taintproper("Insecure dependency in piped open");
247 while (len && isspace(name[len-1]))
249 for (; isspace(*name); name++) ;
250 fp = mypopen(name,"r");
255 for (; isspace(*name); name++) ;
256 if (strEQ(name,"-")) {
261 fp = fopen(name,"r");
268 stio->type != '|' && stio->type != '-') {
269 if (fstat(fileno(fp),&statbuf) < 0) {
273 result = (statbuf.st_mode & S_IFMT);
275 if (result == S_IFSOCK || result == 0)
276 stio->type = 's'; /* in case a socket was passed in to us */
279 #if defined(FCNTL) && defined(F_SETFD)
281 fcntl(fd,F_SETFD,fd >= 3);
285 if (stio->type != 's')
288 stio->ofp = fdopen(fileno(fp),"w");
299 int filemode,fileuid,filegid;
301 while (alen(stab_xarray(stab)) >= 0) {
302 str = ashift(stab_xarray(stab));
303 str_sset(stab_val(stab),str);
304 STABSET(stab_val(stab));
305 oldname = str_get(stab_val(stab));
306 if (do_open(stab,oldname,stab_val(stab)->str_cur)) {
309 taintproper("Insecure dependency in inplace open");
311 filemode = statbuf.st_mode;
312 fileuid = statbuf.st_uid;
313 filegid = statbuf.st_gid;
316 add_suffix(str,inplace);
318 str_cat(str,inplace);
322 (void)rename(oldname,str->str_ptr);
324 do_close(stab,FALSE);
325 (void)unlink(str->str_ptr);
326 (void)rename(oldname,str->str_ptr);
327 do_open(stab,str->str_ptr,stab_val(stab)->str_cur);
330 (void)UNLINK(str->str_ptr);
331 (void)link(oldname,str->str_ptr);
332 (void)UNLINK(oldname);
337 (void)UNLINK(oldname);
339 fatal("Can't do inplace edit without backup");
344 str_cat(str,oldname);
345 errno = 0; /* in case sprintf set errno */
346 if (!do_open(argvoutstab,str->str_ptr,str->str_cur))
347 fatal("Can't do inplace edit");
348 defoutstab = argvoutstab;
350 (void)fchmod(fileno(stab_io(argvoutstab)->ifp),filemode);
352 (void)chmod(oldname,filemode);
355 (void)fchown(fileno(stab_io(argvoutstab)->ifp),fileuid,filegid);
358 (void)chown(oldname,fileuid,filegid);
363 return stab_io(stab)->ifp;
366 fprintf(stderr,"Can't open %s\n",str_get(str));
370 (void)do_close(argvoutstab,FALSE);
371 defoutstab = stabent("STDOUT",TRUE);
378 do_pipe(str, rstab, wstab)
383 register STIO *rstio;
384 register STIO *wstio;
392 rstio = stab_io(rstab);
393 wstio = stab_io(wstab);
396 rstio = stab_io(rstab) = stio_new();
398 do_close(rstab,FALSE);
400 wstio = stab_io(wstab) = stio_new();
402 do_close(wstab,FALSE);
406 rstio->ifp = fdopen(fd[0], "r");
407 wstio->ofp = fdopen(fd[1], "w");
408 wstio->ifp = wstio->ofp;
412 str_sset(str,&str_yes);
416 str_sset(str,&str_undef);
422 do_close(stab,explicit)
434 stio = stab_io(stab);
435 if (!stio) { /* never opened */
436 if (dowarn && explicit)
437 warn("Close on unopened file <%s>",stab_name(stab));
441 if (stio->type == '|') {
442 status = mypclose(stio->ifp);
443 retval = (status >= 0);
444 statusvalue = (unsigned short)status & 0xffff;
446 else if (stio->type == '-')
449 if (stio->ofp && stio->ofp != stio->ifp) { /* a socket */
450 retval = (fclose(stio->ofp) != EOF);
451 fclose(stio->ifp); /* clear stdio, fd already closed */
454 retval = (fclose(stio->ifp) != EOF);
456 stio->ofp = stio->ifp = Nullfp;
471 if (!stab) { /* eof() */
473 stio = stab_io(argvstab);
478 stio = stab_io(stab);
485 #ifdef STDSTDIO /* (the code works without this) */
486 if (stio->ifp->_cnt > 0) /* cheat a little, since */
487 return FALSE; /* this is the most usual case */
490 ch = getc(stio->ifp);
492 (void)ungetc(ch, stio->ifp);
495 if (!stab) { /* not necessarily a real EOF yet? */
496 if (!nextargv(argvstab)) /* get another fp handy */
500 return TRUE; /* normal fp, definitely end of file */
514 stio = stab_io(stab);
515 if (!stio || !stio->ifp)
519 (void)fseek (stio->ifp, 0L, 2); /* ultrix 1.2 workaround */
521 return ftell(stio->ifp);
525 warn("tell() on unopened file");
530 do_seek(stab, pos, whence)
540 stio = stab_io(stab);
541 if (!stio || !stio->ifp)
545 (void)fseek (stio->ifp, 0L, 2); /* ultrix 1.2 workaround */
547 return fseek(stio->ifp, pos, whence) >= 0;
551 warn("seek() on unopened file");
556 do_ctl(optype,stab,func,argstr)
566 if (!stab || !argstr)
568 stio = stab_io(stab);
572 if (argstr->str_pok || !argstr->str_nok) {
573 if (!argstr->str_pok)
578 #define IOCPARM_LEN(x) (((x) >> 16) & IOCPARM_MASK)
582 retval = IOCPARM_LEN(func); /* on BSDish systes we're safe */
584 retval = 256; /* otherwise guess at what's safe */
586 if (argstr->str_cur < retval) {
587 Str_Grow(argstr,retval+1);
588 argstr->str_cur = retval;
592 s[argstr->str_cur] = 17; /* a little sanity check here */
595 retval = (int)str_gnum(argstr);
597 s = (char*)(long)retval; /* ouch */
599 s = (char*)retval; /* ouch */
604 if (optype == O_IOCTL)
605 retval = ioctl(fileno(stio->ifp), func, s);
608 fatal("fcntl is not implemented");
611 retval = fcntl(fileno(stio->ifp), func, s);
613 fatal("fcntl is not implemented");
620 if (argstr->str_pok) {
621 if (s[argstr->str_cur] != 17)
622 fatal("Return value overflowed string");
623 s[argstr->str_cur] = 0; /* put our null back */
629 do_stat(str,arg,gimme,arglast)
635 register ARRAY *ary = stack;
636 register int sp = arglast[0] + 1;
639 if ((arg[1].arg_type & A_MASK) == A_WORD) {
640 tmpstab = arg[1].arg_ptr.arg_stab;
641 if (tmpstab != defstab) {
643 str_set(statname,"");
644 if (!stab_io(tmpstab) || !stab_io(tmpstab)->ifp ||
645 fstat(fileno(stab_io(tmpstab)->ifp),&statcache) < 0) {
650 else if (laststatval < 0)
654 str_sset(statname,ary->ary_array[sp]);
657 if (arg->arg_type == O_LSTAT)
658 laststatval = lstat(str_get(statname),&statcache);
661 laststatval = stat(str_get(statname),&statcache);
666 if (gimme != G_ARRAY) {
668 str_sset(str,&str_yes);
670 str_sset(str,&str_undef);
672 ary->ary_array[sp] = str;
678 (void)astore(ary,++sp,
679 str_2static(str_nmake((double)statcache.st_dev)));
680 (void)astore(ary,++sp,
681 str_2static(str_nmake((double)statcache.st_ino)));
682 (void)astore(ary,++sp,
683 str_2static(str_nmake((double)statcache.st_mode)));
684 (void)astore(ary,++sp,
685 str_2static(str_nmake((double)statcache.st_nlink)));
686 (void)astore(ary,++sp,
687 str_2static(str_nmake((double)statcache.st_uid)));
688 (void)astore(ary,++sp,
689 str_2static(str_nmake((double)statcache.st_gid)));
690 (void)astore(ary,++sp,
691 str_2static(str_nmake((double)statcache.st_rdev)));
692 (void)astore(ary,++sp,
693 str_2static(str_nmake((double)statcache.st_size)));
694 (void)astore(ary,++sp,
695 str_2static(str_nmake((double)statcache.st_atime)));
696 (void)astore(ary,++sp,
697 str_2static(str_nmake((double)statcache.st_mtime)));
698 (void)astore(ary,++sp,
699 str_2static(str_nmake((double)statcache.st_ctime)));
701 (void)astore(ary,++sp,
702 str_2static(str_nmake((double)statcache.st_blksize)));
703 (void)astore(ary,++sp,
704 str_2static(str_nmake((double)statcache.st_blocks)));
706 (void)astore(ary,++sp,
707 str_2static(str_make("",0)));
708 (void)astore(ary,++sp,
709 str_2static(str_make("",0)));
712 (void)astore(ary,++sp,str_nmake(0.0));
718 #if !defined(TRUNCATE) && !defined(CHSIZE) && defined(F_FREESP)
719 /* code courtesy of William Kucharski */
722 int chsize(fd, length)
723 int fd; /* file descriptor */
724 off_t length; /* length to set file to */
730 if (fstat(fd, &filebuf) < 0)
733 if (filebuf.st_size < length) {
735 /* extend file length */
737 if ((lseek(fd, (length - 1), 0)) < 0)
740 /* write a "0" byte */
742 if ((write(fd, "", 1)) != 1)
746 /* truncate length */
751 fl.l_type = F_WRLCK; /* write lock on file space */
754 * This relies on the UNDOCUMENTED F_FREESP argument to
755 * fcntl(2), which truncates the file so that it ends at the
756 * position indicated by fl.l_start.
758 * Will minor miracles never cease?
761 if (fcntl(fd, F_FREESP, &fl) < 0)
768 #endif /* F_FREESP */
771 do_truncate(str,arg,gimme,arglast)
777 register ARRAY *ary = stack;
778 register int sp = arglast[0] + 1;
779 off_t len = (off_t)str_gnum(ary->ary_array[sp+1]);
783 #if defined(TRUNCATE) || defined(CHSIZE)
785 if ((arg[1].arg_type & A_MASK) == A_WORD) {
786 tmpstab = arg[1].arg_ptr.arg_stab;
787 if (!stab_io(tmpstab) ||
788 ftruncate(fileno(stab_io(tmpstab)->ifp), len) < 0)
791 else if (truncate(str_get(ary->ary_array[sp]), len) < 0)
794 if ((arg[1].arg_type & A_MASK) == A_WORD) {
795 tmpstab = arg[1].arg_ptr.arg_stab;
796 if (!stab_io(tmpstab) ||
797 chsize(fileno(stab_io(tmpstab)->ifp), len) < 0)
803 if ((tmpfd = open(str_get(ary->ary_array[sp]), 0)) < 0)
806 if (chsize(tmpfd, len) < 0)
814 str_sset(str,&str_yes);
816 str_sset(str,&str_undef);
818 ary->ary_array[sp] = str;
821 fatal("truncate not implemented");
826 looks_like_number(str)
835 send = s + str->str_cur;
840 if (*s == '+' || *s == '-')
848 else if (s == str->str_ptr)
854 if (*s == 'e' || *s == 'E') {
856 if (*s == '+' || *s == '-')
877 warn("print to unopened file");
883 ((str->str_nok && str->str_u.str_nval != 0.0)
884 || (looks_like_number(str) && str_gnum(str) != 0.0) ) ) {
885 fprintf(fp, ofmt, str->str_u.str_nval);
890 if (*tmps == 'S' && tmps[1] == 't' && tmps[2] == 'B' && tmps[3] == '\0'
891 && str->str_cur == sizeof(STBP) && strlen(tmps) < str->str_cur) {
892 STR *tmpstr = str_static(&str_undef);
893 stab_fullname(tmpstr,((STAB*)str));/* a stab value, be nice */
898 if (str->str_cur && (fwrite(tmps,1,str->str_cur,fp) == 0 || ferror(fp)))
905 do_aprint(arg,fp,arglast)
910 register STR **st = stack->ary_array;
911 register int sp = arglast[1];
913 register int items = arglast[2] - sp;
917 warn("print to unopened file");
921 if (arg->arg_type == O_PRTF) {
922 do_sprintf(arg->arg_ptr.arg_str,items,st);
923 retval = do_print(arg->arg_ptr.arg_str,fp);
926 retval = (items <= 0);
927 for (; items > 0; items--,st++) {
928 if (retval && ofslen) {
929 if (fwrite(ofs, 1, ofslen, fp) == 0 || ferror(fp)) {
934 if (!(retval = do_print(*st, fp)))
937 if (retval && orslen)
938 if (fwrite(ors, 1, orslen, fp) == 0 || ferror(fp))
951 if (arg[1].arg_type & A_DONT) {
952 stio = stab_io(arg[1].arg_ptr.arg_stab);
953 if (stio && stio->ifp) {
954 statstab = arg[1].arg_ptr.arg_stab;
955 str_set(statname,"");
956 return (laststatval = fstat(fileno(stio->ifp), &statcache));
959 if (arg[1].arg_ptr.arg_stab == defstab)
962 warn("Stat on unopened file <%s>",
963 stab_name(arg[1].arg_ptr.arg_stab));
965 str_set(statname,"");
966 return (laststatval = -1);
971 str_sset(statname,str);
972 return (laststatval = stat(str_get(str),&statcache));
988 if (arg[1].arg_type & A_DONT) {
989 if (arg[1].arg_ptr.arg_stab == defstab) {
991 stio = stab_io(statstab);
994 goto really_filename;
998 statstab = arg[1].arg_ptr.arg_stab;
999 str_set(statname,"");
1000 stio = stab_io(statstab);
1002 if (stio && stio->ifp) {
1004 fstat(fileno(stio->ifp),&statcache);
1005 if (stio->ifp->_cnt <= 0) {
1006 i = getc(stio->ifp);
1008 (void)ungetc(i,stio->ifp);
1010 if (stio->ifp->_cnt <= 0) /* null file is anything */
1012 len = stio->ifp->_cnt + (stio->ifp->_ptr - stio->ifp->_base);
1013 s = stio->ifp->_base;
1015 fatal("-T and -B not implemented on filehandles\n");
1020 warn("Test on unopened file <%s>",
1021 stab_name(arg[1].arg_ptr.arg_stab));
1026 statstab = Nullstab;
1027 str_sset(statname,str);
1029 i = open(str_get(str),0);
1032 fstat(i,&statcache);
1033 len = read(i,tbuf,512);
1034 if (len <= 0) /* null file is anything */
1040 /* now scan s to look for textiness */
1042 for (i = 0; i < len; i++,s++) {
1043 if (!*s) { /* null never allowed in text */
1050 *s != '\n' && *s != '\r' && *s != '\b' &&
1051 *s != '\t' && *s != '\f' && *s != 27)
1055 if ((odd * 10 > len) == (arg->arg_type == O_FTTEXT)) /* allow 10% odd */
1062 do_aexec(really,arglast)
1066 register STR **st = stack->ary_array;
1067 register int sp = arglast[1];
1068 register int items = arglast[2] - sp;
1074 New(401,argv, items+1, char*);
1076 for (st += ++sp; items > 0; items--,st++) {
1078 *a++ = str_get(*st);
1084 if (*argv[0] != '/') /* will execvp use PATH? */
1085 taintenv(); /* testing IFS here is overkill, probably */
1087 if (really && *(tmps = str_get(really)))
1090 execvp(argv[0],argv);
1096 static char **Argv = Null(char **);
1097 static char *Cmd = Nullch;
1104 Argv = Null(char **);
1122 taintproper("Insecure dependency in exec");
1125 /* save an extra exec if possible */
1128 if (strnEQ(cmd,cshname,cshlen) && strnEQ(cmd+cshlen," -c",3)) {
1144 if (s[-1] == '\'') {
1146 execl(cshname,"csh", flags,ncmd,(char*)0);
1154 /* see if there are shell metacharacters in it */
1156 for (s = cmd; *s && isalpha(*s); s++) ; /* catch VAR=val gizmo */
1159 for (s = cmd; *s; s++) {
1160 if (*s != ' ' && !isalpha(*s) && index("$&*(){}[]'\";\\|?<>~`\n",*s)) {
1161 if (*s == '\n' && !s[1]) {
1166 execl("/bin/sh","sh","-c",cmd,(char*)0);
1170 New(402,Argv, (s - cmd) / 2 + 2, char*);
1171 Cmd = nsavestr(cmd, s-cmd);
1173 for (s = Cmd; *s;) {
1174 while (*s && isspace(*s)) s++;
1177 while (*s && !isspace(*s)) s++;
1183 execvp(Argv[0],Argv);
1184 if (errno == ENOEXEC) { /* for system V NIH syndrome */
1195 do_socket(stab, arglast)
1199 register STR **st = stack->ary_array;
1200 register int sp = arglast[1];
1201 register STIO *stio;
1202 int domain, type, protocol, fd;
1207 stio = stab_io(stab);
1209 stio = stab_io(stab) = stio_new();
1211 do_close(stab,FALSE);
1213 domain = (int)str_gnum(st[++sp]);
1214 type = (int)str_gnum(st[++sp]);
1215 protocol = (int)str_gnum(st[++sp]);
1217 taintproper("Insecure dependency in socket");
1219 fd = socket(domain,type,protocol);
1222 stio->ifp = fdopen(fd, "r"); /* stdio gets confused about sockets */
1223 stio->ofp = fdopen(fd, "w");
1230 do_bind(stab, arglast)
1234 register STR **st = stack->ary_array;
1235 register int sp = arglast[1];
1236 register STIO *stio;
1242 stio = stab_io(stab);
1243 if (!stio || !stio->ifp)
1246 addr = str_get(st[++sp]);
1248 taintproper("Insecure dependency in bind");
1250 return bind(fileno(stio->ifp), addr, st[sp]->str_cur) >= 0;
1254 warn("bind() on closed fd");
1260 do_connect(stab, arglast)
1264 register STR **st = stack->ary_array;
1265 register int sp = arglast[1];
1266 register STIO *stio;
1272 stio = stab_io(stab);
1273 if (!stio || !stio->ifp)
1276 addr = str_get(st[++sp]);
1278 taintproper("Insecure dependency in connect");
1280 return connect(fileno(stio->ifp), addr, st[sp]->str_cur) >= 0;
1284 warn("connect() on closed fd");
1290 do_listen(stab, arglast)
1294 register STR **st = stack->ary_array;
1295 register int sp = arglast[1];
1296 register STIO *stio;
1302 stio = stab_io(stab);
1303 if (!stio || !stio->ifp)
1306 backlog = (int)str_gnum(st[++sp]);
1307 return listen(fileno(stio->ifp), backlog) >= 0;
1311 warn("listen() on closed fd");
1316 do_accept(str, nstab, gstab)
1321 register STIO *nstio;
1322 register STIO *gstio;
1323 int len = sizeof buf;
1331 gstio = stab_io(gstab);
1332 nstio = stab_io(nstab);
1334 if (!gstio || !gstio->ifp)
1337 nstio = stab_io(nstab) = stio_new();
1338 else if (nstio->ifp)
1339 do_close(nstab,FALSE);
1341 fd = accept(fileno(gstio->ifp),buf,&len);
1344 nstio->ifp = fdopen(fd, "r");
1345 nstio->ofp = fdopen(fd, "w");
1348 str_nset(str, buf, len);
1353 warn("accept() on closed fd");
1355 str_sset(str,&str_undef);
1360 do_shutdown(stab, arglast)
1364 register STR **st = stack->ary_array;
1365 register int sp = arglast[1];
1366 register STIO *stio;
1372 stio = stab_io(stab);
1373 if (!stio || !stio->ifp)
1376 how = (int)str_gnum(st[++sp]);
1377 return shutdown(fileno(stio->ifp), how) >= 0;
1381 warn("shutdown() on closed fd");
1387 do_sopt(optype, stab, arglast)
1392 register STR **st = stack->ary_array;
1393 register int sp = arglast[1];
1394 register STIO *stio;
1402 stio = stab_io(stab);
1403 if (!stio || !stio->ifp)
1406 fd = fileno(stio->ifp);
1407 lvl = (int)str_gnum(st[sp+1]);
1408 optname = (int)str_gnum(st[sp+2]);
1411 st[sp] = str_2static(str_new(257));
1412 st[sp]->str_cur = 256;
1413 st[sp]->str_pok = 1;
1414 if (getsockopt(fd, lvl, optname, st[sp]->str_ptr, &st[sp]->str_cur) < 0)
1419 if (setsockopt(fd, lvl, optname, st[sp]->str_ptr, st[sp]->str_cur) < 0)
1429 warn("[gs]etsockopt() on closed fd");
1430 st[sp] = &str_undef;
1436 do_getsockname(optype, stab, arglast)
1441 register STR **st = stack->ary_array;
1442 register int sp = arglast[1];
1443 register STIO *stio;
1449 stio = stab_io(stab);
1450 if (!stio || !stio->ifp)
1453 st[sp] = str_2static(str_new(257));
1454 st[sp]->str_cur = 256;
1455 st[sp]->str_pok = 1;
1456 fd = fileno(stio->ifp);
1459 if (getsockname(fd, st[sp]->str_ptr, &st[sp]->str_cur) < 0)
1463 if (getpeername(fd, st[sp]->str_ptr, &st[sp]->str_cur) < 0)
1472 warn("get{sock,peer}name() on closed fd");
1474 st[sp] = &str_undef;
1480 do_ghent(which,gimme,arglast)
1485 register ARRAY *ary = stack;
1486 register int sp = arglast[0];
1487 register char **elem;
1489 struct hostent *gethostbyname();
1490 struct hostent *gethostbyaddr();
1492 struct hostent *gethostent();
1494 struct hostent *hent;
1497 if (gimme != G_ARRAY) {
1498 astore(ary, ++sp, str_static(&str_undef));
1502 if (which == O_GHBYNAME) {
1503 char *name = str_get(ary->ary_array[sp+1]);
1505 hent = gethostbyname(name);
1507 else if (which == O_GHBYADDR) {
1508 STR *addrstr = ary->ary_array[sp+1];
1509 int addrtype = (int)str_gnum(ary->ary_array[sp+2]);
1510 char *addr = str_get(addrstr);
1512 hent = gethostbyaddr(addr,addrstr->str_cur,addrtype);
1516 hent = gethostent();
1518 fatal("gethostent not implemented");
1522 (void)astore(ary, ++sp, str = str_static(&str_no));
1523 str_set(str, hent->h_name);
1524 (void)astore(ary, ++sp, str = str_static(&str_no));
1525 for (elem = hent->h_aliases; *elem; elem++) {
1526 str_cat(str, *elem);
1528 str_ncat(str," ",1);
1530 (void)astore(ary, ++sp, str = str_static(&str_no));
1531 str_numset(str, (double)hent->h_addrtype);
1532 (void)astore(ary, ++sp, str = str_static(&str_no));
1533 len = hent->h_length;
1534 str_numset(str, (double)len);
1536 for (elem = hent->h_addr_list; *elem; elem++) {
1537 (void)astore(ary, ++sp, str = str_static(&str_no));
1538 str_nset(str, *elem, len);
1541 (void)astore(ary, ++sp, str = str_static(&str_no));
1542 str_nset(str, hent->h_addr, len);
1547 (void)astore(ary, ++sp, str_static(&str_no));
1555 do_gnent(which,gimme,arglast)
1560 register ARRAY *ary = stack;
1561 register int sp = arglast[0];
1562 register char **elem;
1564 struct netent *getnetbyname();
1565 struct netent *getnetbyaddr();
1566 struct netent *getnetent();
1567 struct netent *nent;
1569 if (gimme != G_ARRAY) {
1570 astore(ary, ++sp, str_static(&str_undef));
1574 if (which == O_GNBYNAME) {
1575 char *name = str_get(ary->ary_array[sp+1]);
1577 nent = getnetbyname(name);
1579 else if (which == O_GNBYADDR) {
1580 STR *addrstr = ary->ary_array[sp+1];
1581 int addrtype = (int)str_gnum(ary->ary_array[sp+2]);
1582 char *addr = str_get(addrstr);
1584 nent = getnetbyaddr(addr,addrtype);
1591 (void)astore(ary, ++sp, str = str_static(&str_no));
1592 str_set(str, nent->n_name);
1593 (void)astore(ary, ++sp, str = str_static(&str_no));
1594 for (elem = nent->n_aliases; *elem; elem++) {
1595 str_cat(str, *elem);
1597 str_ncat(str," ",1);
1599 (void)astore(ary, ++sp, str = str_static(&str_no));
1600 str_numset(str, (double)nent->n_addrtype);
1601 (void)astore(ary, ++sp, str = str_static(&str_no));
1602 str_numset(str, (double)nent->n_net);
1606 (void)astore(ary, ++sp, str_static(&str_no));
1614 do_gpent(which,gimme,arglast)
1619 register ARRAY *ary = stack;
1620 register int sp = arglast[0];
1621 register char **elem;
1623 struct protoent *getprotobyname();
1624 struct protoent *getprotobynumber();
1625 struct protoent *getprotoent();
1626 struct protoent *pent;
1628 if (gimme != G_ARRAY) {
1629 astore(ary, ++sp, str_static(&str_undef));
1633 if (which == O_GPBYNAME) {
1634 char *name = str_get(ary->ary_array[sp+1]);
1636 pent = getprotobyname(name);
1638 else if (which == O_GPBYNUMBER) {
1639 int proto = (int)str_gnum(ary->ary_array[sp+1]);
1641 pent = getprotobynumber(proto);
1644 pent = getprotoent();
1648 (void)astore(ary, ++sp, str = str_static(&str_no));
1649 str_set(str, pent->p_name);
1650 (void)astore(ary, ++sp, str = str_static(&str_no));
1651 for (elem = pent->p_aliases; *elem; elem++) {
1652 str_cat(str, *elem);
1654 str_ncat(str," ",1);
1656 (void)astore(ary, ++sp, str = str_static(&str_no));
1657 str_numset(str, (double)pent->p_proto);
1661 (void)astore(ary, ++sp, str_static(&str_no));
1669 do_gsent(which,gimme,arglast)
1674 register ARRAY *ary = stack;
1675 register int sp = arglast[0];
1676 register char **elem;
1678 struct servent *getservbyname();
1679 struct servent *getservbynumber();
1680 struct servent *getservent();
1681 struct servent *sent;
1683 if (gimme != G_ARRAY) {
1684 astore(ary, ++sp, str_static(&str_undef));
1688 if (which == O_GSBYNAME) {
1689 char *name = str_get(ary->ary_array[sp+1]);
1690 char *proto = str_get(ary->ary_array[sp+2]);
1692 if (proto && !*proto)
1695 sent = getservbyname(name,proto);
1697 else if (which == O_GSBYPORT) {
1698 int port = (int)str_gnum(ary->ary_array[sp+1]);
1699 char *proto = str_get(ary->ary_array[sp+2]);
1701 sent = getservbyport(port,proto);
1704 sent = getservent();
1707 (void)astore(ary, ++sp, str = str_static(&str_no));
1708 str_set(str, sent->s_name);
1709 (void)astore(ary, ++sp, str = str_static(&str_no));
1710 for (elem = sent->s_aliases; *elem; elem++) {
1711 str_cat(str, *elem);
1713 str_ncat(str," ",1);
1715 (void)astore(ary, ++sp, str = str_static(&str_no));
1717 str_numset(str, (double)ntohs(sent->s_port));
1719 str_numset(str, (double)(sent->s_port));
1721 (void)astore(ary, ++sp, str = str_static(&str_no));
1722 str_set(str, sent->s_proto);
1726 (void)astore(ary, ++sp, str_static(&str_no));
1737 do_select(gimme,arglast)
1741 register STR **st = stack->ary_array;
1742 register int sp = arglast[0];
1750 struct timeval timebuf;
1751 struct timeval *tbuf = &timebuf;
1753 #if BYTEORDER != 0x1234 && BYTEORDER != 0x12345678
1759 #if BYTEORDER & 0xf0000
1760 #define ORDERBYTE (0x88888888 - BYTEORDER)
1762 #define ORDERBYTE (0x4444 - BYTEORDER)
1767 for (i = 1; i <= 3; i++) {
1768 j = st[sp+i]->str_cur;
1773 #if BYTEORDER == 0x1234 || BYTEORDER == 0x12345678
1774 growsize = maxlen; /* little endians can use vecs directly */
1782 masksize = NFDBITS / NBBY;
1784 masksize = sizeof(long); /* documented int, everyone seems to use long */
1786 growsize = maxlen + (masksize - (maxlen % masksize));
1787 Zero(&fd_sets[0], 4, char*);
1790 for (i = 1; i <= 3; i++) {
1795 Str_Grow(str,growsize);
1796 s = str_get(str) + j;
1797 while (++j <= growsize) {
1801 else if (str->str_ptr) {
1802 Safefree(str->str_ptr);
1803 str->str_ptr = Nullch;
1806 #if BYTEORDER != 0x1234 && BYTEORDER != 0x12345678
1809 New(403, fd_sets[i], growsize, char);
1810 for (offset = 0; offset < growsize; offset += masksize) {
1811 for (j = 0, k=ORDERBYTE; j < masksize; j++, (k >>= 4))
1812 fd_sets[i][j+offset] = s[(k % masksize) + offset];
1818 if (str->str_nok || str->str_pok) {
1819 value = str_gnum(str);
1822 timebuf.tv_sec = (long)value;
1823 value -= (double)timebuf.tv_sec;
1824 timebuf.tv_usec = (long)(value * 1000000.0);
1827 tbuf = Null(struct timeval*);
1829 #if BYTEORDER == 0x1234 || BYTEORDER == 0x12345678
1843 for (i = 1; i <= 3; i++) {
1847 for (offset = 0; offset < growsize; offset += masksize) {
1848 for (j = 0, k=ORDERBYTE; j < masksize; j++, (k >>= 4))
1849 s[(k % masksize) + offset] = fd_sets[i][j+offset];
1855 st[++sp] = str_static(&str_no);
1856 str_numset(st[sp], (double)nfound);
1857 if (gimme == G_ARRAY && tbuf) {
1858 value = (double)(timebuf.tv_sec) +
1859 (double)(timebuf.tv_usec) / 1000000.0;
1860 st[++sp] = str_static(&str_no);
1861 str_numset(st[sp], value);
1869 do_spair(stab1, stab2, arglast)
1874 register STR **st = stack->ary_array;
1875 register int sp = arglast[2];
1876 register STIO *stio1;
1877 register STIO *stio2;
1878 int domain, type, protocol, fd[2];
1880 if (!stab1 || !stab2)
1883 stio1 = stab_io(stab1);
1884 stio2 = stab_io(stab2);
1886 stio1 = stab_io(stab1) = stio_new();
1887 else if (stio1->ifp)
1888 do_close(stab1,FALSE);
1890 stio2 = stab_io(stab2) = stio_new();
1891 else if (stio2->ifp)
1892 do_close(stab2,FALSE);
1894 domain = (int)str_gnum(st[++sp]);
1895 type = (int)str_gnum(st[++sp]);
1896 protocol = (int)str_gnum(st[++sp]);
1898 taintproper("Insecure dependency in socketpair");
1901 if (socketpair(domain,type,protocol,fd) < 0)
1904 fatal("Socketpair unimplemented");
1906 stio1->ifp = fdopen(fd[0], "r");
1907 stio1->ofp = fdopen(fd[0], "w");
1909 stio2->ifp = fdopen(fd[1], "r");
1910 stio2->ofp = fdopen(fd[1], "w");
1919 do_gpwent(which,gimme,arglast)
1925 register ARRAY *ary = stack;
1926 register int sp = arglast[0];
1928 struct passwd *getpwnam();
1929 struct passwd *getpwuid();
1930 struct passwd *getpwent();
1931 struct passwd *pwent;
1933 if (gimme != G_ARRAY) {
1934 astore(ary, ++sp, str_static(&str_undef));
1938 if (which == O_GPWNAM) {
1939 char *name = str_get(ary->ary_array[sp+1]);
1941 pwent = getpwnam(name);
1943 else if (which == O_GPWUID) {
1944 int uid = (int)str_gnum(ary->ary_array[sp+1]);
1946 pwent = getpwuid(uid);
1952 (void)astore(ary, ++sp, str = str_static(&str_no));
1953 str_set(str, pwent->pw_name);
1954 (void)astore(ary, ++sp, str = str_static(&str_no));
1955 str_set(str, pwent->pw_passwd);
1956 (void)astore(ary, ++sp, str = str_static(&str_no));
1957 str_numset(str, (double)pwent->pw_uid);
1958 (void)astore(ary, ++sp, str = str_static(&str_no));
1959 str_numset(str, (double)pwent->pw_gid);
1960 (void)astore(ary, ++sp, str = str_static(&str_no));
1962 str_numset(str, (double)pwent->pw_change);
1965 str_numset(str, (double)pwent->pw_quota);
1968 str_set(str, pwent->pw_age);
1972 (void)astore(ary, ++sp, str = str_static(&str_no));
1974 str_set(str,pwent->pw_class);
1977 str_set(str, pwent->pw_comment);
1980 (void)astore(ary, ++sp, str = str_static(&str_no));
1981 str_set(str, pwent->pw_gecos);
1982 (void)astore(ary, ++sp, str = str_static(&str_no));
1983 str_set(str, pwent->pw_dir);
1984 (void)astore(ary, ++sp, str = str_static(&str_no));
1985 str_set(str, pwent->pw_shell);
1987 (void)astore(ary, ++sp, str = str_static(&str_no));
1988 str_numset(str, (double)pwent->pw_expire);
1994 fatal("password routines not implemented");
1999 do_ggrent(which,gimme,arglast)
2005 register ARRAY *ary = stack;
2006 register int sp = arglast[0];
2007 register char **elem;
2009 struct group *getgrnam();
2010 struct group *getgrgid();
2011 struct group *getgrent();
2012 struct group *grent;
2014 if (gimme != G_ARRAY) {
2015 astore(ary, ++sp, str_static(&str_undef));
2019 if (which == O_GGRNAM) {
2020 char *name = str_get(ary->ary_array[sp+1]);
2022 grent = getgrnam(name);
2024 else if (which == O_GGRGID) {
2025 int gid = (int)str_gnum(ary->ary_array[sp+1]);
2027 grent = getgrgid(gid);
2033 (void)astore(ary, ++sp, str = str_static(&str_no));
2034 str_set(str, grent->gr_name);
2035 (void)astore(ary, ++sp, str = str_static(&str_no));
2036 str_set(str, grent->gr_passwd);
2037 (void)astore(ary, ++sp, str = str_static(&str_no));
2038 str_numset(str, (double)grent->gr_gid);
2039 (void)astore(ary, ++sp, str = str_static(&str_no));
2040 for (elem = grent->gr_mem; *elem; elem++) {
2041 str_cat(str, *elem);
2043 str_ncat(str," ",1);
2049 fatal("group routines not implemented");
2054 do_dirop(optype,stab,gimme,arglast)
2060 #if defined(DIRENT) && defined(READDIR)
2061 register ARRAY *ary = stack;
2062 register STR **st = ary->ary_array;
2063 register int sp = arglast[1];
2064 register STIO *stio;
2069 struct DIRENT *readdir();
2070 register struct DIRENT *dp;
2074 if (!(stio = stab_io(stab)))
2075 stio = stab_io(stab) = stio_new();
2076 if (!stio->dirp && optype != O_OPENDIR)
2082 closedir(stio->dirp);
2083 if (!(stio->dirp = opendir(str_get(st[sp+1]))))
2087 if (gimme == G_ARRAY) {
2089 while (dp = readdir(stio->dirp)) {
2091 (void)astore(ary,++sp,
2092 str_2static(str_make(dp->d_name,dp->d_namlen)));
2094 (void)astore(ary,++sp,
2095 str_2static(str_make(dp->d_name,0)));
2100 if (!(dp = readdir(stio->dirp)))
2102 st[sp] = str_static(&str_undef);
2104 str_nset(st[sp], dp->d_name, dp->d_namlen);
2106 str_set(st[sp], dp->d_name);
2116 st[sp] = str_static(&str_undef);
2117 str_numset(st[sp], (double)telldir(stio->dirp));
2120 st[sp] = str_static(&str_undef);
2121 along = (long)str_gnum(st[sp+1]);
2122 (void)seekdir(stio->dirp,along);
2126 st[sp] = str_static(&str_undef);
2127 (void)rewinddir(stio->dirp);
2130 st[sp] = str_static(&str_undef);
2131 (void)closedir(stio->dirp);
2138 st[sp] = &str_undef;
2142 fatal("Unimplemented directory operation");
2150 register STR **st = stack->ary_array;
2151 register int sp = arglast[1];
2152 register int items = arglast[2] - sp;
2155 register int tot = 0;
2159 for (st += ++sp; items--; st++)
2160 tainted |= (*st)->str_tainted;
2161 st = stack->ary_array;
2163 items = arglast[2] - sp;
2168 taintproper("Insecure dependency in chmod");
2172 val = (int)str_gnum(st[++sp]);
2174 if (chmod(str_get(st[++sp]),val))
2182 taintproper("Insecure dependency in chown");
2187 val = (int)str_gnum(st[++sp]);
2188 val2 = (int)str_gnum(st[++sp]);
2190 if (chown(str_get(st[++sp]),val,val2))
2199 taintproper("Insecure dependency in kill");
2203 s = str_get(st[++sp]);
2205 if (*s == 'S' && s[1] == 'I' && s[2] == 'G')
2207 if (!(val = whichsig(s)))
2208 fatal("Unrecognized signal name \"%s\"",s);
2211 val = (int)str_gnum(st[sp]);
2215 int proc = (int)str_gnum(st[++sp]);
2217 if (killpg(proc,val)) /* BSD */
2219 if (kill(-proc,val)) /* SYSV */
2226 if (kill((int)(str_gnum(st[++sp])),val))
2235 taintproper("Insecure dependency in unlink");
2239 s = str_get(st[++sp]);
2240 if (euid || unsafe) {
2244 else { /* don't let root wipe out directories without -U */
2246 if (lstat(s,&statbuf) < 0 ||
2248 if (stat(s,&statbuf) < 0 ||
2250 (statbuf.st_mode & S_IFMT) == S_IFDIR )
2261 taintproper("Insecure dependency in utime");
2265 struct utimbuf utbuf;
2273 Zero(&utbuf, sizeof utbuf, char);
2274 utbuf.actime = (long)str_gnum(st[++sp]); /* time accessed */
2275 utbuf.modtime = (long)str_gnum(st[++sp]); /* time modified */
2280 if (utime(str_get(st[++sp]),&utbuf))
2292 /* Do the permissions allow some operation? Assumes statcache already set. */
2295 cando(bit, effective, statbufp)
2298 register struct stat *statbufp;
2300 if ((effective ? euid : uid) == 0) { /* root is special */
2301 if (bit == S_IEXEC) {
2302 if (statbufp->st_mode & 0111 ||
2303 (statbufp->st_mode & S_IFMT) == S_IFDIR )
2307 return TRUE; /* root reads and writes anything */
2310 if (statbufp->st_uid == (effective ? euid : uid) ) {
2311 if (statbufp->st_mode & bit)
2312 return TRUE; /* ok as "user" */
2314 else if (ingroup((int)statbufp->st_gid,effective)) {
2315 if (statbufp->st_mode & bit >> 3)
2316 return TRUE; /* ok as "group" */
2318 else if (statbufp->st_mode & bit >> 6)
2319 return TRUE; /* ok as "other" */
2324 ingroup(testgid,effective)
2328 if (testgid == (effective ? egid : gid))
2335 GIDTYPE gary[NGROUPS];
2338 anum = getgroups(NGROUPS,gary);
2340 if (gary[anum] == testgid)
2350 do_ipcget(optype, arglast)
2354 register STR **st = stack->ary_array;
2355 register int sp = arglast[0];
2359 key = (key_t)str_gnum(st[++sp]);
2360 n = (optype == O_MSGGET) ? 0 : (int)str_gnum(st[++sp]);
2361 flags = (int)str_gnum(st[++sp]);
2367 return msgget(key, flags);
2371 return semget(key, n, flags);
2375 return shmget(key, n, flags);
2377 #if !defined(IPCMSG) || !defined(IPCSEM) || !defined(IPCSHM)
2379 fatal("%s not implemented", opname[optype]);
2382 return -1; /* should never happen */
2386 do_ipcctl(optype, arglast)
2390 register STR **st = stack->ary_array;
2391 register int sp = arglast[0];
2394 int id, n, cmd, infosize, getinfo, ret;
2396 id = (int)str_gnum(st[++sp]);
2397 n = (optype == O_SEMCTL) ? (int)str_gnum(st[++sp]) : 0;
2398 cmd = (int)str_gnum(st[++sp]);
2402 getinfo = (cmd == IPC_STAT);
2408 if (cmd == IPC_STAT || cmd == IPC_SET)
2409 infosize = sizeof(struct msqid_ds);
2414 if (cmd == IPC_STAT || cmd == IPC_SET)
2415 infosize = sizeof(struct shmid_ds);
2420 if (cmd == IPC_STAT || cmd == IPC_SET)
2421 infosize = sizeof(struct semid_ds);
2422 else if (cmd == GETALL || cmd == SETALL)
2424 struct semid_ds semds;
2425 if (semctl(id, 0, IPC_STAT, &semds) == -1)
2427 getinfo = (cmd == GETALL);
2428 infosize = semds.sem_nsems * sizeof(ushort);
2432 #if !defined(IPCMSG) || !defined(IPCSEM) || !defined(IPCSHM)
2434 fatal("%s not implemented", opname[optype]);
2442 STR_GROW(astr, infosize+1);
2448 if (astr->str_cur != infosize)
2457 int i = (int)str_gnum(astr);
2458 a = (char *)i; /* ouch */
2465 ret = msgctl(id, cmd, a);
2470 ret = semctl(id, n, cmd, a);
2475 ret = shmctl(id, cmd, a);
2479 if (getinfo && ret >= 0) {
2480 astr->str_cur = infosize;
2481 astr->str_ptr[infosize] = '\0';
2491 register STR **st = stack->ary_array;
2492 register int sp = arglast[0];
2495 int id, msize, flags;
2497 id = (int)str_gnum(st[++sp]);
2499 flags = (int)str_gnum(st[++sp]);
2500 mbuf = str_get(mstr);
2501 if ((msize = mstr->str_cur - sizeof(long)) < 0) {
2506 return msgsnd(id, mbuf, msize, flags);
2508 fatal("msgsnd not implemented");
2517 register STR **st = stack->ary_array;
2518 register int sp = arglast[0];
2522 int id, msize, flags, ret;
2524 id = (int)str_gnum(st[++sp]);
2526 msize = (int)str_gnum(st[++sp]);
2527 mtype = (long)str_gnum(st[++sp]);
2528 flags = (int)str_gnum(st[++sp]);
2529 mbuf = str_get(mstr);
2530 if (mstr->str_cur < sizeof(long)+msize+1) {
2531 STR_GROW(mstr, sizeof(long)+msize+1);
2532 mbuf = str_get(mstr);
2535 ret = msgrcv(id, mbuf, msize, mtype, flags);
2537 mstr->str_cur = sizeof(long)+ret;
2538 mstr->str_ptr[sizeof(long)+ret] = '\0';
2542 fatal("msgrcv not implemented");
2551 register STR **st = stack->ary_array;
2552 register int sp = arglast[0];
2557 id = (int)str_gnum(st[++sp]);
2559 opbuf = str_get(opstr);
2560 opsize = opstr->str_cur;
2561 if (opsize < sizeof(struct sembuf)
2562 || (opsize % sizeof(struct sembuf)) != 0) {
2567 return semop(id, opbuf, opsize/sizeof(struct sembuf));
2569 fatal("semop not implemented");
2574 do_shmio(optype, arglast)
2579 register STR **st = stack->ary_array;
2580 register int sp = arglast[0];
2583 int id, mpos, msize;
2584 struct shmid_ds shmds;
2585 extern char *shmat();
2587 id = (int)str_gnum(st[++sp]);
2589 mpos = (int)str_gnum(st[++sp]);
2590 msize = (int)str_gnum(st[++sp]);
2592 if (shmctl(id, IPC_STAT, &shmds) == -1)
2594 if (mpos < 0 || msize < 0 || mpos + msize > shmds.shm_segsz) {
2595 errno = EFAULT; /* can't do as caller requested */
2598 shm = shmat(id, (char *)NULL, (optype == O_SHMREAD) ? SHM_RDONLY : 0);
2599 if (shm == (char *)-1) /* I hate System V IPC, I really do */
2601 mbuf = str_get(mstr);
2602 if (optype == O_SHMREAD) {
2603 if (mstr->str_cur < msize) {
2604 STR_GROW(mstr, msize+1);
2605 mbuf = str_get(mstr);
2607 bcopy(shm + mpos, mbuf, msize);
2608 mstr->str_cur = msize;
2609 mstr->str_ptr[msize] = '\0';
2614 if ((n = mstr->str_cur) > msize)
2616 bcopy(mbuf, shm + mpos, n);
2618 bzero(shm + mpos + n, msize - n);
2622 fatal("shm I/O not implemented");
2626 #endif /* SYSVIPC */