1 /* $Header: doio.c,v 3.0.1.12 90/10/20 02:04:18 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.12 90/10/20 02:04:18 lwall
10 * patch37: split out separate Sys V IPC features
12 * Revision 3.0.1.11 90/10/15 16:16:11 lwall
13 * patch29: added SysV IPC
14 * patch29: file - didn't auto-close cleanly
15 * patch29: close; core dumped
16 * patch29: more MSDOS and OS/2 updates, from Kai Uwe Rommel
17 * patch29: various portability fixes
18 * patch29: *foo now prints as *package'foo
20 * Revision 3.0.1.10 90/08/13 22:14:29 lwall
21 * patch28: close-on-exec problems on dup'ed file descriptors
22 * patch28: F_FREESP wasn't implemented the way I thought
24 * Revision 3.0.1.9 90/08/09 02:56:19 lwall
25 * patch19: various MSDOS and OS/2 patches folded in
26 * patch19: prints now check error status better
27 * patch19: printing a list with null elements only printed front of list
28 * patch19: on machines with vfork child would allocate memory in parent
29 * patch19: getsockname and getpeername gave bogus warning on error
30 * patch19: MACH doesn't have seekdir or telldir
32 * Revision 3.0.1.8 90/03/27 15:44:02 lwall
33 * patch16: MSDOS support
34 * patch16: support for machines that can't cast negative floats to unsigned ints
35 * patch16: system() can lose arguments passed to shell scripts on SysV machines
37 * Revision 3.0.1.7 90/03/14 12:26:24 lwall
38 * patch15: commands involving execs could cause malloc arena corruption
40 * Revision 3.0.1.6 90/03/12 16:30:07 lwall
41 * patch13: system 'FOO=bar command' didn't invoke sh as it should
43 * Revision 3.0.1.5 90/02/28 17:01:36 lwall
44 * patch9: open(FOO,"$filename\0") will now protect trailing spaces in filename
45 * patch9: removed obsolete checks to avoid opening block devices
46 * patch9: removed references to acusec and modusec that some utime.h's have
47 * patch9: added pipe function
49 * Revision 3.0.1.4 89/12/21 19:55:10 lwall
50 * patch7: select now works on big-endian machines
51 * patch7: errno may now be a macro with an lvalue
52 * patch7: ANSI strerror() is now supported
53 * patch7: Configure now detects DG/UX thingies like [sg]etpgrp2 and utime.h
55 * Revision 3.0.1.3 89/11/17 15:13:06 lwall
56 * patch5: some systems have symlink() but not lstat()
57 * patch5: some systems have dirent.h but not readdir()
59 * Revision 3.0.1.2 89/11/11 04:25:51 lwall
60 * patch2: orthogonalized the file modes some so we can have <& +<& etc.
61 * patch2: do_open() now detects sockets passed to process from parent
62 * patch2: fd's above 2 are now closed on exec
63 * patch2: csh code can now use csh from other than /bin
64 * patch2: getsockopt, get{sock,peer}name didn't define result properly
65 * patch2: warn("shutdown") was replicated
66 * patch2: gethostbyname was misdeclared
67 * patch2: telldir() is sometimes a macro
69 * Revision 3.0.1.1 89/10/26 23:10:05 lwall
70 * patch1: Configure now checks for BSD shadow passwords
72 * Revision 3.0 89/10/18 15:10:54 lwall
81 #include <sys/socket.h>
85 #if defined(SELECT) && (defined(M_UNIX) || defined(M_XENIX))
86 #include <sys/select.h>
116 do_open(stab,name,len)
122 register STIO *stio = stab_io(stab);
123 char *myname = savestr(name);
127 char mode[3]; /* stdio file mode ("r\0" or "r+\0") */
130 forkprocess = 1; /* assume true if no fork */
131 while (len && isspace(name[len-1]))
134 stio = stab_io(stab) = stio_new();
135 else if (stio->ifp) {
136 fd = fileno(stio->ifp);
137 if (stio->type == '|')
138 result = mypclose(stio->ifp);
139 else if (stio->type == '-')
141 else if (stio->ifp != stio->ofp) {
143 result = fclose(stio->ofp);
144 fclose(stio->ifp); /* clear stdio, fd already closed */
147 result = fclose(stio->ifp);
150 result = fclose(stio->ifp);
151 if (result == EOF && fd > 2)
152 fprintf(stderr,"Warning: unable to close filehandle %s properly.\n",
154 stio->ofp = stio->ifp = Nullfp;
156 if (*name == '+' && len > 1 && name[len-1] != '|') { /* scary */
167 for (name++; isspace(*name); name++) ;
170 taintproper("Insecure dependency in piped open");
172 fp = mypopen(name,"w");
175 else if (*name == '>') {
177 taintproper("Insecure dependency in open");
181 mode[0] = stio->type = 'a';
190 while (isspace(*name))
195 stab = stabent(name,FALSE);
196 if (!stab || !stab_io(stab))
198 if (stab_io(stab) && stab_io(stab)->ifp) {
199 fd = fileno(stab_io(stab)->ifp);
200 if (stab_io(stab)->type == 's')
206 fp = fdopen(dup(fd),mode);
209 while (isspace(*name))
211 if (strEQ(name,"-")) {
216 fp = fopen(name,mode);
224 while (isspace(*name))
228 if (strEQ(name,"-")) {
233 fp = fopen(name,mode);
235 else if (name[len-1] == '|') {
238 taintproper("Insecure dependency in piped open");
241 while (len && isspace(name[len-1]))
243 for (; isspace(*name); name++) ;
244 fp = mypopen(name,"r");
249 for (; isspace(*name); name++) ;
250 if (strEQ(name,"-")) {
255 fp = fopen(name,"r");
262 stio->type != '|' && stio->type != '-') {
263 if (fstat(fileno(fp),&statbuf) < 0) {
267 result = (statbuf.st_mode & S_IFMT);
269 if (result == S_IFSOCK || result == 0)
270 stio->type = 's'; /* in case a socket was passed in to us */
273 #if defined(FCNTL) && defined(F_SETFD)
275 fcntl(fd,F_SETFD,fd >= 3);
279 if (stio->type != 's')
282 stio->ofp = fdopen(fileno(fp),"w");
293 int filemode,fileuid,filegid;
295 while (alen(stab_xarray(stab)) >= 0) {
296 str = ashift(stab_xarray(stab));
297 str_sset(stab_val(stab),str);
298 STABSET(stab_val(stab));
299 oldname = str_get(stab_val(stab));
300 if (do_open(stab,oldname,stab_val(stab)->str_cur)) {
303 taintproper("Insecure dependency in inplace open");
305 filemode = statbuf.st_mode;
306 fileuid = statbuf.st_uid;
307 filegid = statbuf.st_gid;
310 add_suffix(str,inplace);
312 str_cat(str,inplace);
316 (void)rename(oldname,str->str_ptr);
318 do_close(stab,FALSE);
319 (void)unlink(str->str_ptr);
320 (void)rename(oldname,str->str_ptr);
321 do_open(stab,str->str_ptr,stab_val(stab)->str_cur);
324 (void)UNLINK(str->str_ptr);
325 (void)link(oldname,str->str_ptr);
326 (void)UNLINK(oldname);
331 (void)UNLINK(oldname);
333 fatal("Can't do inplace edit without backup");
338 str_cat(str,oldname);
339 errno = 0; /* in case sprintf set errno */
340 if (!do_open(argvoutstab,str->str_ptr,str->str_cur))
341 fatal("Can't do inplace edit");
342 defoutstab = argvoutstab;
344 (void)fchmod(fileno(stab_io(argvoutstab)->ifp),filemode);
346 (void)chmod(oldname,filemode);
349 (void)fchown(fileno(stab_io(argvoutstab)->ifp),fileuid,filegid);
352 (void)chown(oldname,fileuid,filegid);
357 return stab_io(stab)->ifp;
360 fprintf(stderr,"Can't open %s\n",str_get(str));
364 (void)do_close(argvoutstab,FALSE);
365 defoutstab = stabent("STDOUT",TRUE);
372 do_pipe(str, rstab, wstab)
377 register STIO *rstio;
378 register STIO *wstio;
386 rstio = stab_io(rstab);
387 wstio = stab_io(wstab);
390 rstio = stab_io(rstab) = stio_new();
392 do_close(rstab,FALSE);
394 wstio = stab_io(wstab) = stio_new();
396 do_close(wstab,FALSE);
400 rstio->ifp = fdopen(fd[0], "r");
401 wstio->ofp = fdopen(fd[1], "w");
402 wstio->ifp = wstio->ofp;
406 str_sset(str,&str_yes);
410 str_sset(str,&str_undef);
416 do_close(stab,explicit)
428 stio = stab_io(stab);
429 if (!stio) { /* never opened */
430 if (dowarn && explicit)
431 warn("Close on unopened file <%s>",stab_name(stab));
435 if (stio->type == '|') {
436 status = mypclose(stio->ifp);
437 retval = (status >= 0);
438 statusvalue = (unsigned short)status & 0xffff;
440 else if (stio->type == '-')
443 if (stio->ofp && stio->ofp != stio->ifp) { /* a socket */
444 retval = (fclose(stio->ofp) != EOF);
445 fclose(stio->ifp); /* clear stdio, fd already closed */
448 retval = (fclose(stio->ifp) != EOF);
450 stio->ofp = stio->ifp = Nullfp;
465 if (!stab) { /* eof() */
467 stio = stab_io(argvstab);
472 stio = stab_io(stab);
479 #ifdef STDSTDIO /* (the code works without this) */
480 if (stio->ifp->_cnt > 0) /* cheat a little, since */
481 return FALSE; /* this is the most usual case */
484 ch = getc(stio->ifp);
486 (void)ungetc(ch, stio->ifp);
489 if (!stab) { /* not necessarily a real EOF yet? */
490 if (!nextargv(argvstab)) /* get another fp handy */
494 return TRUE; /* normal fp, definitely end of file */
508 stio = stab_io(stab);
509 if (!stio || !stio->ifp)
513 (void)fseek (stio->ifp, 0L, 2); /* ultrix 1.2 workaround */
515 return ftell(stio->ifp);
519 warn("tell() on unopened file");
524 do_seek(stab, pos, whence)
534 stio = stab_io(stab);
535 if (!stio || !stio->ifp)
539 (void)fseek (stio->ifp, 0L, 2); /* ultrix 1.2 workaround */
541 return fseek(stio->ifp, pos, whence) >= 0;
545 warn("seek() on unopened file");
550 do_ctl(optype,stab,func,argstr)
560 if (!stab || !argstr)
562 stio = stab_io(stab);
566 if (argstr->str_pok || !argstr->str_nok) {
567 if (!argstr->str_pok)
572 #define IOCPARM_LEN(x) (((x) >> 16) & IOCPARM_MASK)
576 retval = IOCPARM_LEN(func); /* on BSDish systes we're safe */
578 retval = 256; /* otherwise guess at what's safe */
580 if (argstr->str_cur < retval) {
581 Str_Grow(argstr,retval+1);
582 argstr->str_cur = retval;
586 s[argstr->str_cur] = 17; /* a little sanity check here */
589 retval = (int)str_gnum(argstr);
591 s = (char*)(long)retval; /* ouch */
593 s = (char*)retval; /* ouch */
598 if (optype == O_IOCTL)
599 retval = ioctl(fileno(stio->ifp), func, s);
602 retval = fcntl(fileno(stio->ifp), func, s);
604 fatal("fcntl is not implemented");
610 if (argstr->str_pok) {
611 if (s[argstr->str_cur] != 17)
612 fatal("Return value overflowed string");
613 s[argstr->str_cur] = 0; /* put our null back */
619 do_stat(str,arg,gimme,arglast)
625 register ARRAY *ary = stack;
626 register int sp = arglast[0] + 1;
630 if ((arg[1].arg_type & A_MASK) == A_WORD) {
631 tmpstab = arg[1].arg_ptr.arg_stab;
632 if (tmpstab != defstab) {
634 str_set(statname,"");
635 if (!stab_io(tmpstab) || !stab_io(tmpstab)->ifp ||
636 fstat(fileno(stab_io(tmpstab)->ifp),&statcache) < 0) {
642 str_sset(statname,ary->ary_array[sp]);
645 if (arg->arg_type == O_LSTAT)
646 i = lstat(str_get(statname),&statcache);
649 i = stat(str_get(statname),&statcache);
654 if (gimme != G_ARRAY) {
656 str_sset(str,&str_yes);
658 str_sset(str,&str_undef);
660 ary->ary_array[sp] = str;
666 (void)astore(ary,++sp,
667 str_2static(str_nmake((double)statcache.st_dev)));
668 (void)astore(ary,++sp,
669 str_2static(str_nmake((double)statcache.st_ino)));
670 (void)astore(ary,++sp,
671 str_2static(str_nmake((double)statcache.st_mode)));
672 (void)astore(ary,++sp,
673 str_2static(str_nmake((double)statcache.st_nlink)));
674 (void)astore(ary,++sp,
675 str_2static(str_nmake((double)statcache.st_uid)));
676 (void)astore(ary,++sp,
677 str_2static(str_nmake((double)statcache.st_gid)));
678 (void)astore(ary,++sp,
679 str_2static(str_nmake((double)statcache.st_rdev)));
680 (void)astore(ary,++sp,
681 str_2static(str_nmake((double)statcache.st_size)));
682 (void)astore(ary,++sp,
683 str_2static(str_nmake((double)statcache.st_atime)));
684 (void)astore(ary,++sp,
685 str_2static(str_nmake((double)statcache.st_mtime)));
686 (void)astore(ary,++sp,
687 str_2static(str_nmake((double)statcache.st_ctime)));
689 (void)astore(ary,++sp,
690 str_2static(str_nmake((double)statcache.st_blksize)));
691 (void)astore(ary,++sp,
692 str_2static(str_nmake((double)statcache.st_blocks)));
694 (void)astore(ary,++sp,
695 str_2static(str_make("",0)));
696 (void)astore(ary,++sp,
697 str_2static(str_make("",0)));
700 (void)astore(ary,++sp,str_nmake(0.0));
706 #if !defined(TRUNCATE) && !defined(CHSIZE) && defined(F_FREESP)
707 /* code courtesy of William Kucharski */
710 int chsize(fd, length)
711 int fd; /* file descriptor */
712 off_t length; /* length to set file to */
718 if (fstat(fd, &filebuf) < 0)
721 if (filebuf.st_size < length) {
723 /* extend file length */
725 if ((lseek(fd, (length - 1), 0)) < 0)
728 /* write a "0" byte */
730 if ((write(fd, "", 1)) != 1)
734 /* truncate length */
739 fl.l_type = F_WRLCK; /* write lock on file space */
742 * This relies on the UNDOCUMENTED F_FREESP argument to
743 * fcntl(2), which truncates the file so that it ends at the
744 * position indicated by fl.l_start.
746 * Will minor miracles never cease?
749 if (fcntl(fd, F_FREESP, &fl) < 0)
756 #endif /* F_FREESP */
759 do_truncate(str,arg,gimme,arglast)
765 register ARRAY *ary = stack;
766 register int sp = arglast[0] + 1;
767 off_t len = (off_t)str_gnum(ary->ary_array[sp+1]);
771 #if defined(TRUNCATE) || defined(CHSIZE)
773 if ((arg[1].arg_type & A_MASK) == A_WORD) {
774 tmpstab = arg[1].arg_ptr.arg_stab;
775 if (!stab_io(tmpstab) ||
776 ftruncate(fileno(stab_io(tmpstab)->ifp), len) < 0)
779 else if (truncate(str_get(ary->ary_array[sp]), len) < 0)
782 if ((arg[1].arg_type & A_MASK) == A_WORD) {
783 tmpstab = arg[1].arg_ptr.arg_stab;
784 if (!stab_io(tmpstab) ||
785 chsize(fileno(stab_io(tmpstab)->ifp), len) < 0)
791 if ((tmpfd = open(str_get(ary->ary_array[sp]), 0)) < 0)
794 if (chsize(tmpfd, len) < 0)
802 str_sset(str,&str_yes);
804 str_sset(str,&str_undef);
806 ary->ary_array[sp] = str;
809 fatal("truncate not implemented");
814 looks_like_number(str)
823 send = s + str->str_cur;
828 if (*s == '+' || *s == '-')
836 else if (s == str->str_ptr)
842 if (*s == 'e' || *s == 'E') {
844 if (*s == '+' || *s == '-')
865 warn("print to unopened file");
871 ((str->str_nok && str->str_u.str_nval != 0.0)
872 || (looks_like_number(str) && str_gnum(str) != 0.0) ) ) {
873 fprintf(fp, ofmt, str->str_u.str_nval);
878 if (*tmps == 'S' && tmps[1] == 't' && tmps[2] == 'B' && tmps[3] == '\0'
879 && str->str_cur == sizeof(STBP) && strlen(tmps) < str->str_cur) {
880 STR *tmpstr = str_static(&str_undef);
881 stab_fullname(tmpstr,((STAB*)str));/* a stab value, be nice */
886 if (str->str_cur && (fwrite(tmps,1,str->str_cur,fp) == 0 || ferror(fp)))
893 do_aprint(arg,fp,arglast)
898 register STR **st = stack->ary_array;
899 register int sp = arglast[1];
901 register int items = arglast[2] - sp;
905 warn("print to unopened file");
909 if (arg->arg_type == O_PRTF) {
910 do_sprintf(arg->arg_ptr.arg_str,items,st);
911 retval = do_print(arg->arg_ptr.arg_str,fp);
914 retval = (items <= 0);
915 for (; items > 0; items--,st++) {
916 if (retval && ofslen) {
917 if (fwrite(ofs, 1, ofslen, fp) == 0 || ferror(fp)) {
922 if (!(retval = do_print(*st, fp)))
925 if (retval && orslen)
926 if (fwrite(ors, 1, orslen, fp) == 0 || ferror(fp))
939 if (arg[1].arg_type & A_DONT) {
940 stio = stab_io(arg[1].arg_ptr.arg_stab);
941 if (stio && stio->ifp) {
942 statstab = arg[1].arg_ptr.arg_stab;
943 str_set(statname,"");
944 return fstat(fileno(stio->ifp), &statcache);
947 if (arg[1].arg_ptr.arg_stab == defstab)
950 warn("Stat on unopened file <%s>",
951 stab_name(arg[1].arg_ptr.arg_stab));
953 str_set(statname,"");
959 str_sset(statname,str);
960 return stat(str_get(str),&statcache);
976 if (arg[1].arg_type & A_DONT) {
977 if (arg[1].arg_ptr.arg_stab == defstab) {
979 stio = stab_io(statstab);
982 goto really_filename;
986 statstab = arg[1].arg_ptr.arg_stab;
987 str_set(statname,"");
988 stio = stab_io(statstab);
990 if (stio && stio->ifp) {
992 fstat(fileno(stio->ifp),&statcache);
993 if (stio->ifp->_cnt <= 0) {
996 (void)ungetc(i,stio->ifp);
998 if (stio->ifp->_cnt <= 0) /* null file is anything */
1000 len = stio->ifp->_cnt + (stio->ifp->_ptr - stio->ifp->_base);
1001 s = stio->ifp->_base;
1003 fatal("-T and -B not implemented on filehandles\n");
1008 warn("Test on unopened file <%s>",
1009 stab_name(arg[1].arg_ptr.arg_stab));
1014 statstab = Nullstab;
1015 str_sset(statname,str);
1017 i = open(str_get(str),0);
1020 fstat(i,&statcache);
1021 len = read(i,tbuf,512);
1022 if (len <= 0) /* null file is anything */
1028 /* now scan s to look for textiness */
1030 for (i = 0; i < len; i++,s++) {
1031 if (!*s) { /* null never allowed in text */
1038 *s != '\n' && *s != '\r' && *s != '\b' &&
1039 *s != '\t' && *s != '\f' && *s != 27)
1043 if ((odd * 10 > len) == (arg->arg_type == O_FTTEXT)) /* allow 10% odd */
1050 do_aexec(really,arglast)
1054 register STR **st = stack->ary_array;
1055 register int sp = arglast[1];
1056 register int items = arglast[2] - sp;
1062 New(401,argv, items+1, char*);
1064 for (st += ++sp; items > 0; items--,st++) {
1066 *a++ = str_get(*st);
1072 if (*argv[0] != '/') /* will execvp use PATH? */
1073 taintenv(); /* testing IFS here is overkill, probably */
1075 if (really && *(tmps = str_get(really)))
1078 execvp(argv[0],argv);
1084 static char **Argv = Null(char **);
1085 static char *Cmd = Nullch;
1092 Argv = Null(char **);
1110 taintproper("Insecure dependency in exec");
1113 /* save an extra exec if possible */
1116 if (strnEQ(cmd,cshname,cshlen) && strnEQ(cmd+cshlen," -c",3)) {
1132 if (s[-1] == '\'') {
1134 execl(cshname,"csh", flags,ncmd,(char*)0);
1142 /* see if there are shell metacharacters in it */
1144 for (s = cmd; *s && isalpha(*s); s++) ; /* catch VAR=val gizmo */
1147 for (s = cmd; *s; s++) {
1148 if (*s != ' ' && !isalpha(*s) && index("$&*(){}[]'\";\\|?<>~`\n",*s)) {
1149 if (*s == '\n' && !s[1]) {
1154 execl("/bin/sh","sh","-c",cmd,(char*)0);
1158 New(402,Argv, (s - cmd) / 2 + 2, char*);
1159 Cmd = nsavestr(cmd, s-cmd);
1161 for (s = Cmd; *s;) {
1162 while (*s && isspace(*s)) s++;
1165 while (*s && !isspace(*s)) s++;
1171 execvp(Argv[0],Argv);
1172 if (errno == ENOEXEC) { /* for system V NIH syndrome */
1183 do_socket(stab, arglast)
1187 register STR **st = stack->ary_array;
1188 register int sp = arglast[1];
1189 register STIO *stio;
1190 int domain, type, protocol, fd;
1195 stio = stab_io(stab);
1197 stio = stab_io(stab) = stio_new();
1199 do_close(stab,FALSE);
1201 domain = (int)str_gnum(st[++sp]);
1202 type = (int)str_gnum(st[++sp]);
1203 protocol = (int)str_gnum(st[++sp]);
1205 taintproper("Insecure dependency in socket");
1207 fd = socket(domain,type,protocol);
1210 stio->ifp = fdopen(fd, "r"); /* stdio gets confused about sockets */
1211 stio->ofp = fdopen(fd, "w");
1218 do_bind(stab, arglast)
1222 register STR **st = stack->ary_array;
1223 register int sp = arglast[1];
1224 register STIO *stio;
1230 stio = stab_io(stab);
1231 if (!stio || !stio->ifp)
1234 addr = str_get(st[++sp]);
1236 taintproper("Insecure dependency in bind");
1238 return bind(fileno(stio->ifp), addr, st[sp]->str_cur) >= 0;
1242 warn("bind() on closed fd");
1248 do_connect(stab, arglast)
1252 register STR **st = stack->ary_array;
1253 register int sp = arglast[1];
1254 register STIO *stio;
1260 stio = stab_io(stab);
1261 if (!stio || !stio->ifp)
1264 addr = str_get(st[++sp]);
1266 taintproper("Insecure dependency in connect");
1268 return connect(fileno(stio->ifp), addr, st[sp]->str_cur) >= 0;
1272 warn("connect() on closed fd");
1278 do_listen(stab, arglast)
1282 register STR **st = stack->ary_array;
1283 register int sp = arglast[1];
1284 register STIO *stio;
1290 stio = stab_io(stab);
1291 if (!stio || !stio->ifp)
1294 backlog = (int)str_gnum(st[++sp]);
1295 return listen(fileno(stio->ifp), backlog) >= 0;
1299 warn("listen() on closed fd");
1304 do_accept(str, nstab, gstab)
1309 register STIO *nstio;
1310 register STIO *gstio;
1311 int len = sizeof buf;
1319 gstio = stab_io(gstab);
1320 nstio = stab_io(nstab);
1322 if (!gstio || !gstio->ifp)
1325 nstio = stab_io(nstab) = stio_new();
1326 else if (nstio->ifp)
1327 do_close(nstab,FALSE);
1329 fd = accept(fileno(gstio->ifp),buf,&len);
1332 nstio->ifp = fdopen(fd, "r");
1333 nstio->ofp = fdopen(fd, "w");
1336 str_nset(str, buf, len);
1341 warn("accept() on closed fd");
1343 str_sset(str,&str_undef);
1348 do_shutdown(stab, arglast)
1352 register STR **st = stack->ary_array;
1353 register int sp = arglast[1];
1354 register STIO *stio;
1360 stio = stab_io(stab);
1361 if (!stio || !stio->ifp)
1364 how = (int)str_gnum(st[++sp]);
1365 return shutdown(fileno(stio->ifp), how) >= 0;
1369 warn("shutdown() on closed fd");
1375 do_sopt(optype, stab, arglast)
1380 register STR **st = stack->ary_array;
1381 register int sp = arglast[1];
1382 register STIO *stio;
1390 stio = stab_io(stab);
1391 if (!stio || !stio->ifp)
1394 fd = fileno(stio->ifp);
1395 lvl = (int)str_gnum(st[sp+1]);
1396 optname = (int)str_gnum(st[sp+2]);
1399 st[sp] = str_2static(str_new(257));
1400 st[sp]->str_cur = 256;
1401 st[sp]->str_pok = 1;
1402 if (getsockopt(fd, lvl, optname, st[sp]->str_ptr, &st[sp]->str_cur) < 0)
1407 if (setsockopt(fd, lvl, optname, st[sp]->str_ptr, st[sp]->str_cur) < 0)
1417 warn("[gs]etsockopt() on closed fd");
1418 st[sp] = &str_undef;
1424 do_getsockname(optype, stab, arglast)
1429 register STR **st = stack->ary_array;
1430 register int sp = arglast[1];
1431 register STIO *stio;
1437 stio = stab_io(stab);
1438 if (!stio || !stio->ifp)
1441 st[sp] = str_2static(str_new(257));
1442 st[sp]->str_cur = 256;
1443 st[sp]->str_pok = 1;
1444 fd = fileno(stio->ifp);
1447 if (getsockname(fd, st[sp]->str_ptr, &st[sp]->str_cur) < 0)
1451 if (getpeername(fd, st[sp]->str_ptr, &st[sp]->str_cur) < 0)
1460 warn("get{sock,peer}name() on closed fd");
1462 st[sp] = &str_undef;
1468 do_ghent(which,gimme,arglast)
1473 register ARRAY *ary = stack;
1474 register int sp = arglast[0];
1475 register char **elem;
1477 struct hostent *gethostbyname();
1478 struct hostent *gethostbyaddr();
1480 struct hostent *gethostent();
1482 struct hostent *hent;
1485 if (gimme != G_ARRAY) {
1486 astore(ary, ++sp, str_static(&str_undef));
1490 if (which == O_GHBYNAME) {
1491 char *name = str_get(ary->ary_array[sp+1]);
1493 hent = gethostbyname(name);
1495 else if (which == O_GHBYADDR) {
1496 STR *addrstr = ary->ary_array[sp+1];
1497 int addrtype = (int)str_gnum(ary->ary_array[sp+2]);
1498 char *addr = str_get(addrstr);
1500 hent = gethostbyaddr(addr,addrstr->str_cur,addrtype);
1504 hent = gethostent();
1506 fatal("gethostent not implemented");
1510 (void)astore(ary, ++sp, str = str_static(&str_no));
1511 str_set(str, hent->h_name);
1512 (void)astore(ary, ++sp, str = str_static(&str_no));
1513 for (elem = hent->h_aliases; *elem; elem++) {
1514 str_cat(str, *elem);
1516 str_ncat(str," ",1);
1518 (void)astore(ary, ++sp, str = str_static(&str_no));
1519 str_numset(str, (double)hent->h_addrtype);
1520 (void)astore(ary, ++sp, str = str_static(&str_no));
1521 len = hent->h_length;
1522 str_numset(str, (double)len);
1524 for (elem = hent->h_addr_list; *elem; elem++) {
1525 (void)astore(ary, ++sp, str = str_static(&str_no));
1526 str_nset(str, *elem, len);
1529 (void)astore(ary, ++sp, str = str_static(&str_no));
1530 str_nset(str, hent->h_addr, len);
1535 (void)astore(ary, ++sp, str_static(&str_no));
1543 do_gnent(which,gimme,arglast)
1548 register ARRAY *ary = stack;
1549 register int sp = arglast[0];
1550 register char **elem;
1552 struct netent *getnetbyname();
1553 struct netent *getnetbyaddr();
1554 struct netent *getnetent();
1555 struct netent *nent;
1557 if (gimme != G_ARRAY) {
1558 astore(ary, ++sp, str_static(&str_undef));
1562 if (which == O_GNBYNAME) {
1563 char *name = str_get(ary->ary_array[sp+1]);
1565 nent = getnetbyname(name);
1567 else if (which == O_GNBYADDR) {
1568 STR *addrstr = ary->ary_array[sp+1];
1569 int addrtype = (int)str_gnum(ary->ary_array[sp+2]);
1570 char *addr = str_get(addrstr);
1572 nent = getnetbyaddr(addr,addrtype);
1579 (void)astore(ary, ++sp, str = str_static(&str_no));
1580 str_set(str, nent->n_name);
1581 (void)astore(ary, ++sp, str = str_static(&str_no));
1582 for (elem = nent->n_aliases; *elem; elem++) {
1583 str_cat(str, *elem);
1585 str_ncat(str," ",1);
1587 (void)astore(ary, ++sp, str = str_static(&str_no));
1588 str_numset(str, (double)nent->n_addrtype);
1589 (void)astore(ary, ++sp, str = str_static(&str_no));
1590 str_numset(str, (double)nent->n_net);
1594 (void)astore(ary, ++sp, str_static(&str_no));
1602 do_gpent(which,gimme,arglast)
1607 register ARRAY *ary = stack;
1608 register int sp = arglast[0];
1609 register char **elem;
1611 struct protoent *getprotobyname();
1612 struct protoent *getprotobynumber();
1613 struct protoent *getprotoent();
1614 struct protoent *pent;
1616 if (gimme != G_ARRAY) {
1617 astore(ary, ++sp, str_static(&str_undef));
1621 if (which == O_GPBYNAME) {
1622 char *name = str_get(ary->ary_array[sp+1]);
1624 pent = getprotobyname(name);
1626 else if (which == O_GPBYNUMBER) {
1627 int proto = (int)str_gnum(ary->ary_array[sp+1]);
1629 pent = getprotobynumber(proto);
1632 pent = getprotoent();
1636 (void)astore(ary, ++sp, str = str_static(&str_no));
1637 str_set(str, pent->p_name);
1638 (void)astore(ary, ++sp, str = str_static(&str_no));
1639 for (elem = pent->p_aliases; *elem; elem++) {
1640 str_cat(str, *elem);
1642 str_ncat(str," ",1);
1644 (void)astore(ary, ++sp, str = str_static(&str_no));
1645 str_numset(str, (double)pent->p_proto);
1649 (void)astore(ary, ++sp, str_static(&str_no));
1657 do_gsent(which,gimme,arglast)
1662 register ARRAY *ary = stack;
1663 register int sp = arglast[0];
1664 register char **elem;
1666 struct servent *getservbyname();
1667 struct servent *getservbynumber();
1668 struct servent *getservent();
1669 struct servent *sent;
1671 if (gimme != G_ARRAY) {
1672 astore(ary, ++sp, str_static(&str_undef));
1676 if (which == O_GSBYNAME) {
1677 char *name = str_get(ary->ary_array[sp+1]);
1678 char *proto = str_get(ary->ary_array[sp+2]);
1680 if (proto && !*proto)
1683 sent = getservbyname(name,proto);
1685 else if (which == O_GSBYPORT) {
1686 int port = (int)str_gnum(ary->ary_array[sp+1]);
1687 char *proto = str_get(ary->ary_array[sp+2]);
1689 sent = getservbyport(port,proto);
1692 sent = getservent();
1695 (void)astore(ary, ++sp, str = str_static(&str_no));
1696 str_set(str, sent->s_name);
1697 (void)astore(ary, ++sp, str = str_static(&str_no));
1698 for (elem = sent->s_aliases; *elem; elem++) {
1699 str_cat(str, *elem);
1701 str_ncat(str," ",1);
1703 (void)astore(ary, ++sp, str = str_static(&str_no));
1705 str_numset(str, (double)ntohs(sent->s_port));
1707 str_numset(str, (double)(sent->s_port));
1709 (void)astore(ary, ++sp, str = str_static(&str_no));
1710 str_set(str, sent->s_proto);
1714 (void)astore(ary, ++sp, str_static(&str_no));
1725 do_select(gimme,arglast)
1729 register STR **st = stack->ary_array;
1730 register int sp = arglast[0];
1738 struct timeval timebuf;
1739 struct timeval *tbuf = &timebuf;
1741 #if BYTEORDER != 0x1234 && BYTEORDER != 0x12345678
1747 #if BYTEORDER & 0xf0000
1748 #define ORDERBYTE (0x88888888 - BYTEORDER)
1750 #define ORDERBYTE (0x4444 - BYTEORDER)
1755 for (i = 1; i <= 3; i++) {
1756 j = st[sp+i]->str_cur;
1761 #if BYTEORDER == 0x1234 || BYTEORDER == 0x12345678
1762 growsize = maxlen; /* little endians can use vecs directly */
1770 masksize = NFDBITS / NBBY;
1772 masksize = sizeof(long); /* documented int, everyone seems to use long */
1774 growsize = maxlen + (masksize - (maxlen % masksize));
1775 Zero(&fd_sets[0], 4, char*);
1778 for (i = 1; i <= 3; i++) {
1783 Str_Grow(str,growsize);
1784 s = str_get(str) + j;
1785 while (++j <= growsize) {
1789 else if (str->str_ptr) {
1790 Safefree(str->str_ptr);
1791 str->str_ptr = Nullch;
1794 #if BYTEORDER != 0x1234 && BYTEORDER != 0x12345678
1797 New(403, fd_sets[i], growsize, char);
1798 for (offset = 0; offset < growsize; offset += masksize) {
1799 for (j = 0, k=ORDERBYTE; j < masksize; j++, (k >>= 4))
1800 fd_sets[i][j+offset] = s[(k % masksize) + offset];
1806 if (str->str_nok || str->str_pok) {
1807 value = str_gnum(str);
1810 timebuf.tv_sec = (long)value;
1811 value -= (double)timebuf.tv_sec;
1812 timebuf.tv_usec = (long)(value * 1000000.0);
1815 tbuf = Null(struct timeval*);
1817 #if BYTEORDER == 0x1234 || BYTEORDER == 0x12345678
1831 for (i = 1; i <= 3; i++) {
1835 for (offset = 0; offset < growsize; offset += masksize) {
1836 for (j = 0, k=ORDERBYTE; j < masksize; j++, (k >>= 4))
1837 s[(k % masksize) + offset] = fd_sets[i][j+offset];
1843 st[++sp] = str_static(&str_no);
1844 str_numset(st[sp], (double)nfound);
1845 if (gimme == G_ARRAY && tbuf) {
1846 value = (double)(timebuf.tv_sec) +
1847 (double)(timebuf.tv_usec) / 1000000.0;
1848 st[++sp] = str_static(&str_no);
1849 str_numset(st[sp], value);
1857 do_spair(stab1, stab2, arglast)
1862 register STR **st = stack->ary_array;
1863 register int sp = arglast[2];
1864 register STIO *stio1;
1865 register STIO *stio2;
1866 int domain, type, protocol, fd[2];
1868 if (!stab1 || !stab2)
1871 stio1 = stab_io(stab1);
1872 stio2 = stab_io(stab2);
1874 stio1 = stab_io(stab1) = stio_new();
1875 else if (stio1->ifp)
1876 do_close(stab1,FALSE);
1878 stio2 = stab_io(stab2) = stio_new();
1879 else if (stio2->ifp)
1880 do_close(stab2,FALSE);
1882 domain = (int)str_gnum(st[++sp]);
1883 type = (int)str_gnum(st[++sp]);
1884 protocol = (int)str_gnum(st[++sp]);
1886 taintproper("Insecure dependency in socketpair");
1889 if (socketpair(domain,type,protocol,fd) < 0)
1892 fatal("Socketpair unimplemented");
1894 stio1->ifp = fdopen(fd[0], "r");
1895 stio1->ofp = fdopen(fd[0], "w");
1897 stio2->ifp = fdopen(fd[1], "r");
1898 stio2->ofp = fdopen(fd[1], "w");
1907 do_gpwent(which,gimme,arglast)
1913 register ARRAY *ary = stack;
1914 register int sp = arglast[0];
1916 struct passwd *getpwnam();
1917 struct passwd *getpwuid();
1918 struct passwd *getpwent();
1919 struct passwd *pwent;
1921 if (gimme != G_ARRAY) {
1922 astore(ary, ++sp, str_static(&str_undef));
1926 if (which == O_GPWNAM) {
1927 char *name = str_get(ary->ary_array[sp+1]);
1929 pwent = getpwnam(name);
1931 else if (which == O_GPWUID) {
1932 int uid = (int)str_gnum(ary->ary_array[sp+1]);
1934 pwent = getpwuid(uid);
1940 (void)astore(ary, ++sp, str = str_static(&str_no));
1941 str_set(str, pwent->pw_name);
1942 (void)astore(ary, ++sp, str = str_static(&str_no));
1943 str_set(str, pwent->pw_passwd);
1944 (void)astore(ary, ++sp, str = str_static(&str_no));
1945 str_numset(str, (double)pwent->pw_uid);
1946 (void)astore(ary, ++sp, str = str_static(&str_no));
1947 str_numset(str, (double)pwent->pw_gid);
1948 (void)astore(ary, ++sp, str = str_static(&str_no));
1950 str_numset(str, (double)pwent->pw_change);
1953 str_numset(str, (double)pwent->pw_quota);
1956 str_set(str, pwent->pw_age);
1960 (void)astore(ary, ++sp, str = str_static(&str_no));
1962 str_set(str,pwent->pw_class);
1965 str_set(str, pwent->pw_comment);
1968 (void)astore(ary, ++sp, str = str_static(&str_no));
1969 str_set(str, pwent->pw_gecos);
1970 (void)astore(ary, ++sp, str = str_static(&str_no));
1971 str_set(str, pwent->pw_dir);
1972 (void)astore(ary, ++sp, str = str_static(&str_no));
1973 str_set(str, pwent->pw_shell);
1975 (void)astore(ary, ++sp, str = str_static(&str_no));
1976 str_numset(str, (double)pwent->pw_expire);
1982 fatal("password routines not implemented");
1987 do_ggrent(which,gimme,arglast)
1993 register ARRAY *ary = stack;
1994 register int sp = arglast[0];
1995 register char **elem;
1997 struct group *getgrnam();
1998 struct group *getgrgid();
1999 struct group *getgrent();
2000 struct group *grent;
2002 if (gimme != G_ARRAY) {
2003 astore(ary, ++sp, str_static(&str_undef));
2007 if (which == O_GGRNAM) {
2008 char *name = str_get(ary->ary_array[sp+1]);
2010 grent = getgrnam(name);
2012 else if (which == O_GGRGID) {
2013 int gid = (int)str_gnum(ary->ary_array[sp+1]);
2015 grent = getgrgid(gid);
2021 (void)astore(ary, ++sp, str = str_static(&str_no));
2022 str_set(str, grent->gr_name);
2023 (void)astore(ary, ++sp, str = str_static(&str_no));
2024 str_set(str, grent->gr_passwd);
2025 (void)astore(ary, ++sp, str = str_static(&str_no));
2026 str_numset(str, (double)grent->gr_gid);
2027 (void)astore(ary, ++sp, str = str_static(&str_no));
2028 for (elem = grent->gr_mem; *elem; elem++) {
2029 str_cat(str, *elem);
2031 str_ncat(str," ",1);
2037 fatal("group routines not implemented");
2042 do_dirop(optype,stab,gimme,arglast)
2048 #if defined(DIRENT) && defined(READDIR)
2049 register ARRAY *ary = stack;
2050 register STR **st = ary->ary_array;
2051 register int sp = arglast[1];
2052 register STIO *stio;
2057 struct DIRENT *readdir();
2058 register struct DIRENT *dp;
2062 if (!(stio = stab_io(stab)))
2063 stio = stab_io(stab) = stio_new();
2064 if (!stio->dirp && optype != O_OPENDIR)
2070 closedir(stio->dirp);
2071 if (!(stio->dirp = opendir(str_get(st[sp+1]))))
2075 if (gimme == G_ARRAY) {
2077 while (dp = readdir(stio->dirp)) {
2079 (void)astore(ary,++sp,
2080 str_2static(str_make(dp->d_name,dp->d_namlen)));
2082 (void)astore(ary,++sp,
2083 str_2static(str_make(dp->d_name,0)));
2088 if (!(dp = readdir(stio->dirp)))
2090 st[sp] = str_static(&str_undef);
2092 str_nset(st[sp], dp->d_name, dp->d_namlen);
2094 str_set(st[sp], dp->d_name);
2104 st[sp] = str_static(&str_undef);
2105 str_numset(st[sp], (double)telldir(stio->dirp));
2108 st[sp] = str_static(&str_undef);
2109 along = (long)str_gnum(st[sp+1]);
2110 (void)seekdir(stio->dirp,along);
2114 st[sp] = str_static(&str_undef);
2115 (void)rewinddir(stio->dirp);
2118 st[sp] = str_static(&str_undef);
2119 (void)closedir(stio->dirp);
2126 st[sp] = &str_undef;
2130 fatal("Unimplemented directory operation");
2138 register STR **st = stack->ary_array;
2139 register int sp = arglast[1];
2140 register int items = arglast[2] - sp;
2143 register int tot = 0;
2147 for (st += ++sp; items--; st++)
2148 tainted |= (*st)->str_tainted;
2149 st = stack->ary_array;
2151 items = arglast[2] - sp;
2156 taintproper("Insecure dependency in chmod");
2160 val = (int)str_gnum(st[++sp]);
2162 if (chmod(str_get(st[++sp]),val))
2170 taintproper("Insecure dependency in chown");
2175 val = (int)str_gnum(st[++sp]);
2176 val2 = (int)str_gnum(st[++sp]);
2178 if (chown(str_get(st[++sp]),val,val2))
2187 taintproper("Insecure dependency in kill");
2191 s = str_get(st[++sp]);
2193 if (*s == 'S' && s[1] == 'I' && s[2] == 'G')
2195 if (!(val = whichsig(s)))
2196 fatal("Unrecognized signal name \"%s\"",s);
2199 val = (int)str_gnum(st[sp]);
2203 int proc = (int)str_gnum(st[++sp]);
2205 if (killpg(proc,val)) /* BSD */
2207 if (kill(-proc,val)) /* SYSV */
2214 if (kill((int)(str_gnum(st[++sp])),val))
2223 taintproper("Insecure dependency in unlink");
2227 s = str_get(st[++sp]);
2228 if (euid || unsafe) {
2232 else { /* don't let root wipe out directories without -U */
2234 if (lstat(s,&statbuf) < 0 ||
2236 if (stat(s,&statbuf) < 0 ||
2238 (statbuf.st_mode & S_IFMT) == S_IFDIR )
2249 taintproper("Insecure dependency in utime");
2253 struct utimbuf utbuf;
2261 Zero(&utbuf, sizeof utbuf, char);
2262 utbuf.actime = (long)str_gnum(st[++sp]); /* time accessed */
2263 utbuf.modtime = (long)str_gnum(st[++sp]); /* time modified */
2268 if (utime(str_get(st[++sp]),&utbuf))
2280 /* Do the permissions allow some operation? Assumes statcache already set. */
2283 cando(bit, effective, statbufp)
2286 register struct stat *statbufp;
2288 if ((effective ? euid : uid) == 0) { /* root is special */
2289 if (bit == S_IEXEC) {
2290 if (statbufp->st_mode & 0111 ||
2291 (statbufp->st_mode & S_IFMT) == S_IFDIR )
2295 return TRUE; /* root reads and writes anything */
2298 if (statbufp->st_uid == (effective ? euid : uid) ) {
2299 if (statbufp->st_mode & bit)
2300 return TRUE; /* ok as "user" */
2302 else if (ingroup((int)statbufp->st_gid,effective)) {
2303 if (statbufp->st_mode & bit >> 3)
2304 return TRUE; /* ok as "group" */
2306 else if (statbufp->st_mode & bit >> 6)
2307 return TRUE; /* ok as "other" */
2312 ingroup(testgid,effective)
2316 if (testgid == (effective ? egid : gid))
2323 GIDTYPE gary[NGROUPS];
2326 anum = getgroups(NGROUPS,gary);
2328 if (gary[anum] == testgid)
2338 do_ipcget(optype, arglast)
2342 register STR **st = stack->ary_array;
2343 register int sp = arglast[0];
2347 key = (key_t)str_gnum(st[++sp]);
2348 n = (optype == O_MSGGET) ? 0 : (int)str_gnum(st[++sp]);
2349 flags = (int)str_gnum(st[++sp]);
2355 return msgget(key, flags);
2359 return semget(key, n, flags);
2363 return shmget(key, n, flags);
2365 #if !defined(IPCMSG) || !defined(IPCSEM) || !defined(IPCSHM)
2367 fatal("%s not implemented", opname[optype]);
2370 return -1; /* should never happen */
2374 do_ipcctl(optype, arglast)
2378 register STR **st = stack->ary_array;
2379 register int sp = arglast[0];
2382 int id, n, cmd, infosize, getinfo, ret;
2384 id = (int)str_gnum(st[++sp]);
2385 n = (optype == O_SEMCTL) ? (int)str_gnum(st[++sp]) : 0;
2386 cmd = (int)str_gnum(st[++sp]);
2390 getinfo = (cmd == IPC_STAT);
2396 if (cmd == IPC_STAT || cmd == IPC_SET)
2397 infosize = sizeof(struct msqid_ds);
2402 if (cmd == IPC_STAT || cmd == IPC_SET)
2403 infosize = sizeof(struct shmid_ds);
2408 if (cmd == IPC_STAT || cmd == IPC_SET)
2409 infosize = sizeof(struct semid_ds);
2410 else if (cmd == GETALL || cmd == SETALL)
2412 struct semid_ds semds;
2413 if (semctl(id, 0, IPC_STAT, &semds) == -1)
2415 getinfo = (cmd == GETALL);
2416 infosize = semds.sem_nsems * sizeof(ushort);
2420 #if !defined(IPCMSG) || !defined(IPCSEM) || !defined(IPCSHM)
2422 fatal("%s not implemented", opname[optype]);
2430 STR_GROW(astr, infosize+1);
2436 if (astr->str_cur != infosize)
2445 int i = (int)str_gnum(astr);
2446 a = (char *)i; /* ouch */
2453 ret = msgctl(id, cmd, a);
2458 ret = semctl(id, n, cmd, a);
2463 ret = shmctl(id, cmd, a);
2467 if (getinfo && ret >= 0) {
2468 astr->str_cur = infosize;
2469 astr->str_ptr[infosize] = '\0';
2479 register STR **st = stack->ary_array;
2480 register int sp = arglast[0];
2483 int id, msize, flags;
2485 id = (int)str_gnum(st[++sp]);
2487 flags = (int)str_gnum(st[++sp]);
2488 mbuf = str_get(mstr);
2489 if ((msize = mstr->str_cur - sizeof(long)) < 0) {
2494 return msgsnd(id, mbuf, msize, flags);
2496 fatal("msgsnd not implemented");
2505 register STR **st = stack->ary_array;
2506 register int sp = arglast[0];
2510 int id, msize, flags, ret;
2512 id = (int)str_gnum(st[++sp]);
2514 msize = (int)str_gnum(st[++sp]);
2515 mtype = (long)str_gnum(st[++sp]);
2516 flags = (int)str_gnum(st[++sp]);
2517 mbuf = str_get(mstr);
2518 if (mstr->str_cur < sizeof(long)+msize+1) {
2519 STR_GROW(mstr, sizeof(long)+msize+1);
2520 mbuf = str_get(mstr);
2523 ret = msgrcv(id, mbuf, msize, mtype, flags);
2525 mstr->str_cur = sizeof(long)+ret;
2526 mstr->str_ptr[sizeof(long)+ret] = '\0';
2530 fatal("msgrcv not implemented");
2539 register STR **st = stack->ary_array;
2540 register int sp = arglast[0];
2545 id = (int)str_gnum(st[++sp]);
2547 opbuf = str_get(opstr);
2548 opsize = opstr->str_cur;
2549 if (opsize < sizeof(struct sembuf)
2550 || (opsize % sizeof(struct sembuf)) != 0) {
2555 return semop(id, opbuf, opsize/sizeof(struct sembuf));
2557 fatal("semop not implemented");
2562 do_shmio(optype, arglast)
2567 register STR **st = stack->ary_array;
2568 register int sp = arglast[0];
2571 int id, mpos, msize;
2572 struct shmid_ds shmds;
2573 extern char *shmat();
2575 id = (int)str_gnum(st[++sp]);
2577 mpos = (int)str_gnum(st[++sp]);
2578 msize = (int)str_gnum(st[++sp]);
2580 if (shmctl(id, IPC_STAT, &shmds) == -1)
2582 if (mpos < 0 || msize < 0 || mpos + msize > shmds.shm_segsz) {
2583 errno = EFAULT; /* can't do as caller requested */
2586 shm = shmat(id, (char *)NULL, (optype == O_SHMREAD) ? SHM_RDONLY : 0);
2587 if (shm == (char *)-1) /* I hate System V IPC, I really do */
2589 mbuf = str_get(mstr);
2590 if (optype == O_SHMREAD) {
2591 if (mstr->str_cur < msize) {
2592 STR_GROW(mstr, msize+1);
2593 mbuf = str_get(mstr);
2595 bcopy(shm + mpos, mbuf, msize);
2596 mstr->str_cur = msize;
2597 mstr->str_ptr[msize] = '\0';
2602 if ((n = mstr->str_cur) > msize)
2604 bcopy(mbuf, shm + mpos, n);
2606 bzero(shm + mpos + n, msize - n);
2610 fatal("shm I/O not implemented");
2614 #endif /* SYSVIPC */