perl 3.0 patch #43 patch #42, continued
[p5sagit/p5-mst-13.2.git] / doio.c
CommitLineData
c623bd54 1/* $Header: doio.c,v 3.0.1.14 91/01/11 17:51:04 lwall Locked $
a687059c 2 *
3 * Copyright (c) 1989, Larry Wall
4 *
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.
7 *
8 * $Log: doio.c,v $
c623bd54 9 * Revision 3.0.1.14 91/01/11 17:51:04 lwall
10 * patch42: ANSIfied the stat mode checking
11 * patch42: the -i switch is now much more robust and informative
12 * patch42: close on a pipe didn't return failure correctly
13 * patch42: stat on temp values could wipe them out prematurely, i.e. grep(-d,<*>)
14 * patch42: -l didn't work right with _
15 *
57ebbfd0 16 * Revision 3.0.1.13 90/11/10 01:17:37 lwall
17 * patch38: -e _ was wrong if last stat failed
18 * patch38: more msdos/os2 upgrades
19 *
e5d73d77 20 * Revision 3.0.1.12 90/10/20 02:04:18 lwall
21 * patch37: split out separate Sys V IPC features
22 *
c2ab57d4 23 * Revision 3.0.1.11 90/10/15 16:16:11 lwall
24 * patch29: added SysV IPC
25 * patch29: file - didn't auto-close cleanly
26 * patch29: close; core dumped
27 * patch29: more MSDOS and OS/2 updates, from Kai Uwe Rommel
28 * patch29: various portability fixes
29 * patch29: *foo now prints as *package'foo
30 *
6eb13c3b 31 * Revision 3.0.1.10 90/08/13 22:14:29 lwall
32 * patch28: close-on-exec problems on dup'ed file descriptors
33 * patch28: F_FREESP wasn't implemented the way I thought
34 *
ff8e2863 35 * Revision 3.0.1.9 90/08/09 02:56:19 lwall
36 * patch19: various MSDOS and OS/2 patches folded in
37 * patch19: prints now check error status better
38 * patch19: printing a list with null elements only printed front of list
39 * patch19: on machines with vfork child would allocate memory in parent
40 * patch19: getsockname and getpeername gave bogus warning on error
41 * patch19: MACH doesn't have seekdir or telldir
42 *
b1248f16 43 * Revision 3.0.1.8 90/03/27 15:44:02 lwall
44 * patch16: MSDOS support
45 * patch16: support for machines that can't cast negative floats to unsigned ints
46 * patch16: system() can lose arguments passed to shell scripts on SysV machines
47 *
63f2c1e1 48 * Revision 3.0.1.7 90/03/14 12:26:24 lwall
49 * patch15: commands involving execs could cause malloc arena corruption
50 *
ff2452de 51 * Revision 3.0.1.6 90/03/12 16:30:07 lwall
52 * patch13: system 'FOO=bar command' didn't invoke sh as it should
53 *
afd9f252 54 * Revision 3.0.1.5 90/02/28 17:01:36 lwall
55 * patch9: open(FOO,"$filename\0") will now protect trailing spaces in filename
56 * patch9: removed obsolete checks to avoid opening block devices
57 * patch9: removed references to acusec and modusec that some utime.h's have
58 * patch9: added pipe function
59 *
663a0e37 60 * Revision 3.0.1.4 89/12/21 19:55:10 lwall
61 * patch7: select now works on big-endian machines
62 * patch7: errno may now be a macro with an lvalue
63 * patch7: ANSI strerror() is now supported
64 * patch7: Configure now detects DG/UX thingies like [sg]etpgrp2 and utime.h
65 *
0d3e774c 66 * Revision 3.0.1.3 89/11/17 15:13:06 lwall
67 * patch5: some systems have symlink() but not lstat()
68 * patch5: some systems have dirent.h but not readdir()
69 *
bf38876a 70 * Revision 3.0.1.2 89/11/11 04:25:51 lwall
71 * patch2: orthogonalized the file modes some so we can have <& +<& etc.
72 * patch2: do_open() now detects sockets passed to process from parent
73 * patch2: fd's above 2 are now closed on exec
74 * patch2: csh code can now use csh from other than /bin
75 * patch2: getsockopt, get{sock,peer}name didn't define result properly
76 * patch2: warn("shutdown") was replicated
77 * patch2: gethostbyname was misdeclared
78 * patch2: telldir() is sometimes a macro
79 *
03a14243 80 * Revision 3.0.1.1 89/10/26 23:10:05 lwall
81 * patch1: Configure now checks for BSD shadow passwords
82 *
a687059c 83 * Revision 3.0 89/10/18 15:10:54 lwall
84 * 3.0 baseline
85 *
86 */
87
88#include "EXTERN.h"
89#include "perl.h"
90
91#ifdef SOCKET
92#include <sys/socket.h>
93#include <netdb.h>
94#endif
95
6eb13c3b 96#if defined(SELECT) && (defined(M_UNIX) || defined(M_XENIX))
97#include <sys/select.h>
98#endif
99
c2ab57d4 100#ifdef SYSVIPC
101#include <sys/ipc.h>
e5d73d77 102#ifdef IPCMSG
c2ab57d4 103#include <sys/msg.h>
e5d73d77 104#endif
105#ifdef IPCSEM
c2ab57d4 106#include <sys/sem.h>
e5d73d77 107#endif
108#ifdef IPCSHM
c2ab57d4 109#include <sys/shm.h>
110#endif
e5d73d77 111#endif
c2ab57d4 112
a687059c 113#ifdef I_PWD
114#include <pwd.h>
115#endif
116#ifdef I_GRP
117#include <grp.h>
118#endif
663a0e37 119#ifdef I_UTIME
120#include <utime.h>
121#endif
ff8e2863 122#ifdef I_FCNTL
123#include <fcntl.h>
124#endif
a687059c 125
57ebbfd0 126int laststatval = -1;
127
a687059c 128bool
afd9f252 129do_open(stab,name,len)
a687059c 130STAB *stab;
131register char *name;
afd9f252 132int len;
a687059c 133{
134 FILE *fp;
a687059c 135 register STIO *stio = stab_io(stab);
136 char *myname = savestr(name);
137 int result;
138 int fd;
139 int writing = 0;
140 char mode[3]; /* stdio file mode ("r\0" or "r+\0") */
141
142 name = myname;
143 forkprocess = 1; /* assume true if no fork */
144 while (len && isspace(name[len-1]))
145 name[--len] = '\0';
146 if (!stio)
147 stio = stab_io(stab) = stio_new();
148 else if (stio->ifp) {
149 fd = fileno(stio->ifp);
150 if (stio->type == '|')
151 result = mypclose(stio->ifp);
c2ab57d4 152 else if (stio->type == '-')
153 result = 0;
a687059c 154 else if (stio->ifp != stio->ofp) {
c2ab57d4 155 if (stio->ofp) {
156 result = fclose(stio->ofp);
157 fclose(stio->ifp); /* clear stdio, fd already closed */
158 }
159 else
160 result = fclose(stio->ifp);
a687059c 161 }
a687059c 162 else
c2ab57d4 163 result = fclose(stio->ifp);
a687059c 164 if (result == EOF && fd > 2)
165 fprintf(stderr,"Warning: unable to close filehandle %s properly.\n",
166 stab_name(stab));
167 stio->ofp = stio->ifp = Nullfp;
168 }
169 if (*name == '+' && len > 1 && name[len-1] != '|') { /* scary */
170 mode[1] = *name++;
171 mode[2] = '\0';
172 --len;
173 writing = 1;
174 }
175 else {
176 mode[1] = '\0';
177 }
178 stio->type = *name;
179 if (*name == '|') {
180 for (name++; isspace(*name); name++) ;
181#ifdef TAINT
182 taintenv();
183 taintproper("Insecure dependency in piped open");
184#endif
185 fp = mypopen(name,"w");
186 writing = 1;
187 }
a687059c 188 else if (*name == '>') {
189#ifdef TAINT
190 taintproper("Insecure dependency in open");
191#endif
bf38876a 192 name++;
193 if (*name == '>') {
194 mode[0] = stio->type = 'a';
195 name++;
a687059c 196 }
bf38876a 197 else
a687059c 198 mode[0] = 'w';
a687059c 199 writing = 1;
bf38876a 200 if (*name == '&') {
201 duplicity:
202 name++;
203 while (isspace(*name))
204 name++;
205 if (isdigit(*name))
206 fd = atoi(name);
207 else {
208 stab = stabent(name,FALSE);
209 if (!stab || !stab_io(stab))
210 return FALSE;
211 if (stab_io(stab) && stab_io(stab)->ifp) {
212 fd = fileno(stab_io(stab)->ifp);
213 if (stab_io(stab)->type == 's')
214 stio->type = 's';
215 }
216 else
217 fd = -1;
218 }
219 fp = fdopen(dup(fd),mode);
220 }
221 else {
222 while (isspace(*name))
223 name++;
224 if (strEQ(name,"-")) {
225 fp = stdout;
226 stio->type = '-';
227 }
228 else {
229 fp = fopen(name,mode);
230 }
231 }
a687059c 232 }
233 else {
234 if (*name == '<') {
bf38876a 235 mode[0] = 'r';
236 name++;
237 while (isspace(*name))
238 name++;
239 if (*name == '&')
240 goto duplicity;
a687059c 241 if (strEQ(name,"-")) {
242 fp = stdin;
243 stio->type = '-';
244 }
bf38876a 245 else
a687059c 246 fp = fopen(name,mode);
a687059c 247 }
248 else if (name[len-1] == '|') {
249#ifdef TAINT
250 taintenv();
251 taintproper("Insecure dependency in piped open");
252#endif
253 name[--len] = '\0';
254 while (len && isspace(name[len-1]))
255 name[--len] = '\0';
256 for (; isspace(*name); name++) ;
257 fp = mypopen(name,"r");
258 stio->type = '|';
259 }
260 else {
261 stio->type = '<';
262 for (; isspace(*name); name++) ;
263 if (strEQ(name,"-")) {
264 fp = stdin;
265 stio->type = '-';
266 }
267 else
268 fp = fopen(name,"r");
269 }
270 }
271 Safefree(myname);
272 if (!fp)
273 return FALSE;
274 if (stio->type &&
275 stio->type != '|' && stio->type != '-') {
276 if (fstat(fileno(fp),&statbuf) < 0) {
277 (void)fclose(fp);
278 return FALSE;
279 }
c623bd54 280 if (S_ISSOCK(statbuf.st_mode))
bf38876a 281 stio->type = 's'; /* in case a socket was passed in to us */
c623bd54 282#ifdef S_IFMT
283 else if (!(statbuf.st_mode & S_IFMT))
284 stio->type = 's'; /* some OS's return 0 on fstat()ed socket */
bf38876a 285#endif
a687059c 286 }
bf38876a 287#if defined(FCNTL) && defined(F_SETFD)
288 fd = fileno(fp);
6eb13c3b 289 fcntl(fd,F_SETFD,fd >= 3);
bf38876a 290#endif
a687059c 291 stio->ifp = fp;
bf38876a 292 if (writing) {
293 if (stio->type != 's')
294 stio->ofp = fp;
295 else
296 stio->ofp = fdopen(fileno(fp),"w");
297 }
a687059c 298 return TRUE;
299}
300
301FILE *
302nextargv(stab)
303register STAB *stab;
304{
305 register STR *str;
306 char *oldname;
c623bd54 307 int filedev;
308 int fileino;
309 int filemode;
310 int fileuid;
311 int filegid;
a687059c 312
313 while (alen(stab_xarray(stab)) >= 0) {
314 str = ashift(stab_xarray(stab));
315 str_sset(stab_val(stab),str);
316 STABSET(stab_val(stab));
317 oldname = str_get(stab_val(stab));
afd9f252 318 if (do_open(stab,oldname,stab_val(stab)->str_cur)) {
a687059c 319 if (inplace) {
320#ifdef TAINT
321 taintproper("Insecure dependency in inplace open");
322#endif
c623bd54 323 if (strEQ(oldname,"-")) {
324 str_free(str);
325 defoutstab = stabent("STDOUT",TRUE);
326 return stab_io(stab)->ifp;
327 }
328 filedev = statbuf.st_dev;
329 fileino = statbuf.st_ino;
a687059c 330 filemode = statbuf.st_mode;
331 fileuid = statbuf.st_uid;
332 filegid = statbuf.st_gid;
c623bd54 333 if (!S_ISREG(filemode)) {
334 warn("Can't do inplace edit: %s is not a regular file",
335 oldname );
336 do_close(stab,FALSE);
337 str_free(str);
338 continue;
339 }
a687059c 340 if (*inplace) {
ff8e2863 341#ifdef SUFFIX
342 add_suffix(str,inplace);
343#else
a687059c 344 str_cat(str,inplace);
ff8e2863 345#endif
c623bd54 346#ifndef FLEXFILENAMES
347 if (stat(str->str_ptr,&statbuf) >= 0
348 && statbuf.st_dev == filedev
349 && statbuf.st_ino == fileino ) {
350 warn("Can't do inplace edit: %s > 14 characters",
351 str->str_ptr );
352 do_close(stab,FALSE);
353 str_free(str);
354 continue;
355 }
356#endif
a687059c 357#ifdef RENAME
ff8e2863 358#ifndef MSDOS
c623bd54 359 if (rename(oldname,str->str_ptr) < 0) {
360 warn("Can't rename %s to %s: %s, skipping file",
361 oldname, str->str_ptr, strerror(errno) );
362 do_close(stab,FALSE);
363 str_free(str);
364 continue;
365 }
a687059c 366#else
ff8e2863 367 do_close(stab,FALSE);
368 (void)unlink(str->str_ptr);
369 (void)rename(oldname,str->str_ptr);
370 do_open(stab,str->str_ptr,stab_val(stab)->str_cur);
371#endif /* MSDOS */
372#else
a687059c 373 (void)UNLINK(str->str_ptr);
c623bd54 374 if (link(oldname,str->str_ptr) < 0) {
375 warn("Can't rename %s to %s: %s, skipping file",
376 oldname, str->str_ptr, strerror(errno) );
377 do_close(stab,FALSE);
378 str_free(str);
379 continue;
380 }
a687059c 381 (void)UNLINK(oldname);
382#endif
383 }
384 else {
ff8e2863 385#ifndef MSDOS
a687059c 386 (void)UNLINK(oldname);
ff8e2863 387#else
388 fatal("Can't do inplace edit without backup");
389#endif
a687059c 390 }
391
392 str_nset(str,">",1);
393 str_cat(str,oldname);
394 errno = 0; /* in case sprintf set errno */
afd9f252 395 if (!do_open(argvoutstab,str->str_ptr,str->str_cur))
c623bd54 396 warn("Can't do inplace edit on %s: %s",
397 oldname, strerror(errno) );
a687059c 398 defoutstab = argvoutstab;
399#ifdef FCHMOD
400 (void)fchmod(fileno(stab_io(argvoutstab)->ifp),filemode);
401#else
402 (void)chmod(oldname,filemode);
403#endif
404#ifdef FCHOWN
405 (void)fchown(fileno(stab_io(argvoutstab)->ifp),fileuid,filegid);
406#else
b1248f16 407#ifdef CHOWN
a687059c 408 (void)chown(oldname,fileuid,filegid);
409#endif
b1248f16 410#endif
a687059c 411 }
412 str_free(str);
413 return stab_io(stab)->ifp;
414 }
415 else
c623bd54 416 fprintf(stderr,"Can't open %s: %s\n",str_get(str), strerror(errno));
a687059c 417 str_free(str);
418 }
419 if (inplace) {
420 (void)do_close(argvoutstab,FALSE);
421 defoutstab = stabent("STDOUT",TRUE);
422 }
423 return Nullfp;
424}
425
b1248f16 426#ifdef PIPE
afd9f252 427void
428do_pipe(str, rstab, wstab)
429STR *str;
430STAB *rstab;
431STAB *wstab;
432{
433 register STIO *rstio;
434 register STIO *wstio;
435 int fd[2];
436
437 if (!rstab)
438 goto badexit;
439 if (!wstab)
440 goto badexit;
441
442 rstio = stab_io(rstab);
443 wstio = stab_io(wstab);
444
445 if (!rstio)
446 rstio = stab_io(rstab) = stio_new();
447 else if (rstio->ifp)
448 do_close(rstab,FALSE);
449 if (!wstio)
450 wstio = stab_io(wstab) = stio_new();
451 else if (wstio->ifp)
452 do_close(wstab,FALSE);
453
454 if (pipe(fd) < 0)
455 goto badexit;
456 rstio->ifp = fdopen(fd[0], "r");
457 wstio->ofp = fdopen(fd[1], "w");
458 wstio->ifp = wstio->ofp;
459 rstio->type = '<';
460 wstio->type = '>';
461
462 str_sset(str,&str_yes);
463 return;
464
465badexit:
466 str_sset(str,&str_undef);
467 return;
468}
b1248f16 469#endif
afd9f252 470
a687059c 471bool
472do_close(stab,explicit)
473STAB *stab;
474bool explicit;
475{
476 bool retval = FALSE;
c2ab57d4 477 register STIO *stio;
a687059c 478 int status;
479
c2ab57d4 480 if (!stab)
481 stab = argvstab;
482 if (!stab)
483 return FALSE;
484 stio = stab_io(stab);
a687059c 485 if (!stio) { /* never opened */
486 if (dowarn && explicit)
487 warn("Close on unopened file <%s>",stab_name(stab));
488 return FALSE;
489 }
490 if (stio->ifp) {
491 if (stio->type == '|') {
492 status = mypclose(stio->ifp);
c623bd54 493 retval = (status == 0);
b1248f16 494 statusvalue = (unsigned short)status & 0xffff;
a687059c 495 }
496 else if (stio->type == '-')
497 retval = TRUE;
498 else {
c2ab57d4 499 if (stio->ofp && stio->ofp != stio->ifp) { /* a socket */
500 retval = (fclose(stio->ofp) != EOF);
501 fclose(stio->ifp); /* clear stdio, fd already closed */
502 }
503 else
504 retval = (fclose(stio->ifp) != EOF);
a687059c 505 }
506 stio->ofp = stio->ifp = Nullfp;
507 }
508 if (explicit)
509 stio->lines = 0;
510 stio->type = ' ';
511 return retval;
512}
513
514bool
515do_eof(stab)
516STAB *stab;
517{
518 register STIO *stio;
519 int ch;
520
521 if (!stab) { /* eof() */
522 if (argvstab)
523 stio = stab_io(argvstab);
524 else
525 return TRUE;
526 }
527 else
528 stio = stab_io(stab);
529
530 if (!stio)
531 return TRUE;
532
533 while (stio->ifp) {
534
535#ifdef STDSTDIO /* (the code works without this) */
536 if (stio->ifp->_cnt > 0) /* cheat a little, since */
537 return FALSE; /* this is the most usual case */
538#endif
539
540 ch = getc(stio->ifp);
541 if (ch != EOF) {
542 (void)ungetc(ch, stio->ifp);
543 return FALSE;
544 }
545 if (!stab) { /* not necessarily a real EOF yet? */
546 if (!nextargv(argvstab)) /* get another fp handy */
547 return TRUE;
548 }
549 else
550 return TRUE; /* normal fp, definitely end of file */
551 }
552 return TRUE;
553}
554
555long
556do_tell(stab)
557STAB *stab;
558{
559 register STIO *stio;
560
561 if (!stab)
562 goto phooey;
563
564 stio = stab_io(stab);
565 if (!stio || !stio->ifp)
566 goto phooey;
567
568 if (feof(stio->ifp))
569 (void)fseek (stio->ifp, 0L, 2); /* ultrix 1.2 workaround */
570
571 return ftell(stio->ifp);
572
573phooey:
574 if (dowarn)
575 warn("tell() on unopened file");
576 return -1L;
577}
578
579bool
580do_seek(stab, pos, whence)
581STAB *stab;
582long pos;
583int whence;
584{
585 register STIO *stio;
586
587 if (!stab)
588 goto nuts;
589
590 stio = stab_io(stab);
591 if (!stio || !stio->ifp)
592 goto nuts;
593
594 if (feof(stio->ifp))
595 (void)fseek (stio->ifp, 0L, 2); /* ultrix 1.2 workaround */
596
597 return fseek(stio->ifp, pos, whence) >= 0;
598
599nuts:
600 if (dowarn)
601 warn("seek() on unopened file");
602 return FALSE;
603}
604
605int
606do_ctl(optype,stab,func,argstr)
607int optype;
608STAB *stab;
609int func;
610STR *argstr;
611{
612 register STIO *stio;
613 register char *s;
614 int retval;
615
616 if (!stab || !argstr)
617 return -1;
618 stio = stab_io(stab);
619 if (!stio)
620 return -1;
621
622 if (argstr->str_pok || !argstr->str_nok) {
623 if (!argstr->str_pok)
624 s = str_get(argstr);
625
626#ifdef IOCPARM_MASK
627#ifndef IOCPARM_LEN
628#define IOCPARM_LEN(x) (((x) >> 16) & IOCPARM_MASK)
629#endif
630#endif
631#ifdef IOCPARM_LEN
632 retval = IOCPARM_LEN(func); /* on BSDish systes we're safe */
633#else
634 retval = 256; /* otherwise guess at what's safe */
635#endif
636 if (argstr->str_cur < retval) {
ff8e2863 637 Str_Grow(argstr,retval+1);
a687059c 638 argstr->str_cur = retval;
639 }
640
641 s = argstr->str_ptr;
642 s[argstr->str_cur] = 17; /* a little sanity check here */
643 }
644 else {
645 retval = (int)str_gnum(argstr);
c2ab57d4 646#ifdef MSDOS
647 s = (char*)(long)retval; /* ouch */
648#else
a687059c 649 s = (char*)retval; /* ouch */
c2ab57d4 650#endif
a687059c 651 }
652
653#ifndef lint
654 if (optype == O_IOCTL)
655 retval = ioctl(fileno(stio->ifp), func, s);
656 else
57ebbfd0 657#ifdef MSDOS
658 fatal("fcntl is not implemented");
659#else
a687059c 660#ifdef I_FCNTL
661 retval = fcntl(fileno(stio->ifp), func, s);
662#else
663 fatal("fcntl is not implemented");
664#endif
57ebbfd0 665#endif
a687059c 666#else /* lint */
667 retval = 0;
668#endif /* lint */
669
670 if (argstr->str_pok) {
671 if (s[argstr->str_cur] != 17)
672 fatal("Return value overflowed string");
673 s[argstr->str_cur] = 0; /* put our null back */
674 }
675 return retval;
676}
677
678int
679do_stat(str,arg,gimme,arglast)
680STR *str;
681register ARG *arg;
682int gimme;
683int *arglast;
684{
685 register ARRAY *ary = stack;
686 register int sp = arglast[0] + 1;
687 int max = 13;
a687059c 688
689 if ((arg[1].arg_type & A_MASK) == A_WORD) {
690 tmpstab = arg[1].arg_ptr.arg_stab;
691 if (tmpstab != defstab) {
692 statstab = tmpstab;
693 str_set(statname,"");
c2ab57d4 694 if (!stab_io(tmpstab) || !stab_io(tmpstab)->ifp ||
a687059c 695 fstat(fileno(stab_io(tmpstab)->ifp),&statcache) < 0) {
696 max = 0;
57ebbfd0 697 laststatval = -1;
a687059c 698 }
699 }
57ebbfd0 700 else if (laststatval < 0)
701 max = 0;
a687059c 702 }
703 else {
c623bd54 704 str_set(statname,str_get(ary->ary_array[sp]));
a687059c 705 statstab = Nullstab;
0d3e774c 706#ifdef LSTAT
a687059c 707 if (arg->arg_type == O_LSTAT)
57ebbfd0 708 laststatval = lstat(str_get(statname),&statcache);
a687059c 709 else
710#endif
57ebbfd0 711 laststatval = stat(str_get(statname),&statcache);
712 if (laststatval < 0)
a687059c 713 max = 0;
714 }
715
716 if (gimme != G_ARRAY) {
717 if (max)
718 str_sset(str,&str_yes);
719 else
720 str_sset(str,&str_undef);
721 STABSET(str);
722 ary->ary_array[sp] = str;
723 return sp;
724 }
725 sp--;
726 if (max) {
727#ifndef lint
728 (void)astore(ary,++sp,
729 str_2static(str_nmake((double)statcache.st_dev)));
730 (void)astore(ary,++sp,
731 str_2static(str_nmake((double)statcache.st_ino)));
732 (void)astore(ary,++sp,
733 str_2static(str_nmake((double)statcache.st_mode)));
734 (void)astore(ary,++sp,
735 str_2static(str_nmake((double)statcache.st_nlink)));
736 (void)astore(ary,++sp,
737 str_2static(str_nmake((double)statcache.st_uid)));
738 (void)astore(ary,++sp,
739 str_2static(str_nmake((double)statcache.st_gid)));
740 (void)astore(ary,++sp,
741 str_2static(str_nmake((double)statcache.st_rdev)));
742 (void)astore(ary,++sp,
743 str_2static(str_nmake((double)statcache.st_size)));
744 (void)astore(ary,++sp,
745 str_2static(str_nmake((double)statcache.st_atime)));
746 (void)astore(ary,++sp,
747 str_2static(str_nmake((double)statcache.st_mtime)));
748 (void)astore(ary,++sp,
749 str_2static(str_nmake((double)statcache.st_ctime)));
750#ifdef STATBLOCKS
751 (void)astore(ary,++sp,
752 str_2static(str_nmake((double)statcache.st_blksize)));
753 (void)astore(ary,++sp,
754 str_2static(str_nmake((double)statcache.st_blocks)));
755#else
756 (void)astore(ary,++sp,
757 str_2static(str_make("",0)));
758 (void)astore(ary,++sp,
759 str_2static(str_make("",0)));
760#endif
761#else /* lint */
762 (void)astore(ary,++sp,str_nmake(0.0));
763#endif /* lint */
764 }
765 return sp;
766}
767
6eb13c3b 768#if !defined(TRUNCATE) && !defined(CHSIZE) && defined(F_FREESP)
c2ab57d4 769 /* code courtesy of William Kucharski */
6eb13c3b 770#define CHSIZE
771
772int chsize(fd, length)
773int fd; /* file descriptor */
774off_t length; /* length to set file to */
775{
776 extern long lseek();
777 struct flock fl;
778 struct stat filebuf;
779
780 if (fstat(fd, &filebuf) < 0)
781 return -1;
782
783 if (filebuf.st_size < length) {
784
785 /* extend file length */
786
787 if ((lseek(fd, (length - 1), 0)) < 0)
788 return -1;
789
790 /* write a "0" byte */
791
792 if ((write(fd, "", 1)) != 1)
793 return -1;
794 }
795 else {
796 /* truncate length */
797
798 fl.l_whence = 0;
799 fl.l_len = 0;
800 fl.l_start = length;
801 fl.l_type = F_WRLCK; /* write lock on file space */
802
803 /*
804 * This relies on the UNDOCUMENTED F_FREESP argument to
805 * fcntl(2), which truncates the file so that it ends at the
806 * position indicated by fl.l_start.
807 *
808 * Will minor miracles never cease?
809 */
810
811 if (fcntl(fd, F_FREESP, &fl) < 0)
812 return -1;
813
814 }
815
816 return 0;
817}
818#endif /* F_FREESP */
819
a687059c 820int
ff8e2863 821do_truncate(str,arg,gimme,arglast)
822STR *str;
823register ARG *arg;
824int gimme;
825int *arglast;
826{
827 register ARRAY *ary = stack;
828 register int sp = arglast[0] + 1;
829 off_t len = (off_t)str_gnum(ary->ary_array[sp+1]);
830 int result = 1;
831 STAB *tmpstab;
832
6eb13c3b 833#if defined(TRUNCATE) || defined(CHSIZE)
ff8e2863 834#ifdef TRUNCATE
835 if ((arg[1].arg_type & A_MASK) == A_WORD) {
836 tmpstab = arg[1].arg_ptr.arg_stab;
837 if (!stab_io(tmpstab) ||
838 ftruncate(fileno(stab_io(tmpstab)->ifp), len) < 0)
839 result = 0;
840 }
841 else if (truncate(str_get(ary->ary_array[sp]), len) < 0)
842 result = 0;
843#else
ff8e2863 844 if ((arg[1].arg_type & A_MASK) == A_WORD) {
845 tmpstab = arg[1].arg_ptr.arg_stab;
846 if (!stab_io(tmpstab) ||
847 chsize(fileno(stab_io(tmpstab)->ifp), len) < 0)
848 result = 0;
849 }
850 else {
851 int tmpfd;
852
853 if ((tmpfd = open(str_get(ary->ary_array[sp]), 0)) < 0)
854 result = 0;
855 else {
856 if (chsize(tmpfd, len) < 0)
857 result = 0;
858 close(tmpfd);
859 }
860 }
861#endif
862
863 if (result)
864 str_sset(str,&str_yes);
865 else
866 str_sset(str,&str_undef);
867 STABSET(str);
868 ary->ary_array[sp] = str;
869 return sp;
870#else
871 fatal("truncate not implemented");
872#endif
873}
874
875int
a687059c 876looks_like_number(str)
877STR *str;
878{
879 register char *s;
880 register char *send;
881
882 if (!str->str_pok)
883 return TRUE;
884 s = str->str_ptr;
885 send = s + str->str_cur;
886 while (isspace(*s))
887 s++;
888 if (s >= send)
889 return FALSE;
890 if (*s == '+' || *s == '-')
891 s++;
892 while (isdigit(*s))
893 s++;
894 if (s == send)
895 return TRUE;
896 if (*s == '.')
897 s++;
898 else if (s == str->str_ptr)
899 return FALSE;
900 while (isdigit(*s))
901 s++;
902 if (s == send)
903 return TRUE;
904 if (*s == 'e' || *s == 'E') {
905 s++;
906 if (*s == '+' || *s == '-')
907 s++;
908 while (isdigit(*s))
909 s++;
910 }
911 while (isspace(*s))
912 s++;
913 if (s >= send)
914 return TRUE;
915 return FALSE;
916}
917
918bool
919do_print(str,fp)
920register STR *str;
921FILE *fp;
922{
923 register char *tmps;
924
925 if (!fp) {
926 if (dowarn)
927 warn("print to unopened file");
928 return FALSE;
929 }
930 if (!str)
ff8e2863 931 return TRUE;
a687059c 932 if (ofmt &&
933 ((str->str_nok && str->str_u.str_nval != 0.0)
ff8e2863 934 || (looks_like_number(str) && str_gnum(str) != 0.0) ) ) {
a687059c 935 fprintf(fp, ofmt, str->str_u.str_nval);
ff8e2863 936 return !ferror(fp);
937 }
a687059c 938 else {
939 tmps = str_get(str);
c2ab57d4 940 if (*tmps == 'S' && tmps[1] == 't' && tmps[2] == 'B' && tmps[3] == '\0'
a687059c 941 && str->str_cur == sizeof(STBP) && strlen(tmps) < str->str_cur) {
c2ab57d4 942 STR *tmpstr = str_static(&str_undef);
943 stab_fullname(tmpstr,((STAB*)str));/* a stab value, be nice */
944 str = tmpstr;
945 tmps = str->str_ptr;
a687059c 946 putc('*',fp);
947 }
ff8e2863 948 if (str->str_cur && (fwrite(tmps,1,str->str_cur,fp) == 0 || ferror(fp)))
a687059c 949 return FALSE;
950 }
951 return TRUE;
952}
953
954bool
955do_aprint(arg,fp,arglast)
956register ARG *arg;
957register FILE *fp;
958int *arglast;
959{
960 register STR **st = stack->ary_array;
961 register int sp = arglast[1];
962 register int retval;
963 register int items = arglast[2] - sp;
964
965 if (!fp) {
966 if (dowarn)
967 warn("print to unopened file");
968 return FALSE;
969 }
970 st += ++sp;
971 if (arg->arg_type == O_PRTF) {
972 do_sprintf(arg->arg_ptr.arg_str,items,st);
973 retval = do_print(arg->arg_ptr.arg_str,fp);
974 }
975 else {
976 retval = (items <= 0);
977 for (; items > 0; items--,st++) {
978 if (retval && ofslen) {
ff8e2863 979 if (fwrite(ofs, 1, ofslen, fp) == 0 || ferror(fp)) {
a687059c 980 retval = FALSE;
981 break;
982 }
983 }
984 if (!(retval = do_print(*st, fp)))
985 break;
986 }
987 if (retval && orslen)
ff8e2863 988 if (fwrite(ors, 1, orslen, fp) == 0 || ferror(fp))
a687059c 989 retval = FALSE;
990 }
991 return retval;
992}
993
994int
995mystat(arg,str)
996ARG *arg;
997STR *str;
998{
999 STIO *stio;
1000
1001 if (arg[1].arg_type & A_DONT) {
1002 stio = stab_io(arg[1].arg_ptr.arg_stab);
1003 if (stio && stio->ifp) {
1004 statstab = arg[1].arg_ptr.arg_stab;
1005 str_set(statname,"");
57ebbfd0 1006 return (laststatval = fstat(fileno(stio->ifp), &statcache));
a687059c 1007 }
1008 else {
1009 if (arg[1].arg_ptr.arg_stab == defstab)
57ebbfd0 1010 return laststatval;
a687059c 1011 if (dowarn)
1012 warn("Stat on unopened file <%s>",
1013 stab_name(arg[1].arg_ptr.arg_stab));
1014 statstab = Nullstab;
1015 str_set(statname,"");
57ebbfd0 1016 return (laststatval = -1);
a687059c 1017 }
1018 }
1019 else {
1020 statstab = Nullstab;
c623bd54 1021 str_set(statname,str_get(str));
57ebbfd0 1022 return (laststatval = stat(str_get(str),&statcache));
a687059c 1023 }
1024}
1025
c623bd54 1026int
1027mylstat(arg,str)
1028ARG *arg;
1029STR *str;
1030{
1031 if (arg[1].arg_type & A_DONT)
1032 fatal("You must supply explicit filename with -l");
1033
1034 statstab = Nullstab;
1035 str_set(statname,str_get(str));
1036#ifdef LSTAT
1037 return (laststatval = lstat(str_get(str),&statcache));
1038#else
1039 return (laststatval = stat(str_get(str),&statcache));
1040#endif
1041}
1042
a687059c 1043STR *
1044do_fttext(arg,str)
1045register ARG *arg;
1046STR *str;
1047{
1048 int i;
1049 int len;
1050 int odd = 0;
1051 STDCHAR tbuf[512];
1052 register STDCHAR *s;
1053 register STIO *stio;
1054
1055 if (arg[1].arg_type & A_DONT) {
1056 if (arg[1].arg_ptr.arg_stab == defstab) {
1057 if (statstab)
1058 stio = stab_io(statstab);
1059 else {
1060 str = statname;
1061 goto really_filename;
1062 }
1063 }
1064 else {
1065 statstab = arg[1].arg_ptr.arg_stab;
1066 str_set(statname,"");
1067 stio = stab_io(statstab);
1068 }
1069 if (stio && stio->ifp) {
1070#ifdef STDSTDIO
1071 fstat(fileno(stio->ifp),&statcache);
1072 if (stio->ifp->_cnt <= 0) {
1073 i = getc(stio->ifp);
1074 if (i != EOF)
1075 (void)ungetc(i,stio->ifp);
1076 }
1077 if (stio->ifp->_cnt <= 0) /* null file is anything */
1078 return &str_yes;
1079 len = stio->ifp->_cnt + (stio->ifp->_ptr - stio->ifp->_base);
1080 s = stio->ifp->_base;
1081#else
1082 fatal("-T and -B not implemented on filehandles\n");
1083#endif
1084 }
1085 else {
1086 if (dowarn)
1087 warn("Test on unopened file <%s>",
1088 stab_name(arg[1].arg_ptr.arg_stab));
1089 return &str_undef;
1090 }
1091 }
1092 else {
1093 statstab = Nullstab;
c623bd54 1094 str_set(statname,str_get(str));
a687059c 1095 really_filename:
1096 i = open(str_get(str),0);
1097 if (i < 0)
1098 return &str_undef;
1099 fstat(i,&statcache);
1100 len = read(i,tbuf,512);
1101 if (len <= 0) /* null file is anything */
1102 return &str_yes;
1103 (void)close(i);
1104 s = tbuf;
1105 }
1106
1107 /* now scan s to look for textiness */
1108
1109 for (i = 0; i < len; i++,s++) {
1110 if (!*s) { /* null never allowed in text */
1111 odd += len;
1112 break;
1113 }
1114 else if (*s & 128)
1115 odd++;
1116 else if (*s < 32 &&
1117 *s != '\n' && *s != '\r' && *s != '\b' &&
1118 *s != '\t' && *s != '\f' && *s != 27)
1119 odd++;
1120 }
1121
1122 if ((odd * 10 > len) == (arg->arg_type == O_FTTEXT)) /* allow 10% odd */
1123 return &str_no;
1124 else
1125 return &str_yes;
1126}
1127
1128bool
1129do_aexec(really,arglast)
1130STR *really;
1131int *arglast;
1132{
1133 register STR **st = stack->ary_array;
1134 register int sp = arglast[1];
1135 register int items = arglast[2] - sp;
1136 register char **a;
1137 char **argv;
1138 char *tmps;
1139
1140 if (items) {
1141 New(401,argv, items+1, char*);
1142 a = argv;
1143 for (st += ++sp; items > 0; items--,st++) {
1144 if (*st)
1145 *a++ = str_get(*st);
1146 else
1147 *a++ = "";
1148 }
1149 *a = Nullch;
1150#ifdef TAINT
1151 if (*argv[0] != '/') /* will execvp use PATH? */
1152 taintenv(); /* testing IFS here is overkill, probably */
1153#endif
1154 if (really && *(tmps = str_get(really)))
1155 execvp(tmps,argv);
1156 else
1157 execvp(argv[0],argv);
1158 Safefree(argv);
1159 }
1160 return FALSE;
1161}
1162
ff8e2863 1163static char **Argv = Null(char **);
1164static char *Cmd = Nullch;
1165
1166int
1167do_execfree()
1168{
1169 if (Argv) {
1170 Safefree(Argv);
1171 Argv = Null(char **);
1172 }
1173 if (Cmd) {
1174 Safefree(Cmd);
1175 Cmd = Nullch;
1176 }
1177}
1178
a687059c 1179bool
1180do_exec(cmd)
1181char *cmd;
1182{
1183 register char **a;
1184 register char *s;
a687059c 1185 char flags[10];
1186
1187#ifdef TAINT
1188 taintenv();
1189 taintproper("Insecure dependency in exec");
1190#endif
1191
1192 /* save an extra exec if possible */
1193
bf38876a 1194#ifdef CSH
1195 if (strnEQ(cmd,cshname,cshlen) && strnEQ(cmd+cshlen," -c",3)) {
a687059c 1196 strcpy(flags,"-c");
bf38876a 1197 s = cmd+cshlen+3;
a687059c 1198 if (*s == 'f') {
1199 s++;
1200 strcat(flags,"f");
1201 }
1202 if (*s == ' ')
1203 s++;
1204 if (*s++ == '\'') {
1205 char *ncmd = s;
1206
1207 while (*s)
1208 s++;
1209 if (s[-1] == '\n')
1210 *--s = '\0';
1211 if (s[-1] == '\'') {
1212 *--s = '\0';
bf38876a 1213 execl(cshname,"csh", flags,ncmd,(char*)0);
a687059c 1214 *s = '\'';
1215 return FALSE;
1216 }
1217 }
1218 }
bf38876a 1219#endif /* CSH */
a687059c 1220
1221 /* see if there are shell metacharacters in it */
1222
63f2c1e1 1223 for (s = cmd; *s && isalpha(*s); s++) ; /* catch VAR=val gizmo */
1224 if (*s == '=')
1225 goto doshell;
a687059c 1226 for (s = cmd; *s; s++) {
1227 if (*s != ' ' && !isalpha(*s) && index("$&*(){}[]'\";\\|?<>~`\n",*s)) {
1228 if (*s == '\n' && !s[1]) {
1229 *s = '\0';
1230 break;
1231 }
1232 doshell:
1233 execl("/bin/sh","sh","-c",cmd,(char*)0);
1234 return FALSE;
1235 }
1236 }
ff8e2863 1237 New(402,Argv, (s - cmd) / 2 + 2, char*);
1238 Cmd = nsavestr(cmd, s-cmd);
1239 a = Argv;
1240 for (s = Cmd; *s;) {
a687059c 1241 while (*s && isspace(*s)) s++;
1242 if (*s)
1243 *(a++) = s;
1244 while (*s && !isspace(*s)) s++;
1245 if (*s)
1246 *s++ = '\0';
1247 }
1248 *a = Nullch;
ff8e2863 1249 if (Argv[0]) {
1250 execvp(Argv[0],Argv);
b1248f16 1251 if (errno == ENOEXEC) { /* for system V NIH syndrome */
ff8e2863 1252 do_execfree();
a687059c 1253 goto doshell;
b1248f16 1254 }
a687059c 1255 }
ff8e2863 1256 do_execfree();
a687059c 1257 return FALSE;
1258}
1259
1260#ifdef SOCKET
1261int
1262do_socket(stab, arglast)
1263STAB *stab;
1264int *arglast;
1265{
1266 register STR **st = stack->ary_array;
1267 register int sp = arglast[1];
1268 register STIO *stio;
1269 int domain, type, protocol, fd;
1270
1271 if (!stab)
1272 return FALSE;
1273
1274 stio = stab_io(stab);
1275 if (!stio)
1276 stio = stab_io(stab) = stio_new();
1277 else if (stio->ifp)
1278 do_close(stab,FALSE);
1279
1280 domain = (int)str_gnum(st[++sp]);
1281 type = (int)str_gnum(st[++sp]);
1282 protocol = (int)str_gnum(st[++sp]);
1283#ifdef TAINT
1284 taintproper("Insecure dependency in socket");
1285#endif
1286 fd = socket(domain,type,protocol);
1287 if (fd < 0)
1288 return FALSE;
1289 stio->ifp = fdopen(fd, "r"); /* stdio gets confused about sockets */
1290 stio->ofp = fdopen(fd, "w");
1291 stio->type = 's';
1292
1293 return TRUE;
1294}
1295
1296int
1297do_bind(stab, arglast)
1298STAB *stab;
1299int *arglast;
1300{
1301 register STR **st = stack->ary_array;
1302 register int sp = arglast[1];
1303 register STIO *stio;
1304 char *addr;
1305
1306 if (!stab)
1307 goto nuts;
1308
1309 stio = stab_io(stab);
1310 if (!stio || !stio->ifp)
1311 goto nuts;
1312
1313 addr = str_get(st[++sp]);
1314#ifdef TAINT
1315 taintproper("Insecure dependency in bind");
1316#endif
1317 return bind(fileno(stio->ifp), addr, st[sp]->str_cur) >= 0;
1318
1319nuts:
1320 if (dowarn)
1321 warn("bind() on closed fd");
1322 return FALSE;
1323
1324}
1325
1326int
1327do_connect(stab, arglast)
1328STAB *stab;
1329int *arglast;
1330{
1331 register STR **st = stack->ary_array;
1332 register int sp = arglast[1];
1333 register STIO *stio;
1334 char *addr;
1335
1336 if (!stab)
1337 goto nuts;
1338
1339 stio = stab_io(stab);
1340 if (!stio || !stio->ifp)
1341 goto nuts;
1342
1343 addr = str_get(st[++sp]);
1344#ifdef TAINT
1345 taintproper("Insecure dependency in connect");
1346#endif
1347 return connect(fileno(stio->ifp), addr, st[sp]->str_cur) >= 0;
1348
1349nuts:
1350 if (dowarn)
1351 warn("connect() on closed fd");
1352 return FALSE;
1353
1354}
1355
1356int
1357do_listen(stab, arglast)
1358STAB *stab;
1359int *arglast;
1360{
1361 register STR **st = stack->ary_array;
1362 register int sp = arglast[1];
1363 register STIO *stio;
1364 int backlog;
1365
1366 if (!stab)
1367 goto nuts;
1368
1369 stio = stab_io(stab);
1370 if (!stio || !stio->ifp)
1371 goto nuts;
1372
1373 backlog = (int)str_gnum(st[++sp]);
1374 return listen(fileno(stio->ifp), backlog) >= 0;
1375
1376nuts:
1377 if (dowarn)
1378 warn("listen() on closed fd");
1379 return FALSE;
1380}
1381
1382void
1383do_accept(str, nstab, gstab)
1384STR *str;
1385STAB *nstab;
1386STAB *gstab;
1387{
1388 register STIO *nstio;
1389 register STIO *gstio;
1390 int len = sizeof buf;
1391 int fd;
1392
1393 if (!nstab)
1394 goto badexit;
1395 if (!gstab)
1396 goto nuts;
1397
1398 gstio = stab_io(gstab);
1399 nstio = stab_io(nstab);
1400
1401 if (!gstio || !gstio->ifp)
1402 goto nuts;
1403 if (!nstio)
1404 nstio = stab_io(nstab) = stio_new();
1405 else if (nstio->ifp)
1406 do_close(nstab,FALSE);
1407
1408 fd = accept(fileno(gstio->ifp),buf,&len);
1409 if (fd < 0)
1410 goto badexit;
1411 nstio->ifp = fdopen(fd, "r");
1412 nstio->ofp = fdopen(fd, "w");
1413 nstio->type = 's';
1414
1415 str_nset(str, buf, len);
1416 return;
1417
1418nuts:
1419 if (dowarn)
1420 warn("accept() on closed fd");
1421badexit:
1422 str_sset(str,&str_undef);
1423 return;
1424}
1425
1426int
1427do_shutdown(stab, arglast)
1428STAB *stab;
1429int *arglast;
1430{
1431 register STR **st = stack->ary_array;
1432 register int sp = arglast[1];
1433 register STIO *stio;
1434 int how;
1435
1436 if (!stab)
1437 goto nuts;
1438
1439 stio = stab_io(stab);
1440 if (!stio || !stio->ifp)
1441 goto nuts;
1442
1443 how = (int)str_gnum(st[++sp]);
1444 return shutdown(fileno(stio->ifp), how) >= 0;
1445
1446nuts:
1447 if (dowarn)
1448 warn("shutdown() on closed fd");
1449 return FALSE;
1450
1451}
1452
1453int
1454do_sopt(optype, stab, arglast)
1455int optype;
1456STAB *stab;
1457int *arglast;
1458{
1459 register STR **st = stack->ary_array;
1460 register int sp = arglast[1];
1461 register STIO *stio;
1462 int fd;
1463 int lvl;
1464 int optname;
1465
1466 if (!stab)
1467 goto nuts;
1468
1469 stio = stab_io(stab);
1470 if (!stio || !stio->ifp)
1471 goto nuts;
1472
1473 fd = fileno(stio->ifp);
1474 lvl = (int)str_gnum(st[sp+1]);
1475 optname = (int)str_gnum(st[sp+2]);
1476 switch (optype) {
1477 case O_GSOCKOPT:
1478 st[sp] = str_2static(str_new(257));
1479 st[sp]->str_cur = 256;
bf38876a 1480 st[sp]->str_pok = 1;
a687059c 1481 if (getsockopt(fd, lvl, optname, st[sp]->str_ptr, &st[sp]->str_cur) < 0)
1482 goto nuts;
1483 break;
1484 case O_SSOCKOPT:
1485 st[sp] = st[sp+3];
1486 if (setsockopt(fd, lvl, optname, st[sp]->str_ptr, st[sp]->str_cur) < 0)
1487 goto nuts;
1488 st[sp] = &str_yes;
1489 break;
1490 }
1491
1492 return sp;
1493
1494nuts:
1495 if (dowarn)
bf38876a 1496 warn("[gs]etsockopt() on closed fd");
a687059c 1497 st[sp] = &str_undef;
1498 return sp;
1499
1500}
1501
1502int
1503do_getsockname(optype, stab, arglast)
1504int optype;
1505STAB *stab;
1506int *arglast;
1507{
1508 register STR **st = stack->ary_array;
1509 register int sp = arglast[1];
1510 register STIO *stio;
1511 int fd;
1512
1513 if (!stab)
1514 goto nuts;
1515
1516 stio = stab_io(stab);
1517 if (!stio || !stio->ifp)
1518 goto nuts;
1519
1520 st[sp] = str_2static(str_new(257));
1521 st[sp]->str_cur = 256;
bf38876a 1522 st[sp]->str_pok = 1;
a687059c 1523 fd = fileno(stio->ifp);
1524 switch (optype) {
1525 case O_GETSOCKNAME:
1526 if (getsockname(fd, st[sp]->str_ptr, &st[sp]->str_cur) < 0)
ff8e2863 1527 goto nuts2;
a687059c 1528 break;
1529 case O_GETPEERNAME:
1530 if (getpeername(fd, st[sp]->str_ptr, &st[sp]->str_cur) < 0)
ff8e2863 1531 goto nuts2;
a687059c 1532 break;
1533 }
1534
1535 return sp;
1536
1537nuts:
1538 if (dowarn)
bf38876a 1539 warn("get{sock,peer}name() on closed fd");
ff8e2863 1540nuts2:
a687059c 1541 st[sp] = &str_undef;
1542 return sp;
1543
1544}
1545
1546int
1547do_ghent(which,gimme,arglast)
1548int which;
1549int gimme;
1550int *arglast;
1551{
1552 register ARRAY *ary = stack;
1553 register int sp = arglast[0];
1554 register char **elem;
1555 register STR *str;
bf38876a 1556 struct hostent *gethostbyname();
a687059c 1557 struct hostent *gethostbyaddr();
1558#ifdef GETHOSTENT
1559 struct hostent *gethostent();
1560#endif
1561 struct hostent *hent;
1562 unsigned long len;
1563
1564 if (gimme != G_ARRAY) {
1565 astore(ary, ++sp, str_static(&str_undef));
1566 return sp;
1567 }
1568
1569 if (which == O_GHBYNAME) {
1570 char *name = str_get(ary->ary_array[sp+1]);
1571
1572 hent = gethostbyname(name);
1573 }
1574 else if (which == O_GHBYADDR) {
1575 STR *addrstr = ary->ary_array[sp+1];
1576 int addrtype = (int)str_gnum(ary->ary_array[sp+2]);
1577 char *addr = str_get(addrstr);
1578
1579 hent = gethostbyaddr(addr,addrstr->str_cur,addrtype);
1580 }
1581 else
1582#ifdef GETHOSTENT
1583 hent = gethostent();
1584#else
1585 fatal("gethostent not implemented");
1586#endif
1587 if (hent) {
1588#ifndef lint
1589 (void)astore(ary, ++sp, str = str_static(&str_no));
1590 str_set(str, hent->h_name);
1591 (void)astore(ary, ++sp, str = str_static(&str_no));
1592 for (elem = hent->h_aliases; *elem; elem++) {
1593 str_cat(str, *elem);
1594 if (elem[1])
1595 str_ncat(str," ",1);
1596 }
1597 (void)astore(ary, ++sp, str = str_static(&str_no));
1598 str_numset(str, (double)hent->h_addrtype);
1599 (void)astore(ary, ++sp, str = str_static(&str_no));
1600 len = hent->h_length;
1601 str_numset(str, (double)len);
1602#ifdef h_addr
1603 for (elem = hent->h_addr_list; *elem; elem++) {
1604 (void)astore(ary, ++sp, str = str_static(&str_no));
1605 str_nset(str, *elem, len);
1606 }
1607#else
1608 (void)astore(ary, ++sp, str = str_static(&str_no));
1609 str_nset(str, hent->h_addr, len);
1610#endif /* h_addr */
1611#else /* lint */
1612 elem = Nullch;
1613 elem = elem;
1614 (void)astore(ary, ++sp, str_static(&str_no));
1615#endif /* lint */
1616 }
1617
1618 return sp;
1619}
1620
1621int
1622do_gnent(which,gimme,arglast)
1623int which;
1624int gimme;
1625int *arglast;
1626{
1627 register ARRAY *ary = stack;
1628 register int sp = arglast[0];
1629 register char **elem;
1630 register STR *str;
1631 struct netent *getnetbyname();
1632 struct netent *getnetbyaddr();
1633 struct netent *getnetent();
1634 struct netent *nent;
1635
1636 if (gimme != G_ARRAY) {
1637 astore(ary, ++sp, str_static(&str_undef));
1638 return sp;
1639 }
1640
1641 if (which == O_GNBYNAME) {
1642 char *name = str_get(ary->ary_array[sp+1]);
1643
1644 nent = getnetbyname(name);
1645 }
1646 else if (which == O_GNBYADDR) {
1647 STR *addrstr = ary->ary_array[sp+1];
1648 int addrtype = (int)str_gnum(ary->ary_array[sp+2]);
1649 char *addr = str_get(addrstr);
1650
1651 nent = getnetbyaddr(addr,addrtype);
1652 }
1653 else
1654 nent = getnetent();
1655
1656 if (nent) {
1657#ifndef lint
1658 (void)astore(ary, ++sp, str = str_static(&str_no));
1659 str_set(str, nent->n_name);
1660 (void)astore(ary, ++sp, str = str_static(&str_no));
1661 for (elem = nent->n_aliases; *elem; elem++) {
1662 str_cat(str, *elem);
1663 if (elem[1])
1664 str_ncat(str," ",1);
1665 }
1666 (void)astore(ary, ++sp, str = str_static(&str_no));
1667 str_numset(str, (double)nent->n_addrtype);
1668 (void)astore(ary, ++sp, str = str_static(&str_no));
1669 str_numset(str, (double)nent->n_net);
1670#else /* lint */
1671 elem = Nullch;
1672 elem = elem;
1673 (void)astore(ary, ++sp, str_static(&str_no));
1674#endif /* lint */
1675 }
1676
1677 return sp;
1678}
1679
1680int
1681do_gpent(which,gimme,arglast)
1682int which;
1683int gimme;
1684int *arglast;
1685{
1686 register ARRAY *ary = stack;
1687 register int sp = arglast[0];
1688 register char **elem;
1689 register STR *str;
1690 struct protoent *getprotobyname();
1691 struct protoent *getprotobynumber();
1692 struct protoent *getprotoent();
1693 struct protoent *pent;
1694
1695 if (gimme != G_ARRAY) {
1696 astore(ary, ++sp, str_static(&str_undef));
1697 return sp;
1698 }
1699
1700 if (which == O_GPBYNAME) {
1701 char *name = str_get(ary->ary_array[sp+1]);
1702
1703 pent = getprotobyname(name);
1704 }
1705 else if (which == O_GPBYNUMBER) {
1706 int proto = (int)str_gnum(ary->ary_array[sp+1]);
1707
1708 pent = getprotobynumber(proto);
1709 }
1710 else
1711 pent = getprotoent();
1712
1713 if (pent) {
1714#ifndef lint
1715 (void)astore(ary, ++sp, str = str_static(&str_no));
1716 str_set(str, pent->p_name);
1717 (void)astore(ary, ++sp, str = str_static(&str_no));
1718 for (elem = pent->p_aliases; *elem; elem++) {
1719 str_cat(str, *elem);
1720 if (elem[1])
1721 str_ncat(str," ",1);
1722 }
1723 (void)astore(ary, ++sp, str = str_static(&str_no));
1724 str_numset(str, (double)pent->p_proto);
1725#else /* lint */
1726 elem = Nullch;
1727 elem = elem;
1728 (void)astore(ary, ++sp, str_static(&str_no));
1729#endif /* lint */
1730 }
1731
1732 return sp;
1733}
1734
1735int
1736do_gsent(which,gimme,arglast)
1737int which;
1738int gimme;
1739int *arglast;
1740{
1741 register ARRAY *ary = stack;
1742 register int sp = arglast[0];
1743 register char **elem;
1744 register STR *str;
1745 struct servent *getservbyname();
1746 struct servent *getservbynumber();
1747 struct servent *getservent();
1748 struct servent *sent;
1749
1750 if (gimme != G_ARRAY) {
1751 astore(ary, ++sp, str_static(&str_undef));
1752 return sp;
1753 }
1754
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]);
1758
1759 if (proto && !*proto)
1760 proto = Nullch;
1761
1762 sent = getservbyname(name,proto);
1763 }
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]);
1767
1768 sent = getservbyport(port,proto);
1769 }
1770 else
1771 sent = getservent();
1772 if (sent) {
1773#ifndef lint
1774 (void)astore(ary, ++sp, str = str_static(&str_no));
1775 str_set(str, sent->s_name);
1776 (void)astore(ary, ++sp, str = str_static(&str_no));
1777 for (elem = sent->s_aliases; *elem; elem++) {
1778 str_cat(str, *elem);
1779 if (elem[1])
1780 str_ncat(str," ",1);
1781 }
1782 (void)astore(ary, ++sp, str = str_static(&str_no));
1783#ifdef NTOHS
1784 str_numset(str, (double)ntohs(sent->s_port));
1785#else
1786 str_numset(str, (double)(sent->s_port));
1787#endif
1788 (void)astore(ary, ++sp, str = str_static(&str_no));
1789 str_set(str, sent->s_proto);
1790#else /* lint */
1791 elem = Nullch;
1792 elem = elem;
1793 (void)astore(ary, ++sp, str_static(&str_no));
1794#endif /* lint */
1795 }
1796
1797 return sp;
1798}
1799
ff8e2863 1800#endif /* SOCKET */
1801
1802#ifdef SELECT
a687059c 1803int
1804do_select(gimme,arglast)
1805int gimme;
1806int *arglast;
1807{
1808 register STR **st = stack->ary_array;
1809 register int sp = arglast[0];
1810 register int i;
1811 register int j;
1812 register char *s;
1813 register STR *str;
1814 double value;
1815 int maxlen = 0;
1816 int nfound;
1817 struct timeval timebuf;
1818 struct timeval *tbuf = &timebuf;
663a0e37 1819 int growsize;
1820#if BYTEORDER != 0x1234 && BYTEORDER != 0x12345678
1821 int masksize;
1822 int offset;
1823 char *fd_sets[4];
1824 int k;
1825
1826#if BYTEORDER & 0xf0000
1827#define ORDERBYTE (0x88888888 - BYTEORDER)
1828#else
1829#define ORDERBYTE (0x4444 - BYTEORDER)
1830#endif
1831
1832#endif
a687059c 1833
1834 for (i = 1; i <= 3; i++) {
663a0e37 1835 j = st[sp+i]->str_cur;
a687059c 1836 if (maxlen < j)
1837 maxlen = j;
1838 }
663a0e37 1839
1840#if BYTEORDER == 0x1234 || BYTEORDER == 0x12345678
1841 growsize = maxlen; /* little endians can use vecs directly */
1842#else
1843#ifdef NFDBITS
1844
1845#ifndef NBBY
1846#define NBBY 8
1847#endif
1848
1849 masksize = NFDBITS / NBBY;
1850#else
1851 masksize = sizeof(long); /* documented int, everyone seems to use long */
1852#endif
1853 growsize = maxlen + (masksize - (maxlen % masksize));
1854 Zero(&fd_sets[0], 4, char*);
1855#endif
1856
a687059c 1857 for (i = 1; i <= 3; i++) {
1858 str = st[sp+i];
1859 j = str->str_len;
663a0e37 1860 if (j < growsize) {
a687059c 1861 if (str->str_pok) {
ff8e2863 1862 Str_Grow(str,growsize);
a687059c 1863 s = str_get(str) + j;
663a0e37 1864 while (++j <= growsize) {
a687059c 1865 *s++ = '\0';
1866 }
1867 }
1868 else if (str->str_ptr) {
1869 Safefree(str->str_ptr);
1870 str->str_ptr = Nullch;
1871 }
1872 }
663a0e37 1873#if BYTEORDER != 0x1234 && BYTEORDER != 0x12345678
1874 s = str->str_ptr;
1875 if (s) {
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];
1880 }
1881 }
1882#endif
a687059c 1883 }
1884 str = st[sp+4];
1885 if (str->str_nok || str->str_pok) {
1886 value = str_gnum(str);
1887 if (value < 0.0)
1888 value = 0.0;
1889 timebuf.tv_sec = (long)value;
1890 value -= (double)timebuf.tv_sec;
1891 timebuf.tv_usec = (long)(value * 1000000.0);
1892 }
1893 else
1894 tbuf = Null(struct timeval*);
1895
663a0e37 1896#if BYTEORDER == 0x1234 || BYTEORDER == 0x12345678
a687059c 1897 nfound = select(
1898 maxlen * 8,
1899 st[sp+1]->str_ptr,
1900 st[sp+2]->str_ptr,
1901 st[sp+3]->str_ptr,
1902 tbuf);
663a0e37 1903#else
1904 nfound = select(
1905 maxlen * 8,
1906 fd_sets[1],
1907 fd_sets[2],
1908 fd_sets[3],
1909 tbuf);
1910 for (i = 1; i <= 3; i++) {
1911 if (fd_sets[i]) {
1912 str = st[sp+i];
1913 s = str->str_ptr;
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];
1917 }
1918 }
1919 }
1920#endif
a687059c 1921
1922 st[++sp] = str_static(&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_static(&str_no);
1928 str_numset(st[sp], value);
1929 }
1930 return sp;
1931}
ff8e2863 1932#endif /* SELECT */
a687059c 1933
ff8e2863 1934#ifdef SOCKET
a687059c 1935int
1936do_spair(stab1, stab2, arglast)
1937STAB *stab1;
1938STAB *stab2;
1939int *arglast;
1940{
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];
1946
1947 if (!stab1 || !stab2)
1948 return FALSE;
1949
1950 stio1 = stab_io(stab1);
1951 stio2 = stab_io(stab2);
1952 if (!stio1)
1953 stio1 = stab_io(stab1) = stio_new();
1954 else if (stio1->ifp)
1955 do_close(stab1,FALSE);
1956 if (!stio2)
1957 stio2 = stab_io(stab2) = stio_new();
1958 else if (stio2->ifp)
1959 do_close(stab2,FALSE);
1960
1961 domain = (int)str_gnum(st[++sp]);
1962 type = (int)str_gnum(st[++sp]);
1963 protocol = (int)str_gnum(st[++sp]);
1964#ifdef TAINT
1965 taintproper("Insecure dependency in socketpair");
1966#endif
1967#ifdef SOCKETPAIR
1968 if (socketpair(domain,type,protocol,fd) < 0)
1969 return FALSE;
1970#else
1971 fatal("Socketpair unimplemented");
1972#endif
1973 stio1->ifp = fdopen(fd[0], "r");
1974 stio1->ofp = fdopen(fd[0], "w");
1975 stio1->type = 's';
1976 stio2->ifp = fdopen(fd[1], "r");
1977 stio2->ofp = fdopen(fd[1], "w");
1978 stio2->type = 's';
1979
1980 return TRUE;
1981}
1982
1983#endif /* SOCKET */
1984
1985int
1986do_gpwent(which,gimme,arglast)
1987int which;
1988int gimme;
1989int *arglast;
1990{
1991#ifdef I_PWD
1992 register ARRAY *ary = stack;
1993 register int sp = arglast[0];
a687059c 1994 register STR *str;
1995 struct passwd *getpwnam();
1996 struct passwd *getpwuid();
1997 struct passwd *getpwent();
1998 struct passwd *pwent;
a687059c 1999
2000 if (gimme != G_ARRAY) {
2001 astore(ary, ++sp, str_static(&str_undef));
2002 return sp;
2003 }
2004
2005 if (which == O_GPWNAM) {
2006 char *name = str_get(ary->ary_array[sp+1]);
2007
2008 pwent = getpwnam(name);
2009 }
2010 else if (which == O_GPWUID) {
2011 int uid = (int)str_gnum(ary->ary_array[sp+1]);
2012
2013 pwent = getpwuid(uid);
2014 }
2015 else
2016 pwent = getpwent();
2017
2018 if (pwent) {
2019 (void)astore(ary, ++sp, str = str_static(&str_no));
2020 str_set(str, pwent->pw_name);
2021 (void)astore(ary, ++sp, str = str_static(&str_no));
2022 str_set(str, pwent->pw_passwd);
2023 (void)astore(ary, ++sp, str = str_static(&str_no));
2024 str_numset(str, (double)pwent->pw_uid);
2025 (void)astore(ary, ++sp, str = str_static(&str_no));
2026 str_numset(str, (double)pwent->pw_gid);
2027 (void)astore(ary, ++sp, str = str_static(&str_no));
03a14243 2028#ifdef PWCHANGE
2029 str_numset(str, (double)pwent->pw_change);
2030#else
a687059c 2031#ifdef PWQUOTA
2032 str_numset(str, (double)pwent->pw_quota);
2033#else
2034#ifdef PWAGE
2035 str_set(str, pwent->pw_age);
2036#endif
2037#endif
03a14243 2038#endif
a687059c 2039 (void)astore(ary, ++sp, str = str_static(&str_no));
03a14243 2040#ifdef PWCLASS
2041 str_set(str,pwent->pw_class);
2042#else
c2ab57d4 2043#ifdef PWCOMMENT
a687059c 2044 str_set(str, pwent->pw_comment);
03a14243 2045#endif
c2ab57d4 2046#endif
a687059c 2047 (void)astore(ary, ++sp, str = str_static(&str_no));
2048 str_set(str, pwent->pw_gecos);
2049 (void)astore(ary, ++sp, str = str_static(&str_no));
2050 str_set(str, pwent->pw_dir);
2051 (void)astore(ary, ++sp, str = str_static(&str_no));
2052 str_set(str, pwent->pw_shell);
03a14243 2053#ifdef PWEXPIRE
2054 (void)astore(ary, ++sp, str = str_static(&str_no));
2055 str_numset(str, (double)pwent->pw_expire);
2056#endif
a687059c 2057 }
2058
2059 return sp;
2060#else
2061 fatal("password routines not implemented");
2062#endif
2063}
2064
2065int
2066do_ggrent(which,gimme,arglast)
2067int which;
2068int gimme;
2069int *arglast;
2070{
2071#ifdef I_GRP
2072 register ARRAY *ary = stack;
2073 register int sp = arglast[0];
2074 register char **elem;
2075 register STR *str;
2076 struct group *getgrnam();
2077 struct group *getgrgid();
2078 struct group *getgrent();
2079 struct group *grent;
a687059c 2080
2081 if (gimme != G_ARRAY) {
2082 astore(ary, ++sp, str_static(&str_undef));
2083 return sp;
2084 }
2085
2086 if (which == O_GGRNAM) {
2087 char *name = str_get(ary->ary_array[sp+1]);
2088
2089 grent = getgrnam(name);
2090 }
2091 else if (which == O_GGRGID) {
2092 int gid = (int)str_gnum(ary->ary_array[sp+1]);
2093
2094 grent = getgrgid(gid);
2095 }
2096 else
2097 grent = getgrent();
2098
2099 if (grent) {
2100 (void)astore(ary, ++sp, str = str_static(&str_no));
2101 str_set(str, grent->gr_name);
2102 (void)astore(ary, ++sp, str = str_static(&str_no));
2103 str_set(str, grent->gr_passwd);
2104 (void)astore(ary, ++sp, str = str_static(&str_no));
2105 str_numset(str, (double)grent->gr_gid);
2106 (void)astore(ary, ++sp, str = str_static(&str_no));
2107 for (elem = grent->gr_mem; *elem; elem++) {
2108 str_cat(str, *elem);
2109 if (elem[1])
2110 str_ncat(str," ",1);
2111 }
2112 }
2113
2114 return sp;
2115#else
2116 fatal("group routines not implemented");
2117#endif
2118}
2119
2120int
2121do_dirop(optype,stab,gimme,arglast)
2122int optype;
2123STAB *stab;
2124int gimme;
2125int *arglast;
2126{
0d3e774c 2127#if defined(DIRENT) && defined(READDIR)
a687059c 2128 register ARRAY *ary = stack;
2129 register STR **st = ary->ary_array;
2130 register int sp = arglast[1];
2131 register STIO *stio;
2132 long along;
bf38876a 2133#ifndef telldir
a687059c 2134 long telldir();
bf38876a 2135#endif
a687059c 2136 struct DIRENT *readdir();
2137 register struct DIRENT *dp;
2138
2139 if (!stab)
2140 goto nope;
2141 if (!(stio = stab_io(stab)))
2142 stio = stab_io(stab) = stio_new();
2143 if (!stio->dirp && optype != O_OPENDIR)
2144 goto nope;
2145 st[sp] = &str_yes;
2146 switch (optype) {
2147 case O_OPENDIR:
2148 if (stio->dirp)
2149 closedir(stio->dirp);
2150 if (!(stio->dirp = opendir(str_get(st[sp+1]))))
2151 goto nope;
2152 break;
2153 case O_READDIR:
2154 if (gimme == G_ARRAY) {
2155 --sp;
2156 while (dp = readdir(stio->dirp)) {
2157#ifdef DIRNAMLEN
2158 (void)astore(ary,++sp,
2159 str_2static(str_make(dp->d_name,dp->d_namlen)));
2160#else
2161 (void)astore(ary,++sp,
2162 str_2static(str_make(dp->d_name,0)));
2163#endif
2164 }
2165 }
2166 else {
2167 if (!(dp = readdir(stio->dirp)))
2168 goto nope;
2169 st[sp] = str_static(&str_undef);
2170#ifdef DIRNAMLEN
2171 str_nset(st[sp], dp->d_name, dp->d_namlen);
2172#else
2173 str_set(st[sp], dp->d_name);
2174#endif
2175 }
2176 break;
ff8e2863 2177#if MACH
2178 case O_TELLDIR:
2179 case O_SEEKDIR:
2180 goto nope;
2181#else
a687059c 2182 case O_TELLDIR:
2183 st[sp] = str_static(&str_undef);
2184 str_numset(st[sp], (double)telldir(stio->dirp));
2185 break;
2186 case O_SEEKDIR:
2187 st[sp] = str_static(&str_undef);
2188 along = (long)str_gnum(st[sp+1]);
2189 (void)seekdir(stio->dirp,along);
2190 break;
ff8e2863 2191#endif
a687059c 2192 case O_REWINDDIR:
2193 st[sp] = str_static(&str_undef);
2194 (void)rewinddir(stio->dirp);
2195 break;
2196 case O_CLOSEDIR:
2197 st[sp] = str_static(&str_undef);
2198 (void)closedir(stio->dirp);
2199 stio->dirp = 0;
2200 break;
2201 }
2202 return sp;
2203
2204nope:
2205 st[sp] = &str_undef;
2206 return sp;
2207
2208#else
2209 fatal("Unimplemented directory operation");
2210#endif
2211}
2212
2213apply(type,arglast)
2214int type;
2215int *arglast;
2216{
2217 register STR **st = stack->ary_array;
2218 register int sp = arglast[1];
2219 register int items = arglast[2] - sp;
2220 register int val;
2221 register int val2;
2222 register int tot = 0;
2223 char *s;
2224
2225#ifdef TAINT
2226 for (st += ++sp; items--; st++)
2227 tainted |= (*st)->str_tainted;
2228 st = stack->ary_array;
2229 sp = arglast[1];
2230 items = arglast[2] - sp;
2231#endif
2232 switch (type) {
2233 case O_CHMOD:
2234#ifdef TAINT
2235 taintproper("Insecure dependency in chmod");
2236#endif
2237 if (--items > 0) {
2238 tot = items;
2239 val = (int)str_gnum(st[++sp]);
2240 while (items--) {
2241 if (chmod(str_get(st[++sp]),val))
2242 tot--;
2243 }
2244 }
2245 break;
b1248f16 2246#ifdef CHOWN
a687059c 2247 case O_CHOWN:
2248#ifdef TAINT
2249 taintproper("Insecure dependency in chown");
2250#endif
2251 if (items > 2) {
2252 items -= 2;
2253 tot = items;
2254 val = (int)str_gnum(st[++sp]);
2255 val2 = (int)str_gnum(st[++sp]);
2256 while (items--) {
2257 if (chown(str_get(st[++sp]),val,val2))
2258 tot--;
2259 }
2260 }
2261 break;
b1248f16 2262#endif
2263#ifdef KILL
a687059c 2264 case O_KILL:
2265#ifdef TAINT
2266 taintproper("Insecure dependency in kill");
2267#endif
2268 if (--items > 0) {
2269 tot = items;
2270 s = str_get(st[++sp]);
2271 if (isupper(*s)) {
2272 if (*s == 'S' && s[1] == 'I' && s[2] == 'G')
2273 s += 3;
2274 if (!(val = whichsig(s)))
2275 fatal("Unrecognized signal name \"%s\"",s);
2276 }
2277 else
2278 val = (int)str_gnum(st[sp]);
2279 if (val < 0) {
2280 val = -val;
2281 while (items--) {
2282 int proc = (int)str_gnum(st[++sp]);
2283#ifdef KILLPG
2284 if (killpg(proc,val)) /* BSD */
2285#else
2286 if (kill(-proc,val)) /* SYSV */
2287#endif
2288 tot--;
2289 }
2290 }
2291 else {
2292 while (items--) {
2293 if (kill((int)(str_gnum(st[++sp])),val))
2294 tot--;
2295 }
2296 }
2297 }
2298 break;
b1248f16 2299#endif
a687059c 2300 case O_UNLINK:
2301#ifdef TAINT
2302 taintproper("Insecure dependency in unlink");
2303#endif
2304 tot = items;
2305 while (items--) {
2306 s = str_get(st[++sp]);
2307 if (euid || unsafe) {
2308 if (UNLINK(s))
2309 tot--;
2310 }
2311 else { /* don't let root wipe out directories without -U */
0d3e774c 2312#ifdef LSTAT
c623bd54 2313 if (lstat(s,&statbuf) < 0 || S_ISDIR(statbuf.st_mode))
a687059c 2314#else
c623bd54 2315 if (stat(s,&statbuf) < 0 || S_ISDIR(statbuf.st_mode))
a687059c 2316#endif
a687059c 2317 tot--;
2318 else {
2319 if (UNLINK(s))
2320 tot--;
2321 }
2322 }
2323 }
2324 break;
2325 case O_UTIME:
2326#ifdef TAINT
2327 taintproper("Insecure dependency in utime");
2328#endif
2329 if (items > 2) {
663a0e37 2330#ifdef I_UTIME
2331 struct utimbuf utbuf;
2332#else
a687059c 2333 struct {
663a0e37 2334 long actime;
2335 long modtime;
a687059c 2336 } utbuf;
663a0e37 2337#endif
a687059c 2338
afd9f252 2339 Zero(&utbuf, sizeof utbuf, char);
663a0e37 2340 utbuf.actime = (long)str_gnum(st[++sp]); /* time accessed */
2341 utbuf.modtime = (long)str_gnum(st[++sp]); /* time modified */
a687059c 2342 items -= 2;
2343#ifndef lint
2344 tot = items;
2345 while (items--) {
2346 if (utime(str_get(st[++sp]),&utbuf))
2347 tot--;
2348 }
2349#endif
2350 }
2351 else
2352 items = 0;
2353 break;
2354 }
2355 return tot;
2356}
2357
2358/* Do the permissions allow some operation? Assumes statcache already set. */
2359
2360int
2361cando(bit, effective, statbufp)
2362int bit;
2363int effective;
2364register struct stat *statbufp;
2365{
2366 if ((effective ? euid : uid) == 0) { /* root is special */
c623bd54 2367 if (bit == S_IXUSR) {
2368 if (statbufp->st_mode & 0111 || S_ISDIR(statbufp->st_mode))
a687059c 2369 return TRUE;
2370 }
2371 else
2372 return TRUE; /* root reads and writes anything */
2373 return FALSE;
2374 }
2375 if (statbufp->st_uid == (effective ? euid : uid) ) {
2376 if (statbufp->st_mode & bit)
2377 return TRUE; /* ok as "user" */
2378 }
2379 else if (ingroup((int)statbufp->st_gid,effective)) {
2380 if (statbufp->st_mode & bit >> 3)
2381 return TRUE; /* ok as "group" */
2382 }
2383 else if (statbufp->st_mode & bit >> 6)
2384 return TRUE; /* ok as "other" */
2385 return FALSE;
2386}
2387
2388int
2389ingroup(testgid,effective)
2390int testgid;
2391int effective;
2392{
2393 if (testgid == (effective ? egid : gid))
2394 return TRUE;
2395#ifdef GETGROUPS
2396#ifndef NGROUPS
2397#define NGROUPS 32
2398#endif
2399 {
2400 GIDTYPE gary[NGROUPS];
2401 int anum;
2402
2403 anum = getgroups(NGROUPS,gary);
2404 while (--anum >= 0)
2405 if (gary[anum] == testgid)
2406 return TRUE;
2407 }
2408#endif
2409 return FALSE;
2410}
c2ab57d4 2411
2412#ifdef SYSVIPC
2413
2414int
2415do_ipcget(optype, arglast)
2416int optype;
2417int *arglast;
2418{
2419 register STR **st = stack->ary_array;
2420 register int sp = arglast[0];
2421 key_t key;
2422 int n, flags;
2423
2424 key = (key_t)str_gnum(st[++sp]);
2425 n = (optype == O_MSGGET) ? 0 : (int)str_gnum(st[++sp]);
2426 flags = (int)str_gnum(st[++sp]);
2427 errno = 0;
2428 switch (optype)
2429 {
e5d73d77 2430#ifdef IPCMSG
c2ab57d4 2431 case O_MSGGET:
2432 return msgget(key, flags);
e5d73d77 2433#endif
2434#ifdef IPCSEM
c2ab57d4 2435 case O_SEMGET:
2436 return semget(key, n, flags);
e5d73d77 2437#endif
2438#ifdef IPCSHM
c2ab57d4 2439 case O_SHMGET:
2440 return shmget(key, n, flags);
e5d73d77 2441#endif
2442#if !defined(IPCMSG) || !defined(IPCSEM) || !defined(IPCSHM)
2443 default:
2444 fatal("%s not implemented", opname[optype]);
2445#endif
c2ab57d4 2446 }
2447 return -1; /* should never happen */
2448}
2449
2450int
2451do_ipcctl(optype, arglast)
2452int optype;
2453int *arglast;
2454{
2455 register STR **st = stack->ary_array;
2456 register int sp = arglast[0];
2457 STR *astr;
2458 char *a;
2459 int id, n, cmd, infosize, getinfo, ret;
2460
2461 id = (int)str_gnum(st[++sp]);
2462 n = (optype == O_SEMCTL) ? (int)str_gnum(st[++sp]) : 0;
2463 cmd = (int)str_gnum(st[++sp]);
2464 astr = st[++sp];
2465
2466 infosize = 0;
2467 getinfo = (cmd == IPC_STAT);
2468
2469 switch (optype)
2470 {
e5d73d77 2471#ifdef IPCMSG
c2ab57d4 2472 case O_MSGCTL:
2473 if (cmd == IPC_STAT || cmd == IPC_SET)
2474 infosize = sizeof(struct msqid_ds);
2475 break;
e5d73d77 2476#endif
2477#ifdef IPCSHM
c2ab57d4 2478 case O_SHMCTL:
2479 if (cmd == IPC_STAT || cmd == IPC_SET)
2480 infosize = sizeof(struct shmid_ds);
2481 break;
e5d73d77 2482#endif
2483#ifdef IPCSEM
c2ab57d4 2484 case O_SEMCTL:
2485 if (cmd == IPC_STAT || cmd == IPC_SET)
2486 infosize = sizeof(struct semid_ds);
2487 else if (cmd == GETALL || cmd == SETALL)
2488 {
2489 struct semid_ds semds;
2490 if (semctl(id, 0, IPC_STAT, &semds) == -1)
2491 return -1;
2492 getinfo = (cmd == GETALL);
2493 infosize = semds.sem_nsems * sizeof(ushort);
2494 }
2495 break;
e5d73d77 2496#endif
2497#if !defined(IPCMSG) || !defined(IPCSEM) || !defined(IPCSHM)
2498 default:
2499 fatal("%s not implemented", opname[optype]);
2500#endif
c2ab57d4 2501 }
2502
2503 if (infosize)
2504 {
2505 if (getinfo)
2506 {
2507 STR_GROW(astr, infosize+1);
2508 a = str_get(astr);
2509 }
2510 else
2511 {
2512 a = str_get(astr);
2513 if (astr->str_cur != infosize)
2514 {
2515 errno = EINVAL;
2516 return -1;
2517 }
2518 }
2519 }
2520 else
2521 {
2522 int i = (int)str_gnum(astr);
2523 a = (char *)i; /* ouch */
2524 }
2525 errno = 0;
2526 switch (optype)
2527 {
e5d73d77 2528#ifdef IPCMSG
c2ab57d4 2529 case O_MSGCTL:
2530 ret = msgctl(id, cmd, a);
2531 break;
e5d73d77 2532#endif
2533#ifdef IPCSEM
c2ab57d4 2534 case O_SEMCTL:
2535 ret = semctl(id, n, cmd, a);
2536 break;
e5d73d77 2537#endif
2538#ifdef IPCSHM
c2ab57d4 2539 case O_SHMCTL:
2540 ret = shmctl(id, cmd, a);
2541 break;
e5d73d77 2542#endif
c2ab57d4 2543 }
2544 if (getinfo && ret >= 0) {
2545 astr->str_cur = infosize;
2546 astr->str_ptr[infosize] = '\0';
2547 }
2548 return ret;
2549}
2550
2551int
2552do_msgsnd(arglast)
2553int *arglast;
2554{
e5d73d77 2555#ifdef IPCMSG
c2ab57d4 2556 register STR **st = stack->ary_array;
2557 register int sp = arglast[0];
2558 STR *mstr;
2559 char *mbuf;
2560 int id, msize, flags;
2561
2562 id = (int)str_gnum(st[++sp]);
2563 mstr = st[++sp];
2564 flags = (int)str_gnum(st[++sp]);
2565 mbuf = str_get(mstr);
2566 if ((msize = mstr->str_cur - sizeof(long)) < 0) {
2567 errno = EINVAL;
2568 return -1;
2569 }
2570 errno = 0;
2571 return msgsnd(id, mbuf, msize, flags);
e5d73d77 2572#else
2573 fatal("msgsnd not implemented");
2574#endif
c2ab57d4 2575}
2576
2577int
2578do_msgrcv(arglast)
2579int *arglast;
2580{
e5d73d77 2581#ifdef IPCMSG
c2ab57d4 2582 register STR **st = stack->ary_array;
2583 register int sp = arglast[0];
2584 STR *mstr;
2585 char *mbuf;
2586 long mtype;
2587 int id, msize, flags, ret;
2588
2589 id = (int)str_gnum(st[++sp]);
2590 mstr = st[++sp];
2591 msize = (int)str_gnum(st[++sp]);
2592 mtype = (long)str_gnum(st[++sp]);
2593 flags = (int)str_gnum(st[++sp]);
2594 mbuf = str_get(mstr);
2595 if (mstr->str_cur < sizeof(long)+msize+1) {
2596 STR_GROW(mstr, sizeof(long)+msize+1);
2597 mbuf = str_get(mstr);
2598 }
2599 errno = 0;
2600 ret = msgrcv(id, mbuf, msize, mtype, flags);
2601 if (ret >= 0) {
2602 mstr->str_cur = sizeof(long)+ret;
2603 mstr->str_ptr[sizeof(long)+ret] = '\0';
2604 }
2605 return ret;
e5d73d77 2606#else
2607 fatal("msgrcv not implemented");
2608#endif
c2ab57d4 2609}
2610
2611int
2612do_semop(arglast)
2613int *arglast;
2614{
e5d73d77 2615#ifdef IPCSEM
c2ab57d4 2616 register STR **st = stack->ary_array;
2617 register int sp = arglast[0];
2618 STR *opstr;
2619 char *opbuf;
2620 int id, opsize;
2621
2622 id = (int)str_gnum(st[++sp]);
2623 opstr = st[++sp];
2624 opbuf = str_get(opstr);
2625 opsize = opstr->str_cur;
2626 if (opsize < sizeof(struct sembuf)
2627 || (opsize % sizeof(struct sembuf)) != 0) {
2628 errno = EINVAL;
2629 return -1;
2630 }
2631 errno = 0;
2632 return semop(id, opbuf, opsize/sizeof(struct sembuf));
e5d73d77 2633#else
2634 fatal("semop not implemented");
2635#endif
c2ab57d4 2636}
2637
2638int
2639do_shmio(optype, arglast)
2640int optype;
2641int *arglast;
2642{
e5d73d77 2643#ifdef IPCSHM
c2ab57d4 2644 register STR **st = stack->ary_array;
2645 register int sp = arglast[0];
2646 STR *mstr;
2647 char *mbuf, *shm;
2648 int id, mpos, msize;
2649 struct shmid_ds shmds;
2650 extern char *shmat();
2651
2652 id = (int)str_gnum(st[++sp]);
2653 mstr = st[++sp];
2654 mpos = (int)str_gnum(st[++sp]);
2655 msize = (int)str_gnum(st[++sp]);
2656 errno = 0;
2657 if (shmctl(id, IPC_STAT, &shmds) == -1)
2658 return -1;
2659 if (mpos < 0 || msize < 0 || mpos + msize > shmds.shm_segsz) {
2660 errno = EFAULT; /* can't do as caller requested */
2661 return -1;
2662 }
2663 shm = shmat(id, (char *)NULL, (optype == O_SHMREAD) ? SHM_RDONLY : 0);
2664 if (shm == (char *)-1) /* I hate System V IPC, I really do */
2665 return -1;
2666 mbuf = str_get(mstr);
2667 if (optype == O_SHMREAD) {
2668 if (mstr->str_cur < msize) {
2669 STR_GROW(mstr, msize+1);
2670 mbuf = str_get(mstr);
2671 }
2672 bcopy(shm + mpos, mbuf, msize);
2673 mstr->str_cur = msize;
2674 mstr->str_ptr[msize] = '\0';
2675 }
2676 else {
2677 int n;
2678
2679 if ((n = mstr->str_cur) > msize)
2680 n = msize;
2681 bcopy(mbuf, shm + mpos, n);
2682 if (n < msize)
2683 bzero(shm + mpos + n, msize - n);
2684 }
2685 return shmdt(shm);
e5d73d77 2686#else
2687 fatal("shm I/O not implemented");
2688#endif
c2ab57d4 2689}
2690
2691#endif /* SYSVIPC */