1 /* $RCSfile: doio.c,v $$Revision: 4.0.1.1 $$Date: 91/04/11 17:41:06 $
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 4.0.1.1 91/04/11 17:41:06 lwall
10 * patch1: hopefully straightened out some of the Xenix mess
12 * Revision 4.0 91/03/20 01:07:06 lwall
21 #include <sys/socket.h>
28 #include <sys/select.h>
33 #if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)
63 int laststype = O_STAT;
66 do_open(stab,name,len)
72 register STIO *stio = stab_io(stab);
73 char *myname = savestr(name);
77 char mode[3]; /* stdio file mode ("r\0" or "r+\0") */
80 forkprocess = 1; /* assume true if no fork */
81 while (len && isspace(name[len-1]))
84 stio = stab_io(stab) = stio_new();
86 fd = fileno(stio->ifp);
87 if (stio->type == '|')
88 result = mypclose(stio->ifp);
89 else if (stio->type == '-')
91 else if (stio->ifp != stio->ofp) {
93 result = fclose(stio->ofp);
94 fclose(stio->ifp); /* clear stdio, fd already closed */
97 result = fclose(stio->ifp);
100 result = fclose(stio->ifp);
101 if (result == EOF && fd > 2)
102 fprintf(stderr,"Warning: unable to close filehandle %s properly.\n",
104 stio->ofp = stio->ifp = Nullfp;
106 if (*name == '+' && len > 1 && name[len-1] != '|') { /* scary */
117 for (name++; isspace(*name); name++) ;
120 taintproper("Insecure dependency in piped open");
122 fp = mypopen(name,"w");
125 else if (*name == '>') {
127 taintproper("Insecure dependency in open");
131 mode[0] = stio->type = 'a';
140 while (isspace(*name))
145 stab = stabent(name,FALSE);
146 if (!stab || !stab_io(stab))
148 if (stab_io(stab) && stab_io(stab)->ifp) {
149 fd = fileno(stab_io(stab)->ifp);
150 if (stab_io(stab)->type == 's')
156 if (!(fp = fdopen(fd = dup(fd),mode))) {
161 while (isspace(*name))
163 if (strEQ(name,"-")) {
168 fp = fopen(name,mode);
176 while (isspace(*name))
180 if (strEQ(name,"-")) {
185 fp = fopen(name,mode);
187 else if (name[len-1] == '|') {
190 taintproper("Insecure dependency in piped open");
193 while (len && isspace(name[len-1]))
195 for (; isspace(*name); name++) ;
196 fp = mypopen(name,"r");
201 for (; isspace(*name); name++) ;
202 if (strEQ(name,"-")) {
207 fp = fopen(name,"r");
214 stio->type != '|' && stio->type != '-') {
215 if (fstat(fileno(fp),&statbuf) < 0) {
219 if (S_ISSOCK(statbuf.st_mode))
220 stio->type = 's'; /* in case a socket was passed in to us */
222 else if (!(statbuf.st_mode & S_IFMT))
223 stio->type = 's'; /* some OS's return 0 on fstat()ed socket */
226 #if defined(HAS_FCNTL) && defined(F_SETFD)
228 fcntl(fd,F_SETFD,fd >= 3);
232 if (stio->type != 's')
235 if (!(stio->ofp = fdopen(fileno(fp),"w"))) {
252 static int filemode = 0;
254 static char *oldname;
257 argvoutstab = stabent("ARGVOUT",TRUE);
258 if (filemode & (S_ISUID|S_ISGID)) {
259 fflush(stab_io(argvoutstab)->ifp); /* chmod must follow last write */
261 (void)fchmod(lastfd,filemode);
263 (void)chmod(oldname,filemode);
267 while (alen(stab_xarray(stab)) >= 0) {
268 str = ashift(stab_xarray(stab));
269 str_sset(stab_val(stab),str);
270 STABSET(stab_val(stab));
271 oldname = str_get(stab_val(stab));
272 if (do_open(stab,oldname,stab_val(stab)->str_cur)) {
275 taintproper("Insecure dependency in inplace open");
277 if (strEQ(oldname,"-")) {
279 defoutstab = stabent("STDOUT",TRUE);
280 return stab_io(stab)->ifp;
282 filedev = statbuf.st_dev;
283 fileino = statbuf.st_ino;
284 filemode = statbuf.st_mode;
285 fileuid = statbuf.st_uid;
286 filegid = statbuf.st_gid;
287 if (!S_ISREG(filemode)) {
288 warn("Can't do inplace edit: %s is not a regular file",
290 do_close(stab,FALSE);
296 add_suffix(str,inplace);
298 str_cat(str,inplace);
300 #ifndef FLEXFILENAMES
301 if (stat(str->str_ptr,&statbuf) >= 0
302 && statbuf.st_dev == filedev
303 && statbuf.st_ino == fileino ) {
304 warn("Can't do inplace edit: %s > 14 characters",
306 do_close(stab,FALSE);
313 if (rename(oldname,str->str_ptr) < 0) {
314 warn("Can't rename %s to %s: %s, skipping file",
315 oldname, str->str_ptr, strerror(errno) );
316 do_close(stab,FALSE);
321 do_close(stab,FALSE);
322 (void)unlink(str->str_ptr);
323 (void)rename(oldname,str->str_ptr);
324 do_open(stab,str->str_ptr,stab_val(stab)->str_cur);
327 (void)UNLINK(str->str_ptr);
328 if (link(oldname,str->str_ptr) < 0) {
329 warn("Can't rename %s to %s: %s, skipping file",
330 oldname, str->str_ptr, strerror(errno) );
331 do_close(stab,FALSE);
335 (void)UNLINK(oldname);
340 if (UNLINK(oldname) < 0) {
341 warn("Can't rename %s to %s: %s, skipping file",
342 oldname, str->str_ptr, strerror(errno) );
343 do_close(stab,FALSE);
348 fatal("Can't do inplace edit without backup");
353 str_cat(str,oldname);
354 errno = 0; /* in case sprintf set errno */
355 if (!do_open(argvoutstab,str->str_ptr,str->str_cur)) {
356 warn("Can't do inplace edit on %s: %s",
357 oldname, strerror(errno) );
358 do_close(stab,FALSE);
362 defoutstab = argvoutstab;
363 lastfd = fileno(stab_io(argvoutstab)->ifp);
364 (void)fstat(lastfd,&statbuf);
366 (void)fchmod(lastfd,filemode);
368 (void)chmod(oldname,filemode);
370 if (fileuid != statbuf.st_uid || filegid != statbuf.st_gid) {
372 (void)fchown(lastfd,fileuid,filegid);
375 (void)chown(oldname,fileuid,filegid);
381 return stab_io(stab)->ifp;
384 fprintf(stderr,"Can't open %s: %s\n",str_get(str), strerror(errno));
388 (void)do_close(argvoutstab,FALSE);
389 defoutstab = stabent("STDOUT",TRUE);
396 do_pipe(str, rstab, wstab)
401 register STIO *rstio;
402 register STIO *wstio;
410 rstio = stab_io(rstab);
411 wstio = stab_io(wstab);
414 rstio = stab_io(rstab) = stio_new();
416 do_close(rstab,FALSE);
418 wstio = stab_io(wstab) = stio_new();
420 do_close(wstab,FALSE);
424 rstio->ifp = fdopen(fd[0], "r");
425 wstio->ofp = fdopen(fd[1], "w");
426 wstio->ifp = wstio->ofp;
429 if (!rstio->ifp || !wstio->ofp) {
430 if (rstio->ifp) fclose(rstio->ifp);
432 if (wstio->ofp) fclose(wstio->ofp);
437 str_sset(str,&str_yes);
441 str_sset(str,&str_undef);
447 do_close(stab,explicit)
459 stio = stab_io(stab);
460 if (!stio) { /* never opened */
461 if (dowarn && explicit)
462 warn("Close on unopened file <%s>",stab_name(stab));
466 if (stio->type == '|') {
467 status = mypclose(stio->ifp);
468 retval = (status == 0);
469 statusvalue = (unsigned short)status & 0xffff;
471 else if (stio->type == '-')
474 if (stio->ofp && stio->ofp != stio->ifp) { /* a socket */
475 retval = (fclose(stio->ofp) != EOF);
476 fclose(stio->ifp); /* clear stdio, fd already closed */
479 retval = (fclose(stio->ifp) != EOF);
481 stio->ofp = stio->ifp = Nullfp;
496 if (!stab) { /* eof() */
498 stio = stab_io(argvstab);
503 stio = stab_io(stab);
510 #ifdef STDSTDIO /* (the code works without this) */
511 if (stio->ifp->_cnt > 0) /* cheat a little, since */
512 return FALSE; /* this is the most usual case */
515 ch = getc(stio->ifp);
517 (void)ungetc(ch, stio->ifp);
521 if (stio->ifp->_cnt < -1)
522 stio->ifp->_cnt = -1;
524 if (!stab) { /* not necessarily a real EOF yet? */
525 if (!nextargv(argvstab)) /* get another fp handy */
529 return TRUE; /* normal fp, definitely end of file */
543 stio = stab_io(stab);
544 if (!stio || !stio->ifp)
548 (void)fseek (stio->ifp, 0L, 2); /* ultrix 1.2 workaround */
550 return ftell(stio->ifp);
554 warn("tell() on unopened file");
559 do_seek(stab, pos, whence)
569 stio = stab_io(stab);
570 if (!stio || !stio->ifp)
574 (void)fseek (stio->ifp, 0L, 2); /* ultrix 1.2 workaround */
576 return fseek(stio->ifp, pos, whence) >= 0;
580 warn("seek() on unopened file");
585 do_ctl(optype,stab,func,argstr)
595 if (!stab || !argstr)
597 stio = stab_io(stab);
601 if (argstr->str_pok || !argstr->str_nok) {
602 if (!argstr->str_pok)
607 #define IOCPARM_LEN(x) (((x) >> 16) & IOCPARM_MASK)
611 retval = IOCPARM_LEN(func); /* on BSDish systes we're safe */
613 retval = 256; /* otherwise guess at what's safe */
615 if (argstr->str_cur < retval) {
616 Str_Grow(argstr,retval+1);
617 argstr->str_cur = retval;
621 s[argstr->str_cur] = 17; /* a little sanity check here */
624 retval = (int)str_gnum(argstr);
626 s = (char*)(long)retval; /* ouch */
628 s = (char*)retval; /* ouch */
633 if (optype == O_IOCTL)
634 retval = ioctl(fileno(stio->ifp), func, s);
637 fatal("fcntl is not implemented");
640 retval = fcntl(fileno(stio->ifp), func, s);
642 fatal("fcntl is not implemented");
649 if (argstr->str_pok) {
650 if (s[argstr->str_cur] != 17)
651 fatal("Return value overflowed string");
652 s[argstr->str_cur] = 0; /* put our null back */
658 do_stat(str,arg,gimme,arglast)
664 register ARRAY *ary = stack;
665 register int sp = arglast[0] + 1;
668 if ((arg[1].arg_type & A_MASK) == A_WORD) {
669 tmpstab = arg[1].arg_ptr.arg_stab;
670 if (tmpstab != defstab) {
673 str_set(statname,"");
674 if (!stab_io(tmpstab) || !stab_io(tmpstab)->ifp ||
675 fstat(fileno(stab_io(tmpstab)->ifp),&statcache) < 0) {
680 else if (laststatval < 0)
684 str_set(statname,str_get(ary->ary_array[sp]));
687 laststype = arg->arg_type;
688 if (arg->arg_type == O_LSTAT)
689 laststatval = lstat(str_get(statname),&statcache);
692 laststatval = stat(str_get(statname),&statcache);
697 if (gimme != G_ARRAY) {
699 str_sset(str,&str_yes);
701 str_sset(str,&str_undef);
703 ary->ary_array[sp] = str;
709 (void)astore(ary,++sp,
710 str_2mortal(str_nmake((double)statcache.st_dev)));
711 (void)astore(ary,++sp,
712 str_2mortal(str_nmake((double)statcache.st_ino)));
713 (void)astore(ary,++sp,
714 str_2mortal(str_nmake((double)statcache.st_mode)));
715 (void)astore(ary,++sp,
716 str_2mortal(str_nmake((double)statcache.st_nlink)));
717 (void)astore(ary,++sp,
718 str_2mortal(str_nmake((double)statcache.st_uid)));
719 (void)astore(ary,++sp,
720 str_2mortal(str_nmake((double)statcache.st_gid)));
721 (void)astore(ary,++sp,
722 str_2mortal(str_nmake((double)statcache.st_rdev)));
723 (void)astore(ary,++sp,
724 str_2mortal(str_nmake((double)statcache.st_size)));
725 (void)astore(ary,++sp,
726 str_2mortal(str_nmake((double)statcache.st_atime)));
727 (void)astore(ary,++sp,
728 str_2mortal(str_nmake((double)statcache.st_mtime)));
729 (void)astore(ary,++sp,
730 str_2mortal(str_nmake((double)statcache.st_ctime)));
732 (void)astore(ary,++sp,
733 str_2mortal(str_nmake((double)statcache.st_blksize)));
734 (void)astore(ary,++sp,
735 str_2mortal(str_nmake((double)statcache.st_blocks)));
737 (void)astore(ary,++sp,
738 str_2mortal(str_make("",0)));
739 (void)astore(ary,++sp,
740 str_2mortal(str_make("",0)));
743 (void)astore(ary,++sp,str_nmake(0.0));
749 #if !defined(HAS_TRUNCATE) && !defined(HAS_CHSIZE) && defined(F_FREESP)
750 /* code courtesy of William Kucharski */
753 int chsize(fd, length)
754 int fd; /* file descriptor */
755 off_t length; /* length to set file to */
761 if (fstat(fd, &filebuf) < 0)
764 if (filebuf.st_size < length) {
766 /* extend file length */
768 if ((lseek(fd, (length - 1), 0)) < 0)
771 /* write a "0" byte */
773 if ((write(fd, "", 1)) != 1)
777 /* truncate length */
782 fl.l_type = F_WRLCK; /* write lock on file space */
785 * This relies on the UNDOCUMENTED F_FREESP argument to
786 * fcntl(2), which truncates the file so that it ends at the
787 * position indicated by fl.l_start.
789 * Will minor miracles never cease?
792 if (fcntl(fd, F_FREESP, &fl) < 0)
799 #endif /* F_FREESP */
802 do_truncate(str,arg,gimme,arglast)
808 register ARRAY *ary = stack;
809 register int sp = arglast[0] + 1;
810 off_t len = (off_t)str_gnum(ary->ary_array[sp+1]);
814 #if defined(HAS_TRUNCATE) || defined(HAS_CHSIZE)
816 if ((arg[1].arg_type & A_MASK) == A_WORD) {
817 tmpstab = arg[1].arg_ptr.arg_stab;
818 if (!stab_io(tmpstab) ||
819 ftruncate(fileno(stab_io(tmpstab)->ifp), len) < 0)
822 else if (truncate(str_get(ary->ary_array[sp]), len) < 0)
825 if ((arg[1].arg_type & A_MASK) == A_WORD) {
826 tmpstab = arg[1].arg_ptr.arg_stab;
827 if (!stab_io(tmpstab) ||
828 chsize(fileno(stab_io(tmpstab)->ifp), len) < 0)
834 if ((tmpfd = open(str_get(ary->ary_array[sp]), 0)) < 0)
837 if (chsize(tmpfd, len) < 0)
845 str_sset(str,&str_yes);
847 str_sset(str,&str_undef);
849 ary->ary_array[sp] = str;
852 fatal("truncate not implemented");
857 looks_like_number(str)
866 send = s + str->str_cur;
871 if (*s == '+' || *s == '-')
879 else if (s == str->str_ptr)
885 if (*s == 'e' || *s == 'E') {
887 if (*s == '+' || *s == '-')
908 warn("print to unopened file");
914 ((str->str_nok && str->str_u.str_nval != 0.0)
915 || (looks_like_number(str) && str_gnum(str) != 0.0) ) ) {
916 fprintf(fp, ofmt, str->str_u.str_nval);
921 if (*tmps == 'S' && tmps[1] == 't' && tmps[2] == 'B' && tmps[3] == '\0'
922 && str->str_cur == sizeof(STBP) && strlen(tmps) < str->str_cur) {
923 STR *tmpstr = str_mortal(&str_undef);
924 stab_fullname(tmpstr,((STAB*)str));/* a stab value, be nice */
929 if (str->str_cur && (fwrite(tmps,1,str->str_cur,fp) == 0 || ferror(fp)))
936 do_aprint(arg,fp,arglast)
941 register STR **st = stack->ary_array;
942 register int sp = arglast[1];
944 register int items = arglast[2] - sp;
948 warn("print to unopened file");
952 if (arg->arg_type == O_PRTF) {
953 do_sprintf(arg->arg_ptr.arg_str,items,st);
954 retval = do_print(arg->arg_ptr.arg_str,fp);
957 retval = (items <= 0);
958 for (; items > 0; items--,st++) {
959 if (retval && ofslen) {
960 if (fwrite(ofs, 1, ofslen, fp) == 0 || ferror(fp)) {
965 if (!(retval = do_print(*st, fp)))
968 if (retval && orslen)
969 if (fwrite(ors, 1, orslen, fp) == 0 || ferror(fp))
983 if (arg[1].arg_type & A_DONT) {
984 stio = stab_io(arg[1].arg_ptr.arg_stab);
985 if (stio && stio->ifp) {
986 statstab = arg[1].arg_ptr.arg_stab;
987 str_set(statname,"");
988 return (laststatval = fstat(fileno(stio->ifp), &statcache));
991 if (arg[1].arg_ptr.arg_stab == defstab)
994 warn("Stat on unopened file <%s>",
995 stab_name(arg[1].arg_ptr.arg_stab));
997 str_set(statname,"");
998 return (laststatval = -1);
1002 statstab = Nullstab;
1003 str_set(statname,str_get(str));
1004 return (laststatval = stat(str_get(str),&statcache));
1013 if (arg[1].arg_type & A_DONT) {
1014 if (arg[1].arg_ptr.arg_stab == defstab) {
1015 if (laststype != O_LSTAT)
1016 fatal("The stat preceding -l _ wasn't an lstat");
1019 fatal("You can't use -l on a filehandle");
1022 laststype = O_LSTAT;
1023 statstab = Nullstab;
1024 str_set(statname,str_get(str));
1026 return (laststatval = lstat(str_get(str),&statcache));
1028 return (laststatval = stat(str_get(str),&statcache));
1041 register STDCHAR *s;
1042 register STIO *stio;
1044 if (arg[1].arg_type & A_DONT) {
1045 if (arg[1].arg_ptr.arg_stab == defstab) {
1047 stio = stab_io(statstab);
1050 goto really_filename;
1054 statstab = arg[1].arg_ptr.arg_stab;
1055 str_set(statname,"");
1056 stio = stab_io(statstab);
1058 if (stio && stio->ifp) {
1060 fstat(fileno(stio->ifp),&statcache);
1061 if (stio->ifp->_cnt <= 0) {
1062 i = getc(stio->ifp);
1064 (void)ungetc(i,stio->ifp);
1066 if (stio->ifp->_cnt <= 0) /* null file is anything */
1068 len = stio->ifp->_cnt + (stio->ifp->_ptr - stio->ifp->_base);
1069 s = stio->ifp->_base;
1071 fatal("-T and -B not implemented on filehandles\n");
1076 warn("Test on unopened file <%s>",
1077 stab_name(arg[1].arg_ptr.arg_stab));
1082 statstab = Nullstab;
1083 str_set(statname,str_get(str));
1085 i = open(str_get(str),0);
1088 fstat(i,&statcache);
1089 len = read(i,tbuf,512);
1091 if (len <= 0) /* null file is anything */
1096 /* now scan s to look for textiness */
1098 for (i = 0; i < len; i++,s++) {
1099 if (!*s) { /* null never allowed in text */
1106 *s != '\n' && *s != '\r' && *s != '\b' &&
1107 *s != '\t' && *s != '\f' && *s != 27)
1111 if ((odd * 10 > len) == (arg->arg_type == O_FTTEXT)) /* allow 10% odd */
1118 do_aexec(really,arglast)
1122 register STR **st = stack->ary_array;
1123 register int sp = arglast[1];
1124 register int items = arglast[2] - sp;
1130 New(401,argv, items+1, char*);
1132 for (st += ++sp; items > 0; items--,st++) {
1134 *a++ = str_get(*st);
1140 if (*argv[0] != '/') /* will execvp use PATH? */
1141 taintenv(); /* testing IFS here is overkill, probably */
1143 if (really && *(tmps = str_get(really)))
1146 execvp(argv[0],argv);
1152 static char **Argv = Null(char **);
1153 static char *Cmd = Nullch;
1160 Argv = Null(char **);
1178 taintproper("Insecure dependency in exec");
1181 /* save an extra exec if possible */
1184 if (strnEQ(cmd,cshname,cshlen) && strnEQ(cmd+cshlen," -c",3)) {
1200 if (s[-1] == '\'') {
1202 execl(cshname,"csh", flags,ncmd,(char*)0);
1210 /* see if there are shell metacharacters in it */
1212 for (s = cmd; *s && isalpha(*s); s++) ; /* catch VAR=val gizmo */
1215 for (s = cmd; *s; s++) {
1216 if (*s != ' ' && !isalpha(*s) && index("$&*(){}[]'\";\\|?<>~`\n",*s)) {
1217 if (*s == '\n' && !s[1]) {
1222 execl("/bin/sh","sh","-c",cmd,(char*)0);
1226 New(402,Argv, (s - cmd) / 2 + 2, char*);
1227 Cmd = nsavestr(cmd, s-cmd);
1229 for (s = Cmd; *s;) {
1230 while (*s && isspace(*s)) s++;
1233 while (*s && !isspace(*s)) s++;
1239 execvp(Argv[0],Argv);
1240 if (errno == ENOEXEC) { /* for system V NIH syndrome */
1251 do_socket(stab, arglast)
1255 register STR **st = stack->ary_array;
1256 register int sp = arglast[1];
1257 register STIO *stio;
1258 int domain, type, protocol, fd;
1263 stio = stab_io(stab);
1265 stio = stab_io(stab) = stio_new();
1267 do_close(stab,FALSE);
1269 domain = (int)str_gnum(st[++sp]);
1270 type = (int)str_gnum(st[++sp]);
1271 protocol = (int)str_gnum(st[++sp]);
1273 taintproper("Insecure dependency in socket");
1275 fd = socket(domain,type,protocol);
1278 stio->ifp = fdopen(fd, "r"); /* stdio gets confused about sockets */
1279 stio->ofp = fdopen(fd, "w");
1281 if (!stio->ifp || !stio->ofp) {
1282 if (stio->ifp) fclose(stio->ifp);
1283 if (stio->ofp) fclose(stio->ofp);
1284 if (!stio->ifp && !stio->ofp) close(fd);
1292 do_bind(stab, arglast)
1296 register STR **st = stack->ary_array;
1297 register int sp = arglast[1];
1298 register STIO *stio;
1304 stio = stab_io(stab);
1305 if (!stio || !stio->ifp)
1308 addr = str_get(st[++sp]);
1310 taintproper("Insecure dependency in bind");
1312 return bind(fileno(stio->ifp), addr, st[sp]->str_cur) >= 0;
1316 warn("bind() on closed fd");
1322 do_connect(stab, arglast)
1326 register STR **st = stack->ary_array;
1327 register int sp = arglast[1];
1328 register STIO *stio;
1334 stio = stab_io(stab);
1335 if (!stio || !stio->ifp)
1338 addr = str_get(st[++sp]);
1340 taintproper("Insecure dependency in connect");
1342 return connect(fileno(stio->ifp), addr, st[sp]->str_cur) >= 0;
1346 warn("connect() on closed fd");
1352 do_listen(stab, arglast)
1356 register STR **st = stack->ary_array;
1357 register int sp = arglast[1];
1358 register STIO *stio;
1364 stio = stab_io(stab);
1365 if (!stio || !stio->ifp)
1368 backlog = (int)str_gnum(st[++sp]);
1369 return listen(fileno(stio->ifp), backlog) >= 0;
1373 warn("listen() on closed fd");
1378 do_accept(str, nstab, gstab)
1383 register STIO *nstio;
1384 register STIO *gstio;
1385 int len = sizeof buf;
1393 gstio = stab_io(gstab);
1394 nstio = stab_io(nstab);
1396 if (!gstio || !gstio->ifp)
1399 nstio = stab_io(nstab) = stio_new();
1400 else if (nstio->ifp)
1401 do_close(nstab,FALSE);
1403 fd = accept(fileno(gstio->ifp),buf,&len);
1406 nstio->ifp = fdopen(fd, "r");
1407 nstio->ofp = fdopen(fd, "w");
1409 if (!nstio->ifp || !nstio->ofp) {
1410 if (nstio->ifp) fclose(nstio->ifp);
1411 if (nstio->ofp) fclose(nstio->ofp);
1412 if (!nstio->ifp && !nstio->ofp) close(fd);
1416 str_nset(str, buf, len);
1421 warn("accept() on closed fd");
1423 str_sset(str,&str_undef);
1428 do_shutdown(stab, arglast)
1432 register STR **st = stack->ary_array;
1433 register int sp = arglast[1];
1434 register STIO *stio;
1440 stio = stab_io(stab);
1441 if (!stio || !stio->ifp)
1444 how = (int)str_gnum(st[++sp]);
1445 return shutdown(fileno(stio->ifp), how) >= 0;
1449 warn("shutdown() on closed fd");
1455 do_sopt(optype, stab, arglast)
1460 register STR **st = stack->ary_array;
1461 register int sp = arglast[1];
1462 register STIO *stio;
1470 stio = stab_io(stab);
1471 if (!stio || !stio->ifp)
1474 fd = fileno(stio->ifp);
1475 lvl = (int)str_gnum(st[sp+1]);
1476 optname = (int)str_gnum(st[sp+2]);
1479 st[sp] = str_2mortal(str_new(257));
1480 st[sp]->str_cur = 256;
1481 st[sp]->str_pok = 1;
1482 if (getsockopt(fd, lvl, optname, st[sp]->str_ptr, &st[sp]->str_cur) < 0)
1487 if (setsockopt(fd, lvl, optname, st[sp]->str_ptr, st[sp]->str_cur) < 0)
1497 warn("[gs]etsockopt() on closed fd");
1498 st[sp] = &str_undef;
1504 do_getsockname(optype, stab, arglast)
1509 register STR **st = stack->ary_array;
1510 register int sp = arglast[1];
1511 register STIO *stio;
1517 stio = stab_io(stab);
1518 if (!stio || !stio->ifp)
1521 st[sp] = str_2mortal(str_new(257));
1522 st[sp]->str_cur = 256;
1523 st[sp]->str_pok = 1;
1524 fd = fileno(stio->ifp);
1527 if (getsockname(fd, st[sp]->str_ptr, &st[sp]->str_cur) < 0)
1531 if (getpeername(fd, st[sp]->str_ptr, &st[sp]->str_cur) < 0)
1540 warn("get{sock,peer}name() on closed fd");
1542 st[sp] = &str_undef;
1548 do_ghent(which,gimme,arglast)
1553 register ARRAY *ary = stack;
1554 register int sp = arglast[0];
1555 register char **elem;
1557 struct hostent *gethostbyname();
1558 struct hostent *gethostbyaddr();
1559 #ifdef HAS_GETHOSTENT
1560 struct hostent *gethostent();
1562 struct hostent *hent;
1565 if (gimme != G_ARRAY) {
1566 astore(ary, ++sp, str_mortal(&str_undef));
1570 if (which == O_GHBYNAME) {
1571 char *name = str_get(ary->ary_array[sp+1]);
1573 hent = gethostbyname(name);
1575 else if (which == O_GHBYADDR) {
1576 STR *addrstr = ary->ary_array[sp+1];
1577 int addrtype = (int)str_gnum(ary->ary_array[sp+2]);
1578 char *addr = str_get(addrstr);
1580 hent = gethostbyaddr(addr,addrstr->str_cur,addrtype);
1583 #ifdef HAS_GETHOSTENT
1584 hent = gethostent();
1586 fatal("gethostent not implemented");
1590 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1591 str_set(str, hent->h_name);
1592 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1593 for (elem = hent->h_aliases; *elem; elem++) {
1594 str_cat(str, *elem);
1596 str_ncat(str," ",1);
1598 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1599 str_numset(str, (double)hent->h_addrtype);
1600 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1601 len = hent->h_length;
1602 str_numset(str, (double)len);
1604 for (elem = hent->h_addr_list; *elem; elem++) {
1605 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1606 str_nset(str, *elem, len);
1609 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1610 str_nset(str, hent->h_addr, len);
1615 (void)astore(ary, ++sp, str_mortal(&str_no));
1623 do_gnent(which,gimme,arglast)
1628 register ARRAY *ary = stack;
1629 register int sp = arglast[0];
1630 register char **elem;
1632 struct netent *getnetbyname();
1633 struct netent *getnetbyaddr();
1634 struct netent *getnetent();
1635 struct netent *nent;
1637 if (gimme != G_ARRAY) {
1638 astore(ary, ++sp, str_mortal(&str_undef));
1642 if (which == O_GNBYNAME) {
1643 char *name = str_get(ary->ary_array[sp+1]);
1645 nent = getnetbyname(name);
1647 else if (which == O_GNBYADDR) {
1648 unsigned long addr = U_L(str_gnum(ary->ary_array[sp+1]));
1649 int addrtype = (int)str_gnum(ary->ary_array[sp+2]);
1651 nent = getnetbyaddr((long)addr,addrtype);
1658 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1659 str_set(str, nent->n_name);
1660 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1661 for (elem = nent->n_aliases; *elem; elem++) {
1662 str_cat(str, *elem);
1664 str_ncat(str," ",1);
1666 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1667 str_numset(str, (double)nent->n_addrtype);
1668 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1669 str_numset(str, (double)nent->n_net);
1673 (void)astore(ary, ++sp, str_mortal(&str_no));
1681 do_gpent(which,gimme,arglast)
1686 register ARRAY *ary = stack;
1687 register int sp = arglast[0];
1688 register char **elem;
1690 struct protoent *getprotobyname();
1691 struct protoent *getprotobynumber();
1692 struct protoent *getprotoent();
1693 struct protoent *pent;
1695 if (gimme != G_ARRAY) {
1696 astore(ary, ++sp, str_mortal(&str_undef));
1700 if (which == O_GPBYNAME) {
1701 char *name = str_get(ary->ary_array[sp+1]);
1703 pent = getprotobyname(name);
1705 else if (which == O_GPBYNUMBER) {
1706 int proto = (int)str_gnum(ary->ary_array[sp+1]);
1708 pent = getprotobynumber(proto);
1711 pent = getprotoent();
1715 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1716 str_set(str, pent->p_name);
1717 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1718 for (elem = pent->p_aliases; *elem; elem++) {
1719 str_cat(str, *elem);
1721 str_ncat(str," ",1);
1723 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1724 str_numset(str, (double)pent->p_proto);
1728 (void)astore(ary, ++sp, str_mortal(&str_no));
1736 do_gsent(which,gimme,arglast)
1741 register ARRAY *ary = stack;
1742 register int sp = arglast[0];
1743 register char **elem;
1745 struct servent *getservbyname();
1746 struct servent *getservbynumber();
1747 struct servent *getservent();
1748 struct servent *sent;
1750 if (gimme != G_ARRAY) {
1751 astore(ary, ++sp, str_mortal(&str_undef));
1755 if (which == O_GSBYNAME) {
1756 char *name = str_get(ary->ary_array[sp+1]);
1757 char *proto = str_get(ary->ary_array[sp+2]);
1759 if (proto && !*proto)
1762 sent = getservbyname(name,proto);
1764 else if (which == O_GSBYPORT) {
1765 int port = (int)str_gnum(ary->ary_array[sp+1]);
1766 char *proto = str_get(ary->ary_array[sp+2]);
1768 sent = getservbyport(port,proto);
1771 sent = getservent();
1774 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1775 str_set(str, sent->s_name);
1776 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1777 for (elem = sent->s_aliases; *elem; elem++) {
1778 str_cat(str, *elem);
1780 str_ncat(str," ",1);
1782 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1784 str_numset(str, (double)ntohs(sent->s_port));
1786 str_numset(str, (double)(sent->s_port));
1788 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1789 str_set(str, sent->s_proto);
1793 (void)astore(ary, ++sp, str_mortal(&str_no));
1800 #endif /* HAS_SOCKET */
1804 do_select(gimme,arglast)
1808 register STR **st = stack->ary_array;
1809 register int sp = arglast[0];
1817 struct timeval timebuf;
1818 struct timeval *tbuf = &timebuf;
1820 #if BYTEORDER != 0x1234 && BYTEORDER != 0x12345678
1826 #if BYTEORDER & 0xf0000
1827 #define ORDERBYTE (0x88888888 - BYTEORDER)
1829 #define ORDERBYTE (0x4444 - BYTEORDER)
1834 for (i = 1; i <= 3; i++) {
1835 j = st[sp+i]->str_cur;
1840 #if BYTEORDER == 0x1234 || BYTEORDER == 0x12345678
1841 growsize = maxlen; /* little endians can use vecs directly */
1849 masksize = NFDBITS / NBBY;
1851 masksize = sizeof(long); /* documented int, everyone seems to use long */
1853 growsize = maxlen + (masksize - (maxlen % masksize));
1854 Zero(&fd_sets[0], 4, char*);
1857 for (i = 1; i <= 3; i++) {
1862 Str_Grow(str,growsize);
1863 s = str_get(str) + j;
1864 while (++j <= growsize) {
1868 else if (str->str_ptr) {
1869 Safefree(str->str_ptr);
1870 str->str_ptr = Nullch;
1873 #if BYTEORDER != 0x1234 && BYTEORDER != 0x12345678
1876 New(403, fd_sets[i], growsize, char);
1877 for (offset = 0; offset < growsize; offset += masksize) {
1878 for (j = 0, k=ORDERBYTE; j < masksize; j++, (k >>= 4))
1879 fd_sets[i][j+offset] = s[(k % masksize) + offset];
1885 if (str->str_nok || str->str_pok) {
1886 value = str_gnum(str);
1889 timebuf.tv_sec = (long)value;
1890 value -= (double)timebuf.tv_sec;
1891 timebuf.tv_usec = (long)(value * 1000000.0);
1894 tbuf = Null(struct timeval*);
1896 #if BYTEORDER == 0x1234 || BYTEORDER == 0x12345678
1910 for (i = 1; i <= 3; i++) {
1914 for (offset = 0; offset < growsize; offset += masksize) {
1915 for (j = 0, k=ORDERBYTE; j < masksize; j++, (k >>= 4))
1916 s[(k % masksize) + offset] = fd_sets[i][j+offset];
1922 st[++sp] = str_mortal(&str_no);
1923 str_numset(st[sp], (double)nfound);
1924 if (gimme == G_ARRAY && tbuf) {
1925 value = (double)(timebuf.tv_sec) +
1926 (double)(timebuf.tv_usec) / 1000000.0;
1927 st[++sp] = str_mortal(&str_no);
1928 str_numset(st[sp], value);
1936 do_spair(stab1, stab2, arglast)
1941 register STR **st = stack->ary_array;
1942 register int sp = arglast[2];
1943 register STIO *stio1;
1944 register STIO *stio2;
1945 int domain, type, protocol, fd[2];
1947 if (!stab1 || !stab2)
1950 stio1 = stab_io(stab1);
1951 stio2 = stab_io(stab2);
1953 stio1 = stab_io(stab1) = stio_new();
1954 else if (stio1->ifp)
1955 do_close(stab1,FALSE);
1957 stio2 = stab_io(stab2) = stio_new();
1958 else if (stio2->ifp)
1959 do_close(stab2,FALSE);
1961 domain = (int)str_gnum(st[++sp]);
1962 type = (int)str_gnum(st[++sp]);
1963 protocol = (int)str_gnum(st[++sp]);
1965 taintproper("Insecure dependency in socketpair");
1967 #ifdef HAS_SOCKETPAIR
1968 if (socketpair(domain,type,protocol,fd) < 0)
1971 fatal("Socketpair unimplemented");
1973 stio1->ifp = fdopen(fd[0], "r");
1974 stio1->ofp = fdopen(fd[0], "w");
1976 stio2->ifp = fdopen(fd[1], "r");
1977 stio2->ofp = fdopen(fd[1], "w");
1979 if (!stio1->ifp || !stio1->ofp || !stio2->ifp || !stio2->ofp) {
1980 if (stio1->ifp) fclose(stio1->ifp);
1981 if (stio1->ofp) fclose(stio1->ofp);
1982 if (!stio1->ifp && !stio1->ofp) close(fd[0]);
1983 if (stio2->ifp) fclose(stio2->ifp);
1984 if (stio2->ofp) fclose(stio2->ofp);
1985 if (!stio2->ifp && !stio2->ofp) close(fd[1]);
1992 #endif /* HAS_SOCKET */
1995 do_gpwent(which,gimme,arglast)
2001 register ARRAY *ary = stack;
2002 register int sp = arglast[0];
2004 struct passwd *getpwnam();
2005 struct passwd *getpwuid();
2006 struct passwd *getpwent();
2007 struct passwd *pwent;
2009 if (gimme != G_ARRAY) {
2010 astore(ary, ++sp, str_mortal(&str_undef));
2014 if (which == O_GPWNAM) {
2015 char *name = str_get(ary->ary_array[sp+1]);
2017 pwent = getpwnam(name);
2019 else if (which == O_GPWUID) {
2020 int uid = (int)str_gnum(ary->ary_array[sp+1]);
2022 pwent = getpwuid(uid);
2028 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2029 str_set(str, pwent->pw_name);
2030 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2031 str_set(str, pwent->pw_passwd);
2032 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2033 str_numset(str, (double)pwent->pw_uid);
2034 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2035 str_numset(str, (double)pwent->pw_gid);
2036 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2038 str_numset(str, (double)pwent->pw_change);
2041 str_numset(str, (double)pwent->pw_quota);
2044 str_set(str, pwent->pw_age);
2048 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2050 str_set(str,pwent->pw_class);
2053 str_set(str, pwent->pw_comment);
2056 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2057 str_set(str, pwent->pw_gecos);
2058 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2059 str_set(str, pwent->pw_dir);
2060 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2061 str_set(str, pwent->pw_shell);
2063 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2064 str_numset(str, (double)pwent->pw_expire);
2070 fatal("password routines not implemented");
2075 do_ggrent(which,gimme,arglast)
2081 register ARRAY *ary = stack;
2082 register int sp = arglast[0];
2083 register char **elem;
2085 struct group *getgrnam();
2086 struct group *getgrgid();
2087 struct group *getgrent();
2088 struct group *grent;
2090 if (gimme != G_ARRAY) {
2091 astore(ary, ++sp, str_mortal(&str_undef));
2095 if (which == O_GGRNAM) {
2096 char *name = str_get(ary->ary_array[sp+1]);
2098 grent = getgrnam(name);
2100 else if (which == O_GGRGID) {
2101 int gid = (int)str_gnum(ary->ary_array[sp+1]);
2103 grent = getgrgid(gid);
2109 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2110 str_set(str, grent->gr_name);
2111 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2112 str_set(str, grent->gr_passwd);
2113 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2114 str_numset(str, (double)grent->gr_gid);
2115 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2116 for (elem = grent->gr_mem; *elem; elem++) {
2117 str_cat(str, *elem);
2119 str_ncat(str," ",1);
2125 fatal("group routines not implemented");
2130 do_dirop(optype,stab,gimme,arglast)
2136 #if defined(DIRENT) && defined(HAS_READDIR)
2137 register ARRAY *ary = stack;
2138 register STR **st = ary->ary_array;
2139 register int sp = arglast[1];
2140 register STIO *stio;
2145 struct DIRENT *readdir();
2146 register struct DIRENT *dp;
2150 if (!(stio = stab_io(stab)))
2151 stio = stab_io(stab) = stio_new();
2152 if (!stio->dirp && optype != O_OPENDIR)
2158 closedir(stio->dirp);
2159 if (!(stio->dirp = opendir(str_get(st[sp+1]))))
2163 if (gimme == G_ARRAY) {
2165 while (dp = readdir(stio->dirp)) {
2167 (void)astore(ary,++sp,
2168 str_2mortal(str_make(dp->d_name,dp->d_namlen)));
2170 (void)astore(ary,++sp,
2171 str_2mortal(str_make(dp->d_name,0)));
2176 if (!(dp = readdir(stio->dirp)))
2178 st[sp] = str_mortal(&str_undef);
2180 str_nset(st[sp], dp->d_name, dp->d_namlen);
2182 str_set(st[sp], dp->d_name);
2192 st[sp] = str_mortal(&str_undef);
2193 str_numset(st[sp], (double)telldir(stio->dirp));
2196 st[sp] = str_mortal(&str_undef);
2197 along = (long)str_gnum(st[sp+1]);
2198 (void)seekdir(stio->dirp,along);
2202 st[sp] = str_mortal(&str_undef);
2203 (void)rewinddir(stio->dirp);
2206 st[sp] = str_mortal(&str_undef);
2207 (void)closedir(stio->dirp);
2214 st[sp] = &str_undef;
2218 fatal("Unimplemented directory operation");
2226 register STR **st = stack->ary_array;
2227 register int sp = arglast[1];
2228 register int items = arglast[2] - sp;
2231 register int tot = 0;
2235 for (st += ++sp; items--; st++)
2236 tainted |= (*st)->str_tainted;
2237 st = stack->ary_array;
2239 items = arglast[2] - sp;
2244 taintproper("Insecure dependency in chmod");
2248 val = (int)str_gnum(st[++sp]);
2250 if (chmod(str_get(st[++sp]),val))
2258 taintproper("Insecure dependency in chown");
2263 val = (int)str_gnum(st[++sp]);
2264 val2 = (int)str_gnum(st[++sp]);
2266 if (chown(str_get(st[++sp]),val,val2))
2275 taintproper("Insecure dependency in kill");
2279 s = str_get(st[++sp]);
2281 if (*s == 'S' && s[1] == 'I' && s[2] == 'G')
2283 if (!(val = whichsig(s)))
2284 fatal("Unrecognized signal name \"%s\"",s);
2287 val = (int)str_gnum(st[sp]);
2291 int proc = (int)str_gnum(st[++sp]);
2293 if (killpg(proc,val)) /* BSD */
2295 if (kill(-proc,val)) /* SYSV */
2302 if (kill((int)(str_gnum(st[++sp])),val))
2311 taintproper("Insecure dependency in unlink");
2315 s = str_get(st[++sp]);
2316 if (euid || unsafe) {
2320 else { /* don't let root wipe out directories without -U */
2322 if (lstat(s,&statbuf) < 0 || S_ISDIR(statbuf.st_mode))
2324 if (stat(s,&statbuf) < 0 || S_ISDIR(statbuf.st_mode))
2336 taintproper("Insecure dependency in utime");
2340 struct utimbuf utbuf;
2348 Zero(&utbuf, sizeof utbuf, char);
2349 utbuf.actime = (long)str_gnum(st[++sp]); /* time accessed */
2350 utbuf.modtime = (long)str_gnum(st[++sp]); /* time modified */
2355 if (utime(str_get(st[++sp]),&utbuf))
2367 /* Do the permissions allow some operation? Assumes statcache already set. */
2370 cando(bit, effective, statbufp)
2373 register struct stat *statbufp;
2376 /* [Comments and code from Len Reed]
2377 * MS-DOS "user" is similar to UNIX's "superuser," but can't write
2378 * to write-protected files. The execute permission bit is set
2379 * by the Miscrosoft C library stat() function for the following:
2384 * All files and directories are readable.
2385 * Directories and special files, e.g. "CON", cannot be
2387 * [Comment by Tom Dinger -- a directory can have the write-protect
2388 * bit set in the file system, but DOS permits changes to
2389 * the directory anyway. In addition, all bets are off
2390 * here for networked software, such as Novell and
2394 return (bit & statbufp->st_mode) ? TRUE : FALSE;
2397 if ((effective ? euid : uid) == 0) { /* root is special */
2398 if (bit == S_IXUSR) {
2399 if (statbufp->st_mode & 0111 || S_ISDIR(statbufp->st_mode))
2403 return TRUE; /* root reads and writes anything */
2406 if (statbufp->st_uid == (effective ? euid : uid) ) {
2407 if (statbufp->st_mode & bit)
2408 return TRUE; /* ok as "user" */
2410 else if (ingroup((int)statbufp->st_gid,effective)) {
2411 if (statbufp->st_mode & bit >> 3)
2412 return TRUE; /* ok as "group" */
2414 else if (statbufp->st_mode & bit >> 6)
2415 return TRUE; /* ok as "other" */
2417 #endif /* ! MSDOS */
2421 ingroup(testgid,effective)
2425 if (testgid == (effective ? egid : gid))
2427 #ifdef HAS_GETGROUPS
2432 GROUPSTYPE gary[NGROUPS];
2435 anum = getgroups(NGROUPS,gary);
2437 if (gary[anum] == testgid)
2444 #if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)
2447 do_ipcget(optype, arglast)
2451 register STR **st = stack->ary_array;
2452 register int sp = arglast[0];
2456 key = (key_t)str_gnum(st[++sp]);
2457 n = (optype == O_MSGGET) ? 0 : (int)str_gnum(st[++sp]);
2458 flags = (int)str_gnum(st[++sp]);
2464 return msgget(key, flags);
2468 return semget(key, n, flags);
2472 return shmget(key, n, flags);
2474 #if !defined(HAS_MSG) || !defined(HAS_SEM) || !defined(HAS_SHM)
2476 fatal("%s not implemented", opname[optype]);
2479 return -1; /* should never happen */
2483 do_ipcctl(optype, arglast)
2487 register STR **st = stack->ary_array;
2488 register int sp = arglast[0];
2491 int id, n, cmd, infosize, getinfo, ret;
2493 id = (int)str_gnum(st[++sp]);
2494 n = (optype == O_SEMCTL) ? (int)str_gnum(st[++sp]) : 0;
2495 cmd = (int)str_gnum(st[++sp]);
2499 getinfo = (cmd == IPC_STAT);
2505 if (cmd == IPC_STAT || cmd == IPC_SET)
2506 infosize = sizeof(struct msqid_ds);
2511 if (cmd == IPC_STAT || cmd == IPC_SET)
2512 infosize = sizeof(struct shmid_ds);
2517 if (cmd == IPC_STAT || cmd == IPC_SET)
2518 infosize = sizeof(struct semid_ds);
2519 else if (cmd == GETALL || cmd == SETALL)
2521 struct semid_ds semds;
2522 if (semctl(id, 0, IPC_STAT, &semds) == -1)
2524 getinfo = (cmd == GETALL);
2525 #ifdef _POSIX_SOURCE
2526 infosize = semds.sem_nsems * sizeof(ushort_t);
2528 infosize = semds.sem_nsems * sizeof(ushort);
2533 #if !defined(HAS_MSG) || !defined(HAS_SEM) || !defined(HAS_SHM)
2535 fatal("%s not implemented", opname[optype]);
2543 STR_GROW(astr, infosize+1);
2549 if (astr->str_cur != infosize)
2558 int i = (int)str_gnum(astr);
2559 a = (char *)i; /* ouch */
2566 ret = msgctl(id, cmd, a);
2571 ret = semctl(id, n, cmd, a);
2576 ret = shmctl(id, cmd, a);
2580 if (getinfo && ret >= 0) {
2581 astr->str_cur = infosize;
2582 astr->str_ptr[infosize] = '\0';
2592 register STR **st = stack->ary_array;
2593 register int sp = arglast[0];
2596 int id, msize, flags;
2598 id = (int)str_gnum(st[++sp]);
2600 flags = (int)str_gnum(st[++sp]);
2601 mbuf = str_get(mstr);
2602 if ((msize = mstr->str_cur - sizeof(long)) < 0) {
2607 return msgsnd(id, mbuf, msize, flags);
2609 fatal("msgsnd not implemented");
2618 register STR **st = stack->ary_array;
2619 register int sp = arglast[0];
2623 int id, msize, flags, ret;
2625 id = (int)str_gnum(st[++sp]);
2627 msize = (int)str_gnum(st[++sp]);
2628 mtype = (long)str_gnum(st[++sp]);
2629 flags = (int)str_gnum(st[++sp]);
2630 mbuf = str_get(mstr);
2631 if (mstr->str_cur < sizeof(long)+msize+1) {
2632 STR_GROW(mstr, sizeof(long)+msize+1);
2633 mbuf = str_get(mstr);
2636 ret = msgrcv(id, mbuf, msize, mtype, flags);
2638 mstr->str_cur = sizeof(long)+ret;
2639 mstr->str_ptr[sizeof(long)+ret] = '\0';
2643 fatal("msgrcv not implemented");
2652 register STR **st = stack->ary_array;
2653 register int sp = arglast[0];
2658 id = (int)str_gnum(st[++sp]);
2660 opbuf = str_get(opstr);
2661 opsize = opstr->str_cur;
2662 if (opsize < sizeof(struct sembuf)
2663 || (opsize % sizeof(struct sembuf)) != 0) {
2668 return semop(id, opbuf, opsize/sizeof(struct sembuf));
2670 fatal("semop not implemented");
2675 do_shmio(optype, arglast)
2680 register STR **st = stack->ary_array;
2681 register int sp = arglast[0];
2684 int id, mpos, msize;
2685 struct shmid_ds shmds;
2686 extern char *shmat();
2688 id = (int)str_gnum(st[++sp]);
2690 mpos = (int)str_gnum(st[++sp]);
2691 msize = (int)str_gnum(st[++sp]);
2693 if (shmctl(id, IPC_STAT, &shmds) == -1)
2695 if (mpos < 0 || msize < 0 || mpos + msize > shmds.shm_segsz) {
2696 errno = EFAULT; /* can't do as caller requested */
2699 shm = shmat(id, (char *)NULL, (optype == O_SHMREAD) ? SHM_RDONLY : 0);
2700 if (shm == (char *)-1) /* I hate System V IPC, I really do */
2702 mbuf = str_get(mstr);
2703 if (optype == O_SHMREAD) {
2704 if (mstr->str_cur < msize) {
2705 STR_GROW(mstr, msize+1);
2706 mbuf = str_get(mstr);
2708 bcopy(shm + mpos, mbuf, msize);
2709 mstr->str_cur = msize;
2710 mstr->str_ptr[msize] = '\0';
2715 if ((n = mstr->str_cur) > msize)
2717 bcopy(mbuf, shm + mpos, n);
2719 bzero(shm + mpos + n, msize - n);
2723 fatal("shm I/O not implemented");
2727 #endif /* SYSV IPC */