1 /* $Header: doio.c,v 4.0 91/03/20 01:07:06 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 4.0 91/03/20 01:07:06 lwall
18 #include <sys/socket.h>
23 #if defined(HAS_SELECT) && !defined(I_SYS_TIME)
24 #include <sys/select.h>
30 #include <sys/select.h>
34 #if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)
64 int laststype = O_STAT;
67 do_open(stab,name,len)
73 register STIO *stio = stab_io(stab);
74 char *myname = savestr(name);
78 char mode[3]; /* stdio file mode ("r\0" or "r+\0") */
81 forkprocess = 1; /* assume true if no fork */
82 while (len && isspace(name[len-1]))
85 stio = stab_io(stab) = stio_new();
87 fd = fileno(stio->ifp);
88 if (stio->type == '|')
89 result = mypclose(stio->ifp);
90 else if (stio->type == '-')
92 else if (stio->ifp != stio->ofp) {
94 result = fclose(stio->ofp);
95 fclose(stio->ifp); /* clear stdio, fd already closed */
98 result = fclose(stio->ifp);
101 result = fclose(stio->ifp);
102 if (result == EOF && fd > 2)
103 fprintf(stderr,"Warning: unable to close filehandle %s properly.\n",
105 stio->ofp = stio->ifp = Nullfp;
107 if (*name == '+' && len > 1 && name[len-1] != '|') { /* scary */
118 for (name++; isspace(*name); name++) ;
121 taintproper("Insecure dependency in piped open");
123 fp = mypopen(name,"w");
126 else if (*name == '>') {
128 taintproper("Insecure dependency in open");
132 mode[0] = stio->type = 'a';
141 while (isspace(*name))
146 stab = stabent(name,FALSE);
147 if (!stab || !stab_io(stab))
149 if (stab_io(stab) && stab_io(stab)->ifp) {
150 fd = fileno(stab_io(stab)->ifp);
151 if (stab_io(stab)->type == 's')
157 if (!(fp = fdopen(fd = dup(fd),mode))) {
162 while (isspace(*name))
164 if (strEQ(name,"-")) {
169 fp = fopen(name,mode);
177 while (isspace(*name))
181 if (strEQ(name,"-")) {
186 fp = fopen(name,mode);
188 else if (name[len-1] == '|') {
191 taintproper("Insecure dependency in piped open");
194 while (len && isspace(name[len-1]))
196 for (; isspace(*name); name++) ;
197 fp = mypopen(name,"r");
202 for (; isspace(*name); name++) ;
203 if (strEQ(name,"-")) {
208 fp = fopen(name,"r");
215 stio->type != '|' && stio->type != '-') {
216 if (fstat(fileno(fp),&statbuf) < 0) {
220 if (S_ISSOCK(statbuf.st_mode))
221 stio->type = 's'; /* in case a socket was passed in to us */
223 else if (!(statbuf.st_mode & S_IFMT))
224 stio->type = 's'; /* some OS's return 0 on fstat()ed socket */
227 #if defined(HAS_FCNTL) && defined(F_SETFD)
229 fcntl(fd,F_SETFD,fd >= 3);
233 if (stio->type != 's')
236 if (!(stio->ofp = fdopen(fileno(fp),"w"))) {
253 static int filemode = 0;
255 static char *oldname;
258 argvoutstab = stabent("ARGVOUT",TRUE);
259 if (filemode & (S_ISUID|S_ISGID)) {
260 fflush(stab_io(argvoutstab)->ifp); /* chmod must follow last write */
262 (void)fchmod(lastfd,filemode);
264 (void)chmod(oldname,filemode);
268 while (alen(stab_xarray(stab)) >= 0) {
269 str = ashift(stab_xarray(stab));
270 str_sset(stab_val(stab),str);
271 STABSET(stab_val(stab));
272 oldname = str_get(stab_val(stab));
273 if (do_open(stab,oldname,stab_val(stab)->str_cur)) {
276 taintproper("Insecure dependency in inplace open");
278 if (strEQ(oldname,"-")) {
280 defoutstab = stabent("STDOUT",TRUE);
281 return stab_io(stab)->ifp;
283 filedev = statbuf.st_dev;
284 fileino = statbuf.st_ino;
285 filemode = statbuf.st_mode;
286 fileuid = statbuf.st_uid;
287 filegid = statbuf.st_gid;
288 if (!S_ISREG(filemode)) {
289 warn("Can't do inplace edit: %s is not a regular file",
291 do_close(stab,FALSE);
297 add_suffix(str,inplace);
299 str_cat(str,inplace);
301 #ifndef FLEXFILENAMES
302 if (stat(str->str_ptr,&statbuf) >= 0
303 && statbuf.st_dev == filedev
304 && statbuf.st_ino == fileino ) {
305 warn("Can't do inplace edit: %s > 14 characters",
307 do_close(stab,FALSE);
314 if (rename(oldname,str->str_ptr) < 0) {
315 warn("Can't rename %s to %s: %s, skipping file",
316 oldname, str->str_ptr, strerror(errno) );
317 do_close(stab,FALSE);
322 do_close(stab,FALSE);
323 (void)unlink(str->str_ptr);
324 (void)rename(oldname,str->str_ptr);
325 do_open(stab,str->str_ptr,stab_val(stab)->str_cur);
328 (void)UNLINK(str->str_ptr);
329 if (link(oldname,str->str_ptr) < 0) {
330 warn("Can't rename %s to %s: %s, skipping file",
331 oldname, str->str_ptr, strerror(errno) );
332 do_close(stab,FALSE);
336 (void)UNLINK(oldname);
341 if (UNLINK(oldname) < 0) {
342 warn("Can't rename %s to %s: %s, skipping file",
343 oldname, str->str_ptr, strerror(errno) );
344 do_close(stab,FALSE);
349 fatal("Can't do inplace edit without backup");
354 str_cat(str,oldname);
355 errno = 0; /* in case sprintf set errno */
356 if (!do_open(argvoutstab,str->str_ptr,str->str_cur)) {
357 warn("Can't do inplace edit on %s: %s",
358 oldname, strerror(errno) );
359 do_close(stab,FALSE);
363 defoutstab = argvoutstab;
364 lastfd = fileno(stab_io(argvoutstab)->ifp);
365 (void)fstat(lastfd,&statbuf);
367 (void)fchmod(lastfd,filemode);
369 (void)chmod(oldname,filemode);
371 if (fileuid != statbuf.st_uid || filegid != statbuf.st_gid) {
373 (void)fchown(lastfd,fileuid,filegid);
376 (void)chown(oldname,fileuid,filegid);
382 return stab_io(stab)->ifp;
385 fprintf(stderr,"Can't open %s: %s\n",str_get(str), strerror(errno));
389 (void)do_close(argvoutstab,FALSE);
390 defoutstab = stabent("STDOUT",TRUE);
397 do_pipe(str, rstab, wstab)
402 register STIO *rstio;
403 register STIO *wstio;
411 rstio = stab_io(rstab);
412 wstio = stab_io(wstab);
415 rstio = stab_io(rstab) = stio_new();
417 do_close(rstab,FALSE);
419 wstio = stab_io(wstab) = stio_new();
421 do_close(wstab,FALSE);
425 rstio->ifp = fdopen(fd[0], "r");
426 wstio->ofp = fdopen(fd[1], "w");
427 wstio->ifp = wstio->ofp;
430 if (!rstio->ifp || !wstio->ofp) {
431 if (rstio->ifp) fclose(rstio->ifp);
433 if (wstio->ofp) fclose(wstio->ofp);
438 str_sset(str,&str_yes);
442 str_sset(str,&str_undef);
448 do_close(stab,explicit)
460 stio = stab_io(stab);
461 if (!stio) { /* never opened */
462 if (dowarn && explicit)
463 warn("Close on unopened file <%s>",stab_name(stab));
467 if (stio->type == '|') {
468 status = mypclose(stio->ifp);
469 retval = (status == 0);
470 statusvalue = (unsigned short)status & 0xffff;
472 else if (stio->type == '-')
475 if (stio->ofp && stio->ofp != stio->ifp) { /* a socket */
476 retval = (fclose(stio->ofp) != EOF);
477 fclose(stio->ifp); /* clear stdio, fd already closed */
480 retval = (fclose(stio->ifp) != EOF);
482 stio->ofp = stio->ifp = Nullfp;
497 if (!stab) { /* eof() */
499 stio = stab_io(argvstab);
504 stio = stab_io(stab);
511 #ifdef STDSTDIO /* (the code works without this) */
512 if (stio->ifp->_cnt > 0) /* cheat a little, since */
513 return FALSE; /* this is the most usual case */
516 ch = getc(stio->ifp);
518 (void)ungetc(ch, stio->ifp);
522 if (stio->ifp->_cnt < -1)
523 stio->ifp->_cnt = -1;
525 if (!stab) { /* not necessarily a real EOF yet? */
526 if (!nextargv(argvstab)) /* get another fp handy */
530 return TRUE; /* normal fp, definitely end of file */
544 stio = stab_io(stab);
545 if (!stio || !stio->ifp)
549 (void)fseek (stio->ifp, 0L, 2); /* ultrix 1.2 workaround */
551 return ftell(stio->ifp);
555 warn("tell() on unopened file");
560 do_seek(stab, pos, whence)
570 stio = stab_io(stab);
571 if (!stio || !stio->ifp)
575 (void)fseek (stio->ifp, 0L, 2); /* ultrix 1.2 workaround */
577 return fseek(stio->ifp, pos, whence) >= 0;
581 warn("seek() on unopened file");
586 do_ctl(optype,stab,func,argstr)
596 if (!stab || !argstr)
598 stio = stab_io(stab);
602 if (argstr->str_pok || !argstr->str_nok) {
603 if (!argstr->str_pok)
608 #define IOCPARM_LEN(x) (((x) >> 16) & IOCPARM_MASK)
612 retval = IOCPARM_LEN(func); /* on BSDish systes we're safe */
614 retval = 256; /* otherwise guess at what's safe */
616 if (argstr->str_cur < retval) {
617 Str_Grow(argstr,retval+1);
618 argstr->str_cur = retval;
622 s[argstr->str_cur] = 17; /* a little sanity check here */
625 retval = (int)str_gnum(argstr);
627 s = (char*)(long)retval; /* ouch */
629 s = (char*)retval; /* ouch */
634 if (optype == O_IOCTL)
635 retval = ioctl(fileno(stio->ifp), func, s);
638 fatal("fcntl is not implemented");
641 retval = fcntl(fileno(stio->ifp), func, s);
643 fatal("fcntl is not implemented");
650 if (argstr->str_pok) {
651 if (s[argstr->str_cur] != 17)
652 fatal("Return value overflowed string");
653 s[argstr->str_cur] = 0; /* put our null back */
659 do_stat(str,arg,gimme,arglast)
665 register ARRAY *ary = stack;
666 register int sp = arglast[0] + 1;
669 if ((arg[1].arg_type & A_MASK) == A_WORD) {
670 tmpstab = arg[1].arg_ptr.arg_stab;
671 if (tmpstab != defstab) {
674 str_set(statname,"");
675 if (!stab_io(tmpstab) || !stab_io(tmpstab)->ifp ||
676 fstat(fileno(stab_io(tmpstab)->ifp),&statcache) < 0) {
681 else if (laststatval < 0)
685 str_set(statname,str_get(ary->ary_array[sp]));
688 laststype = arg->arg_type;
689 if (arg->arg_type == O_LSTAT)
690 laststatval = lstat(str_get(statname),&statcache);
693 laststatval = stat(str_get(statname),&statcache);
698 if (gimme != G_ARRAY) {
700 str_sset(str,&str_yes);
702 str_sset(str,&str_undef);
704 ary->ary_array[sp] = str;
710 (void)astore(ary,++sp,
711 str_2mortal(str_nmake((double)statcache.st_dev)));
712 (void)astore(ary,++sp,
713 str_2mortal(str_nmake((double)statcache.st_ino)));
714 (void)astore(ary,++sp,
715 str_2mortal(str_nmake((double)statcache.st_mode)));
716 (void)astore(ary,++sp,
717 str_2mortal(str_nmake((double)statcache.st_nlink)));
718 (void)astore(ary,++sp,
719 str_2mortal(str_nmake((double)statcache.st_uid)));
720 (void)astore(ary,++sp,
721 str_2mortal(str_nmake((double)statcache.st_gid)));
722 (void)astore(ary,++sp,
723 str_2mortal(str_nmake((double)statcache.st_rdev)));
724 (void)astore(ary,++sp,
725 str_2mortal(str_nmake((double)statcache.st_size)));
726 (void)astore(ary,++sp,
727 str_2mortal(str_nmake((double)statcache.st_atime)));
728 (void)astore(ary,++sp,
729 str_2mortal(str_nmake((double)statcache.st_mtime)));
730 (void)astore(ary,++sp,
731 str_2mortal(str_nmake((double)statcache.st_ctime)));
733 (void)astore(ary,++sp,
734 str_2mortal(str_nmake((double)statcache.st_blksize)));
735 (void)astore(ary,++sp,
736 str_2mortal(str_nmake((double)statcache.st_blocks)));
738 (void)astore(ary,++sp,
739 str_2mortal(str_make("",0)));
740 (void)astore(ary,++sp,
741 str_2mortal(str_make("",0)));
744 (void)astore(ary,++sp,str_nmake(0.0));
750 #if !defined(HAS_TRUNCATE) && !defined(HAS_CHSIZE) && defined(F_FREESP)
751 /* code courtesy of William Kucharski */
754 int chsize(fd, length)
755 int fd; /* file descriptor */
756 off_t length; /* length to set file to */
762 if (fstat(fd, &filebuf) < 0)
765 if (filebuf.st_size < length) {
767 /* extend file length */
769 if ((lseek(fd, (length - 1), 0)) < 0)
772 /* write a "0" byte */
774 if ((write(fd, "", 1)) != 1)
778 /* truncate length */
783 fl.l_type = F_WRLCK; /* write lock on file space */
786 * This relies on the UNDOCUMENTED F_FREESP argument to
787 * fcntl(2), which truncates the file so that it ends at the
788 * position indicated by fl.l_start.
790 * Will minor miracles never cease?
793 if (fcntl(fd, F_FREESP, &fl) < 0)
800 #endif /* F_FREESP */
803 do_truncate(str,arg,gimme,arglast)
809 register ARRAY *ary = stack;
810 register int sp = arglast[0] + 1;
811 off_t len = (off_t)str_gnum(ary->ary_array[sp+1]);
815 #if defined(HAS_TRUNCATE) || defined(HAS_CHSIZE)
817 if ((arg[1].arg_type & A_MASK) == A_WORD) {
818 tmpstab = arg[1].arg_ptr.arg_stab;
819 if (!stab_io(tmpstab) ||
820 ftruncate(fileno(stab_io(tmpstab)->ifp), len) < 0)
823 else if (truncate(str_get(ary->ary_array[sp]), len) < 0)
826 if ((arg[1].arg_type & A_MASK) == A_WORD) {
827 tmpstab = arg[1].arg_ptr.arg_stab;
828 if (!stab_io(tmpstab) ||
829 chsize(fileno(stab_io(tmpstab)->ifp), len) < 0)
835 if ((tmpfd = open(str_get(ary->ary_array[sp]), 0)) < 0)
838 if (chsize(tmpfd, len) < 0)
846 str_sset(str,&str_yes);
848 str_sset(str,&str_undef);
850 ary->ary_array[sp] = str;
853 fatal("truncate not implemented");
858 looks_like_number(str)
867 send = s + str->str_cur;
872 if (*s == '+' || *s == '-')
880 else if (s == str->str_ptr)
886 if (*s == 'e' || *s == 'E') {
888 if (*s == '+' || *s == '-')
909 warn("print to unopened file");
915 ((str->str_nok && str->str_u.str_nval != 0.0)
916 || (looks_like_number(str) && str_gnum(str) != 0.0) ) ) {
917 fprintf(fp, ofmt, str->str_u.str_nval);
922 if (*tmps == 'S' && tmps[1] == 't' && tmps[2] == 'B' && tmps[3] == '\0'
923 && str->str_cur == sizeof(STBP) && strlen(tmps) < str->str_cur) {
924 STR *tmpstr = str_mortal(&str_undef);
925 stab_fullname(tmpstr,((STAB*)str));/* a stab value, be nice */
930 if (str->str_cur && (fwrite(tmps,1,str->str_cur,fp) == 0 || ferror(fp)))
937 do_aprint(arg,fp,arglast)
942 register STR **st = stack->ary_array;
943 register int sp = arglast[1];
945 register int items = arglast[2] - sp;
949 warn("print to unopened file");
953 if (arg->arg_type == O_PRTF) {
954 do_sprintf(arg->arg_ptr.arg_str,items,st);
955 retval = do_print(arg->arg_ptr.arg_str,fp);
958 retval = (items <= 0);
959 for (; items > 0; items--,st++) {
960 if (retval && ofslen) {
961 if (fwrite(ofs, 1, ofslen, fp) == 0 || ferror(fp)) {
966 if (!(retval = do_print(*st, fp)))
969 if (retval && orslen)
970 if (fwrite(ors, 1, orslen, fp) == 0 || ferror(fp))
984 if (arg[1].arg_type & A_DONT) {
985 stio = stab_io(arg[1].arg_ptr.arg_stab);
986 if (stio && stio->ifp) {
987 statstab = arg[1].arg_ptr.arg_stab;
988 str_set(statname,"");
989 return (laststatval = fstat(fileno(stio->ifp), &statcache));
992 if (arg[1].arg_ptr.arg_stab == defstab)
995 warn("Stat on unopened file <%s>",
996 stab_name(arg[1].arg_ptr.arg_stab));
998 str_set(statname,"");
999 return (laststatval = -1);
1003 statstab = Nullstab;
1004 str_set(statname,str_get(str));
1005 return (laststatval = stat(str_get(str),&statcache));
1014 if (arg[1].arg_type & A_DONT) {
1015 if (arg[1].arg_ptr.arg_stab == defstab) {
1016 if (laststype != O_LSTAT)
1017 fatal("The stat preceding -l _ wasn't an lstat");
1020 fatal("You can't use -l on a filehandle");
1023 laststype = O_LSTAT;
1024 statstab = Nullstab;
1025 str_set(statname,str_get(str));
1027 return (laststatval = lstat(str_get(str),&statcache));
1029 return (laststatval = stat(str_get(str),&statcache));
1042 register STDCHAR *s;
1043 register STIO *stio;
1045 if (arg[1].arg_type & A_DONT) {
1046 if (arg[1].arg_ptr.arg_stab == defstab) {
1048 stio = stab_io(statstab);
1051 goto really_filename;
1055 statstab = arg[1].arg_ptr.arg_stab;
1056 str_set(statname,"");
1057 stio = stab_io(statstab);
1059 if (stio && stio->ifp) {
1061 fstat(fileno(stio->ifp),&statcache);
1062 if (stio->ifp->_cnt <= 0) {
1063 i = getc(stio->ifp);
1065 (void)ungetc(i,stio->ifp);
1067 if (stio->ifp->_cnt <= 0) /* null file is anything */
1069 len = stio->ifp->_cnt + (stio->ifp->_ptr - stio->ifp->_base);
1070 s = stio->ifp->_base;
1072 fatal("-T and -B not implemented on filehandles\n");
1077 warn("Test on unopened file <%s>",
1078 stab_name(arg[1].arg_ptr.arg_stab));
1083 statstab = Nullstab;
1084 str_set(statname,str_get(str));
1086 i = open(str_get(str),0);
1089 fstat(i,&statcache);
1090 len = read(i,tbuf,512);
1092 if (len <= 0) /* null file is anything */
1097 /* now scan s to look for textiness */
1099 for (i = 0; i < len; i++,s++) {
1100 if (!*s) { /* null never allowed in text */
1107 *s != '\n' && *s != '\r' && *s != '\b' &&
1108 *s != '\t' && *s != '\f' && *s != 27)
1112 if ((odd * 10 > len) == (arg->arg_type == O_FTTEXT)) /* allow 10% odd */
1119 do_aexec(really,arglast)
1123 register STR **st = stack->ary_array;
1124 register int sp = arglast[1];
1125 register int items = arglast[2] - sp;
1131 New(401,argv, items+1, char*);
1133 for (st += ++sp; items > 0; items--,st++) {
1135 *a++ = str_get(*st);
1141 if (*argv[0] != '/') /* will execvp use PATH? */
1142 taintenv(); /* testing IFS here is overkill, probably */
1144 if (really && *(tmps = str_get(really)))
1147 execvp(argv[0],argv);
1153 static char **Argv = Null(char **);
1154 static char *Cmd = Nullch;
1161 Argv = Null(char **);
1179 taintproper("Insecure dependency in exec");
1182 /* save an extra exec if possible */
1185 if (strnEQ(cmd,cshname,cshlen) && strnEQ(cmd+cshlen," -c",3)) {
1201 if (s[-1] == '\'') {
1203 execl(cshname,"csh", flags,ncmd,(char*)0);
1211 /* see if there are shell metacharacters in it */
1213 for (s = cmd; *s && isalpha(*s); s++) ; /* catch VAR=val gizmo */
1216 for (s = cmd; *s; s++) {
1217 if (*s != ' ' && !isalpha(*s) && index("$&*(){}[]'\";\\|?<>~`\n",*s)) {
1218 if (*s == '\n' && !s[1]) {
1223 execl("/bin/sh","sh","-c",cmd,(char*)0);
1227 New(402,Argv, (s - cmd) / 2 + 2, char*);
1228 Cmd = nsavestr(cmd, s-cmd);
1230 for (s = Cmd; *s;) {
1231 while (*s && isspace(*s)) s++;
1234 while (*s && !isspace(*s)) s++;
1240 execvp(Argv[0],Argv);
1241 if (errno == ENOEXEC) { /* for system V NIH syndrome */
1252 do_socket(stab, arglast)
1256 register STR **st = stack->ary_array;
1257 register int sp = arglast[1];
1258 register STIO *stio;
1259 int domain, type, protocol, fd;
1264 stio = stab_io(stab);
1266 stio = stab_io(stab) = stio_new();
1268 do_close(stab,FALSE);
1270 domain = (int)str_gnum(st[++sp]);
1271 type = (int)str_gnum(st[++sp]);
1272 protocol = (int)str_gnum(st[++sp]);
1274 taintproper("Insecure dependency in socket");
1276 fd = socket(domain,type,protocol);
1279 stio->ifp = fdopen(fd, "r"); /* stdio gets confused about sockets */
1280 stio->ofp = fdopen(fd, "w");
1282 if (!stio->ifp || !stio->ofp) {
1283 if (stio->ifp) fclose(stio->ifp);
1284 if (stio->ofp) fclose(stio->ofp);
1285 if (!stio->ifp && !stio->ofp) close(fd);
1293 do_bind(stab, arglast)
1297 register STR **st = stack->ary_array;
1298 register int sp = arglast[1];
1299 register STIO *stio;
1305 stio = stab_io(stab);
1306 if (!stio || !stio->ifp)
1309 addr = str_get(st[++sp]);
1311 taintproper("Insecure dependency in bind");
1313 return bind(fileno(stio->ifp), addr, st[sp]->str_cur) >= 0;
1317 warn("bind() on closed fd");
1323 do_connect(stab, arglast)
1327 register STR **st = stack->ary_array;
1328 register int sp = arglast[1];
1329 register STIO *stio;
1335 stio = stab_io(stab);
1336 if (!stio || !stio->ifp)
1339 addr = str_get(st[++sp]);
1341 taintproper("Insecure dependency in connect");
1343 return connect(fileno(stio->ifp), addr, st[sp]->str_cur) >= 0;
1347 warn("connect() on closed fd");
1353 do_listen(stab, arglast)
1357 register STR **st = stack->ary_array;
1358 register int sp = arglast[1];
1359 register STIO *stio;
1365 stio = stab_io(stab);
1366 if (!stio || !stio->ifp)
1369 backlog = (int)str_gnum(st[++sp]);
1370 return listen(fileno(stio->ifp), backlog) >= 0;
1374 warn("listen() on closed fd");
1379 do_accept(str, nstab, gstab)
1384 register STIO *nstio;
1385 register STIO *gstio;
1386 int len = sizeof buf;
1394 gstio = stab_io(gstab);
1395 nstio = stab_io(nstab);
1397 if (!gstio || !gstio->ifp)
1400 nstio = stab_io(nstab) = stio_new();
1401 else if (nstio->ifp)
1402 do_close(nstab,FALSE);
1404 fd = accept(fileno(gstio->ifp),buf,&len);
1407 nstio->ifp = fdopen(fd, "r");
1408 nstio->ofp = fdopen(fd, "w");
1410 if (!nstio->ifp || !nstio->ofp) {
1411 if (nstio->ifp) fclose(nstio->ifp);
1412 if (nstio->ofp) fclose(nstio->ofp);
1413 if (!nstio->ifp && !nstio->ofp) close(fd);
1417 str_nset(str, buf, len);
1422 warn("accept() on closed fd");
1424 str_sset(str,&str_undef);
1429 do_shutdown(stab, arglast)
1433 register STR **st = stack->ary_array;
1434 register int sp = arglast[1];
1435 register STIO *stio;
1441 stio = stab_io(stab);
1442 if (!stio || !stio->ifp)
1445 how = (int)str_gnum(st[++sp]);
1446 return shutdown(fileno(stio->ifp), how) >= 0;
1450 warn("shutdown() on closed fd");
1456 do_sopt(optype, stab, arglast)
1461 register STR **st = stack->ary_array;
1462 register int sp = arglast[1];
1463 register STIO *stio;
1471 stio = stab_io(stab);
1472 if (!stio || !stio->ifp)
1475 fd = fileno(stio->ifp);
1476 lvl = (int)str_gnum(st[sp+1]);
1477 optname = (int)str_gnum(st[sp+2]);
1480 st[sp] = str_2mortal(str_new(257));
1481 st[sp]->str_cur = 256;
1482 st[sp]->str_pok = 1;
1483 if (getsockopt(fd, lvl, optname, st[sp]->str_ptr, &st[sp]->str_cur) < 0)
1488 if (setsockopt(fd, lvl, optname, st[sp]->str_ptr, st[sp]->str_cur) < 0)
1498 warn("[gs]etsockopt() on closed fd");
1499 st[sp] = &str_undef;
1505 do_getsockname(optype, stab, arglast)
1510 register STR **st = stack->ary_array;
1511 register int sp = arglast[1];
1512 register STIO *stio;
1518 stio = stab_io(stab);
1519 if (!stio || !stio->ifp)
1522 st[sp] = str_2mortal(str_new(257));
1523 st[sp]->str_cur = 256;
1524 st[sp]->str_pok = 1;
1525 fd = fileno(stio->ifp);
1528 if (getsockname(fd, st[sp]->str_ptr, &st[sp]->str_cur) < 0)
1532 if (getpeername(fd, st[sp]->str_ptr, &st[sp]->str_cur) < 0)
1541 warn("get{sock,peer}name() on closed fd");
1543 st[sp] = &str_undef;
1549 do_ghent(which,gimme,arglast)
1554 register ARRAY *ary = stack;
1555 register int sp = arglast[0];
1556 register char **elem;
1558 struct hostent *gethostbyname();
1559 struct hostent *gethostbyaddr();
1560 #ifdef HAS_GETHOSTENT
1561 struct hostent *gethostent();
1563 struct hostent *hent;
1566 if (gimme != G_ARRAY) {
1567 astore(ary, ++sp, str_mortal(&str_undef));
1571 if (which == O_GHBYNAME) {
1572 char *name = str_get(ary->ary_array[sp+1]);
1574 hent = gethostbyname(name);
1576 else if (which == O_GHBYADDR) {
1577 STR *addrstr = ary->ary_array[sp+1];
1578 int addrtype = (int)str_gnum(ary->ary_array[sp+2]);
1579 char *addr = str_get(addrstr);
1581 hent = gethostbyaddr(addr,addrstr->str_cur,addrtype);
1584 #ifdef HAS_GETHOSTENT
1585 hent = gethostent();
1587 fatal("gethostent not implemented");
1591 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1592 str_set(str, hent->h_name);
1593 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1594 for (elem = hent->h_aliases; *elem; elem++) {
1595 str_cat(str, *elem);
1597 str_ncat(str," ",1);
1599 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1600 str_numset(str, (double)hent->h_addrtype);
1601 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1602 len = hent->h_length;
1603 str_numset(str, (double)len);
1605 for (elem = hent->h_addr_list; *elem; elem++) {
1606 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1607 str_nset(str, *elem, len);
1610 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1611 str_nset(str, hent->h_addr, len);
1616 (void)astore(ary, ++sp, str_mortal(&str_no));
1624 do_gnent(which,gimme,arglast)
1629 register ARRAY *ary = stack;
1630 register int sp = arglast[0];
1631 register char **elem;
1633 struct netent *getnetbyname();
1634 struct netent *getnetbyaddr();
1635 struct netent *getnetent();
1636 struct netent *nent;
1638 if (gimme != G_ARRAY) {
1639 astore(ary, ++sp, str_mortal(&str_undef));
1643 if (which == O_GNBYNAME) {
1644 char *name = str_get(ary->ary_array[sp+1]);
1646 nent = getnetbyname(name);
1648 else if (which == O_GNBYADDR) {
1649 unsigned long addr = U_L(str_gnum(ary->ary_array[sp+1]));
1650 int addrtype = (int)str_gnum(ary->ary_array[sp+2]);
1652 nent = getnetbyaddr((long)addr,addrtype);
1659 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1660 str_set(str, nent->n_name);
1661 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1662 for (elem = nent->n_aliases; *elem; elem++) {
1663 str_cat(str, *elem);
1665 str_ncat(str," ",1);
1667 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1668 str_numset(str, (double)nent->n_addrtype);
1669 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1670 str_numset(str, (double)nent->n_net);
1674 (void)astore(ary, ++sp, str_mortal(&str_no));
1682 do_gpent(which,gimme,arglast)
1687 register ARRAY *ary = stack;
1688 register int sp = arglast[0];
1689 register char **elem;
1691 struct protoent *getprotobyname();
1692 struct protoent *getprotobynumber();
1693 struct protoent *getprotoent();
1694 struct protoent *pent;
1696 if (gimme != G_ARRAY) {
1697 astore(ary, ++sp, str_mortal(&str_undef));
1701 if (which == O_GPBYNAME) {
1702 char *name = str_get(ary->ary_array[sp+1]);
1704 pent = getprotobyname(name);
1706 else if (which == O_GPBYNUMBER) {
1707 int proto = (int)str_gnum(ary->ary_array[sp+1]);
1709 pent = getprotobynumber(proto);
1712 pent = getprotoent();
1716 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1717 str_set(str, pent->p_name);
1718 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1719 for (elem = pent->p_aliases; *elem; elem++) {
1720 str_cat(str, *elem);
1722 str_ncat(str," ",1);
1724 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1725 str_numset(str, (double)pent->p_proto);
1729 (void)astore(ary, ++sp, str_mortal(&str_no));
1737 do_gsent(which,gimme,arglast)
1742 register ARRAY *ary = stack;
1743 register int sp = arglast[0];
1744 register char **elem;
1746 struct servent *getservbyname();
1747 struct servent *getservbynumber();
1748 struct servent *getservent();
1749 struct servent *sent;
1751 if (gimme != G_ARRAY) {
1752 astore(ary, ++sp, str_mortal(&str_undef));
1756 if (which == O_GSBYNAME) {
1757 char *name = str_get(ary->ary_array[sp+1]);
1758 char *proto = str_get(ary->ary_array[sp+2]);
1760 if (proto && !*proto)
1763 sent = getservbyname(name,proto);
1765 else if (which == O_GSBYPORT) {
1766 int port = (int)str_gnum(ary->ary_array[sp+1]);
1767 char *proto = str_get(ary->ary_array[sp+2]);
1769 sent = getservbyport(port,proto);
1772 sent = getservent();
1775 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1776 str_set(str, sent->s_name);
1777 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1778 for (elem = sent->s_aliases; *elem; elem++) {
1779 str_cat(str, *elem);
1781 str_ncat(str," ",1);
1783 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1785 str_numset(str, (double)ntohs(sent->s_port));
1787 str_numset(str, (double)(sent->s_port));
1789 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1790 str_set(str, sent->s_proto);
1794 (void)astore(ary, ++sp, str_mortal(&str_no));
1801 #endif /* HAS_SOCKET */
1805 do_select(gimme,arglast)
1809 register STR **st = stack->ary_array;
1810 register int sp = arglast[0];
1818 struct timeval timebuf;
1819 struct timeval *tbuf = &timebuf;
1821 #if BYTEORDER != 0x1234 && BYTEORDER != 0x12345678
1827 #if BYTEORDER & 0xf0000
1828 #define ORDERBYTE (0x88888888 - BYTEORDER)
1830 #define ORDERBYTE (0x4444 - BYTEORDER)
1835 for (i = 1; i <= 3; i++) {
1836 j = st[sp+i]->str_cur;
1841 #if BYTEORDER == 0x1234 || BYTEORDER == 0x12345678
1842 growsize = maxlen; /* little endians can use vecs directly */
1850 masksize = NFDBITS / NBBY;
1852 masksize = sizeof(long); /* documented int, everyone seems to use long */
1854 growsize = maxlen + (masksize - (maxlen % masksize));
1855 Zero(&fd_sets[0], 4, char*);
1858 for (i = 1; i <= 3; i++) {
1863 Str_Grow(str,growsize);
1864 s = str_get(str) + j;
1865 while (++j <= growsize) {
1869 else if (str->str_ptr) {
1870 Safefree(str->str_ptr);
1871 str->str_ptr = Nullch;
1874 #if BYTEORDER != 0x1234 && BYTEORDER != 0x12345678
1877 New(403, fd_sets[i], growsize, char);
1878 for (offset = 0; offset < growsize; offset += masksize) {
1879 for (j = 0, k=ORDERBYTE; j < masksize; j++, (k >>= 4))
1880 fd_sets[i][j+offset] = s[(k % masksize) + offset];
1886 if (str->str_nok || str->str_pok) {
1887 value = str_gnum(str);
1890 timebuf.tv_sec = (long)value;
1891 value -= (double)timebuf.tv_sec;
1892 timebuf.tv_usec = (long)(value * 1000000.0);
1895 tbuf = Null(struct timeval*);
1897 #if BYTEORDER == 0x1234 || BYTEORDER == 0x12345678
1911 for (i = 1; i <= 3; i++) {
1915 for (offset = 0; offset < growsize; offset += masksize) {
1916 for (j = 0, k=ORDERBYTE; j < masksize; j++, (k >>= 4))
1917 s[(k % masksize) + offset] = fd_sets[i][j+offset];
1923 st[++sp] = str_mortal(&str_no);
1924 str_numset(st[sp], (double)nfound);
1925 if (gimme == G_ARRAY && tbuf) {
1926 value = (double)(timebuf.tv_sec) +
1927 (double)(timebuf.tv_usec) / 1000000.0;
1928 st[++sp] = str_mortal(&str_no);
1929 str_numset(st[sp], value);
1937 do_spair(stab1, stab2, arglast)
1942 register STR **st = stack->ary_array;
1943 register int sp = arglast[2];
1944 register STIO *stio1;
1945 register STIO *stio2;
1946 int domain, type, protocol, fd[2];
1948 if (!stab1 || !stab2)
1951 stio1 = stab_io(stab1);
1952 stio2 = stab_io(stab2);
1954 stio1 = stab_io(stab1) = stio_new();
1955 else if (stio1->ifp)
1956 do_close(stab1,FALSE);
1958 stio2 = stab_io(stab2) = stio_new();
1959 else if (stio2->ifp)
1960 do_close(stab2,FALSE);
1962 domain = (int)str_gnum(st[++sp]);
1963 type = (int)str_gnum(st[++sp]);
1964 protocol = (int)str_gnum(st[++sp]);
1966 taintproper("Insecure dependency in socketpair");
1968 #ifdef HAS_SOCKETPAIR
1969 if (socketpair(domain,type,protocol,fd) < 0)
1972 fatal("Socketpair unimplemented");
1974 stio1->ifp = fdopen(fd[0], "r");
1975 stio1->ofp = fdopen(fd[0], "w");
1977 stio2->ifp = fdopen(fd[1], "r");
1978 stio2->ofp = fdopen(fd[1], "w");
1980 if (!stio1->ifp || !stio1->ofp || !stio2->ifp || !stio2->ofp) {
1981 if (stio1->ifp) fclose(stio1->ifp);
1982 if (stio1->ofp) fclose(stio1->ofp);
1983 if (!stio1->ifp && !stio1->ofp) close(fd[0]);
1984 if (stio2->ifp) fclose(stio2->ifp);
1985 if (stio2->ofp) fclose(stio2->ofp);
1986 if (!stio2->ifp && !stio2->ofp) close(fd[1]);
1993 #endif /* HAS_SOCKET */
1996 do_gpwent(which,gimme,arglast)
2002 register ARRAY *ary = stack;
2003 register int sp = arglast[0];
2005 struct passwd *getpwnam();
2006 struct passwd *getpwuid();
2007 struct passwd *getpwent();
2008 struct passwd *pwent;
2010 if (gimme != G_ARRAY) {
2011 astore(ary, ++sp, str_mortal(&str_undef));
2015 if (which == O_GPWNAM) {
2016 char *name = str_get(ary->ary_array[sp+1]);
2018 pwent = getpwnam(name);
2020 else if (which == O_GPWUID) {
2021 int uid = (int)str_gnum(ary->ary_array[sp+1]);
2023 pwent = getpwuid(uid);
2029 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2030 str_set(str, pwent->pw_name);
2031 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2032 str_set(str, pwent->pw_passwd);
2033 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2034 str_numset(str, (double)pwent->pw_uid);
2035 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2036 str_numset(str, (double)pwent->pw_gid);
2037 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2039 str_numset(str, (double)pwent->pw_change);
2042 str_numset(str, (double)pwent->pw_quota);
2045 str_set(str, pwent->pw_age);
2049 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2051 str_set(str,pwent->pw_class);
2054 str_set(str, pwent->pw_comment);
2057 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2058 str_set(str, pwent->pw_gecos);
2059 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2060 str_set(str, pwent->pw_dir);
2061 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2062 str_set(str, pwent->pw_shell);
2064 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2065 str_numset(str, (double)pwent->pw_expire);
2071 fatal("password routines not implemented");
2076 do_ggrent(which,gimme,arglast)
2082 register ARRAY *ary = stack;
2083 register int sp = arglast[0];
2084 register char **elem;
2086 struct group *getgrnam();
2087 struct group *getgrgid();
2088 struct group *getgrent();
2089 struct group *grent;
2091 if (gimme != G_ARRAY) {
2092 astore(ary, ++sp, str_mortal(&str_undef));
2096 if (which == O_GGRNAM) {
2097 char *name = str_get(ary->ary_array[sp+1]);
2099 grent = getgrnam(name);
2101 else if (which == O_GGRGID) {
2102 int gid = (int)str_gnum(ary->ary_array[sp+1]);
2104 grent = getgrgid(gid);
2110 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2111 str_set(str, grent->gr_name);
2112 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2113 str_set(str, grent->gr_passwd);
2114 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2115 str_numset(str, (double)grent->gr_gid);
2116 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2117 for (elem = grent->gr_mem; *elem; elem++) {
2118 str_cat(str, *elem);
2120 str_ncat(str," ",1);
2126 fatal("group routines not implemented");
2131 do_dirop(optype,stab,gimme,arglast)
2137 #if defined(DIRENT) && defined(HAS_READDIR)
2138 register ARRAY *ary = stack;
2139 register STR **st = ary->ary_array;
2140 register int sp = arglast[1];
2141 register STIO *stio;
2146 struct DIRENT *readdir();
2147 register struct DIRENT *dp;
2151 if (!(stio = stab_io(stab)))
2152 stio = stab_io(stab) = stio_new();
2153 if (!stio->dirp && optype != O_OPENDIR)
2159 closedir(stio->dirp);
2160 if (!(stio->dirp = opendir(str_get(st[sp+1]))))
2164 if (gimme == G_ARRAY) {
2166 while (dp = readdir(stio->dirp)) {
2168 (void)astore(ary,++sp,
2169 str_2mortal(str_make(dp->d_name,dp->d_namlen)));
2171 (void)astore(ary,++sp,
2172 str_2mortal(str_make(dp->d_name,0)));
2177 if (!(dp = readdir(stio->dirp)))
2179 st[sp] = str_mortal(&str_undef);
2181 str_nset(st[sp], dp->d_name, dp->d_namlen);
2183 str_set(st[sp], dp->d_name);
2193 st[sp] = str_mortal(&str_undef);
2194 str_numset(st[sp], (double)telldir(stio->dirp));
2197 st[sp] = str_mortal(&str_undef);
2198 along = (long)str_gnum(st[sp+1]);
2199 (void)seekdir(stio->dirp,along);
2203 st[sp] = str_mortal(&str_undef);
2204 (void)rewinddir(stio->dirp);
2207 st[sp] = str_mortal(&str_undef);
2208 (void)closedir(stio->dirp);
2215 st[sp] = &str_undef;
2219 fatal("Unimplemented directory operation");
2227 register STR **st = stack->ary_array;
2228 register int sp = arglast[1];
2229 register int items = arglast[2] - sp;
2232 register int tot = 0;
2236 for (st += ++sp; items--; st++)
2237 tainted |= (*st)->str_tainted;
2238 st = stack->ary_array;
2240 items = arglast[2] - sp;
2245 taintproper("Insecure dependency in chmod");
2249 val = (int)str_gnum(st[++sp]);
2251 if (chmod(str_get(st[++sp]),val))
2259 taintproper("Insecure dependency in chown");
2264 val = (int)str_gnum(st[++sp]);
2265 val2 = (int)str_gnum(st[++sp]);
2267 if (chown(str_get(st[++sp]),val,val2))
2276 taintproper("Insecure dependency in kill");
2280 s = str_get(st[++sp]);
2282 if (*s == 'S' && s[1] == 'I' && s[2] == 'G')
2284 if (!(val = whichsig(s)))
2285 fatal("Unrecognized signal name \"%s\"",s);
2288 val = (int)str_gnum(st[sp]);
2292 int proc = (int)str_gnum(st[++sp]);
2294 if (killpg(proc,val)) /* BSD */
2296 if (kill(-proc,val)) /* SYSV */
2303 if (kill((int)(str_gnum(st[++sp])),val))
2312 taintproper("Insecure dependency in unlink");
2316 s = str_get(st[++sp]);
2317 if (euid || unsafe) {
2321 else { /* don't let root wipe out directories without -U */
2323 if (lstat(s,&statbuf) < 0 || S_ISDIR(statbuf.st_mode))
2325 if (stat(s,&statbuf) < 0 || S_ISDIR(statbuf.st_mode))
2337 taintproper("Insecure dependency in utime");
2341 struct utimbuf utbuf;
2349 Zero(&utbuf, sizeof utbuf, char);
2350 utbuf.actime = (long)str_gnum(st[++sp]); /* time accessed */
2351 utbuf.modtime = (long)str_gnum(st[++sp]); /* time modified */
2356 if (utime(str_get(st[++sp]),&utbuf))
2368 /* Do the permissions allow some operation? Assumes statcache already set. */
2371 cando(bit, effective, statbufp)
2374 register struct stat *statbufp;
2377 /* [Comments and code from Len Reed]
2378 * MS-DOS "user" is similar to UNIX's "superuser," but can't write
2379 * to write-protected files. The execute permission bit is set
2380 * by the Miscrosoft C library stat() function for the following:
2385 * All files and directories are readable.
2386 * Directories and special files, e.g. "CON", cannot be
2388 * [Comment by Tom Dinger -- a directory can have the write-protect
2389 * bit set in the file system, but DOS permits changes to
2390 * the directory anyway. In addition, all bets are off
2391 * here for networked software, such as Novell and
2395 return (bit & statbufp->st_mode) ? TRUE : FALSE;
2398 if ((effective ? euid : uid) == 0) { /* root is special */
2399 if (bit == S_IXUSR) {
2400 if (statbufp->st_mode & 0111 || S_ISDIR(statbufp->st_mode))
2404 return TRUE; /* root reads and writes anything */
2407 if (statbufp->st_uid == (effective ? euid : uid) ) {
2408 if (statbufp->st_mode & bit)
2409 return TRUE; /* ok as "user" */
2411 else if (ingroup((int)statbufp->st_gid,effective)) {
2412 if (statbufp->st_mode & bit >> 3)
2413 return TRUE; /* ok as "group" */
2415 else if (statbufp->st_mode & bit >> 6)
2416 return TRUE; /* ok as "other" */
2418 #endif /* ! MSDOS */
2422 ingroup(testgid,effective)
2426 if (testgid == (effective ? egid : gid))
2428 #ifdef HAS_GETGROUPS
2433 GIDTYPE gary[NGROUPS];
2436 anum = getgroups(NGROUPS,gary);
2438 if (gary[anum] == testgid)
2445 #if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)
2448 do_ipcget(optype, arglast)
2452 register STR **st = stack->ary_array;
2453 register int sp = arglast[0];
2457 key = (key_t)str_gnum(st[++sp]);
2458 n = (optype == O_MSGGET) ? 0 : (int)str_gnum(st[++sp]);
2459 flags = (int)str_gnum(st[++sp]);
2465 return msgget(key, flags);
2469 return semget(key, n, flags);
2473 return shmget(key, n, flags);
2475 #if !defined(HAS_MSG) || !defined(HAS_SEM) || !defined(HAS_SHM)
2477 fatal("%s not implemented", opname[optype]);
2480 return -1; /* should never happen */
2484 do_ipcctl(optype, arglast)
2488 register STR **st = stack->ary_array;
2489 register int sp = arglast[0];
2492 int id, n, cmd, infosize, getinfo, ret;
2494 id = (int)str_gnum(st[++sp]);
2495 n = (optype == O_SEMCTL) ? (int)str_gnum(st[++sp]) : 0;
2496 cmd = (int)str_gnum(st[++sp]);
2500 getinfo = (cmd == IPC_STAT);
2506 if (cmd == IPC_STAT || cmd == IPC_SET)
2507 infosize = sizeof(struct msqid_ds);
2512 if (cmd == IPC_STAT || cmd == IPC_SET)
2513 infosize = sizeof(struct shmid_ds);
2518 if (cmd == IPC_STAT || cmd == IPC_SET)
2519 infosize = sizeof(struct semid_ds);
2520 else if (cmd == GETALL || cmd == SETALL)
2522 struct semid_ds semds;
2523 if (semctl(id, 0, IPC_STAT, &semds) == -1)
2525 getinfo = (cmd == GETALL);
2526 #ifdef _POSIX_SOURCE
2527 infosize = semds.sem_nsems * sizeof(ushort_t);
2529 infosize = semds.sem_nsems * sizeof(ushort);
2534 #if !defined(HAS_MSG) || !defined(HAS_SEM) || !defined(HAS_SHM)
2536 fatal("%s not implemented", opname[optype]);
2544 STR_GROW(astr, infosize+1);
2550 if (astr->str_cur != infosize)
2559 int i = (int)str_gnum(astr);
2560 a = (char *)i; /* ouch */
2567 ret = msgctl(id, cmd, a);
2572 ret = semctl(id, n, cmd, a);
2577 ret = shmctl(id, cmd, a);
2581 if (getinfo && ret >= 0) {
2582 astr->str_cur = infosize;
2583 astr->str_ptr[infosize] = '\0';
2593 register STR **st = stack->ary_array;
2594 register int sp = arglast[0];
2597 int id, msize, flags;
2599 id = (int)str_gnum(st[++sp]);
2601 flags = (int)str_gnum(st[++sp]);
2602 mbuf = str_get(mstr);
2603 if ((msize = mstr->str_cur - sizeof(long)) < 0) {
2608 return msgsnd(id, mbuf, msize, flags);
2610 fatal("msgsnd not implemented");
2619 register STR **st = stack->ary_array;
2620 register int sp = arglast[0];
2624 int id, msize, flags, ret;
2626 id = (int)str_gnum(st[++sp]);
2628 msize = (int)str_gnum(st[++sp]);
2629 mtype = (long)str_gnum(st[++sp]);
2630 flags = (int)str_gnum(st[++sp]);
2631 mbuf = str_get(mstr);
2632 if (mstr->str_cur < sizeof(long)+msize+1) {
2633 STR_GROW(mstr, sizeof(long)+msize+1);
2634 mbuf = str_get(mstr);
2637 ret = msgrcv(id, mbuf, msize, mtype, flags);
2639 mstr->str_cur = sizeof(long)+ret;
2640 mstr->str_ptr[sizeof(long)+ret] = '\0';
2644 fatal("msgrcv not implemented");
2653 register STR **st = stack->ary_array;
2654 register int sp = arglast[0];
2659 id = (int)str_gnum(st[++sp]);
2661 opbuf = str_get(opstr);
2662 opsize = opstr->str_cur;
2663 if (opsize < sizeof(struct sembuf)
2664 || (opsize % sizeof(struct sembuf)) != 0) {
2669 return semop(id, opbuf, opsize/sizeof(struct sembuf));
2671 fatal("semop not implemented");
2676 do_shmio(optype, arglast)
2681 register STR **st = stack->ary_array;
2682 register int sp = arglast[0];
2685 int id, mpos, msize;
2686 struct shmid_ds shmds;
2687 extern char *shmat();
2689 id = (int)str_gnum(st[++sp]);
2691 mpos = (int)str_gnum(st[++sp]);
2692 msize = (int)str_gnum(st[++sp]);
2694 if (shmctl(id, IPC_STAT, &shmds) == -1)
2696 if (mpos < 0 || msize < 0 || mpos + msize > shmds.shm_segsz) {
2697 errno = EFAULT; /* can't do as caller requested */
2700 shm = shmat(id, (char *)NULL, (optype == O_SHMREAD) ? SHM_RDONLY : 0);
2701 if (shm == (char *)-1) /* I hate System V IPC, I really do */
2703 mbuf = str_get(mstr);
2704 if (optype == O_SHMREAD) {
2705 if (mstr->str_cur < msize) {
2706 STR_GROW(mstr, msize+1);
2707 mbuf = str_get(mstr);
2709 bcopy(shm + mpos, mbuf, msize);
2710 mstr->str_cur = msize;
2711 mstr->str_ptr[msize] = '\0';
2716 if ((n = mstr->str_cur) > msize)
2718 bcopy(mbuf, shm + mpos, n);
2720 bzero(shm + mpos + n, msize - n);
2724 fatal("shm I/O not implemented");
2728 #endif /* SYSV IPC */