perl 3.0 patch #15 (combined patch)
[p5sagit/p5-mst-13.2.git] / doio.c
CommitLineData
63f2c1e1 1/* $Header: doio.c,v 3.0.1.7 90/03/14 12:26:24 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 $
63f2c1e1 9 * Revision 3.0.1.7 90/03/14 12:26:24 lwall
10 * patch15: commands involving execs could cause malloc arena corruption
11 *
ff2452de 12 * Revision 3.0.1.6 90/03/12 16:30:07 lwall
13 * patch13: system 'FOO=bar command' didn't invoke sh as it should
14 *
afd9f252 15 * Revision 3.0.1.5 90/02/28 17:01:36 lwall
16 * patch9: open(FOO,"$filename\0") will now protect trailing spaces in filename
17 * patch9: removed obsolete checks to avoid opening block devices
18 * patch9: removed references to acusec and modusec that some utime.h's have
19 * patch9: added pipe function
20 *
663a0e37 21 * Revision 3.0.1.4 89/12/21 19:55:10 lwall
22 * patch7: select now works on big-endian machines
23 * patch7: errno may now be a macro with an lvalue
24 * patch7: ANSI strerror() is now supported
25 * patch7: Configure now detects DG/UX thingies like [sg]etpgrp2 and utime.h
26 *
0d3e774c 27 * Revision 3.0.1.3 89/11/17 15:13:06 lwall
28 * patch5: some systems have symlink() but not lstat()
29 * patch5: some systems have dirent.h but not readdir()
30 *
bf38876a 31 * Revision 3.0.1.2 89/11/11 04:25:51 lwall
32 * patch2: orthogonalized the file modes some so we can have <& +<& etc.
33 * patch2: do_open() now detects sockets passed to process from parent
34 * patch2: fd's above 2 are now closed on exec
35 * patch2: csh code can now use csh from other than /bin
36 * patch2: getsockopt, get{sock,peer}name didn't define result properly
37 * patch2: warn("shutdown") was replicated
38 * patch2: gethostbyname was misdeclared
39 * patch2: telldir() is sometimes a macro
40 *
03a14243 41 * Revision 3.0.1.1 89/10/26 23:10:05 lwall
42 * patch1: Configure now checks for BSD shadow passwords
43 *
a687059c 44 * Revision 3.0 89/10/18 15:10:54 lwall
45 * 3.0 baseline
46 *
47 */
48
49#include "EXTERN.h"
50#include "perl.h"
51
52#ifdef SOCKET
53#include <sys/socket.h>
54#include <netdb.h>
55#endif
56
a687059c 57#ifdef I_PWD
58#include <pwd.h>
59#endif
60#ifdef I_GRP
61#include <grp.h>
62#endif
663a0e37 63#ifdef I_UTIME
64#include <utime.h>
65#endif
a687059c 66
67bool
afd9f252 68do_open(stab,name,len)
a687059c 69STAB *stab;
70register char *name;
afd9f252 71int len;
a687059c 72{
73 FILE *fp;
a687059c 74 register STIO *stio = stab_io(stab);
75 char *myname = savestr(name);
76 int result;
77 int fd;
78 int writing = 0;
79 char mode[3]; /* stdio file mode ("r\0" or "r+\0") */
80
81 name = myname;
82 forkprocess = 1; /* assume true if no fork */
83 while (len && isspace(name[len-1]))
84 name[--len] = '\0';
85 if (!stio)
86 stio = stab_io(stab) = stio_new();
87 else if (stio->ifp) {
88 fd = fileno(stio->ifp);
89 if (stio->type == '|')
90 result = mypclose(stio->ifp);
91 else if (stio->ifp != stio->ofp) {
92 if (stio->ofp)
93 fclose(stio->ofp);
94 result = fclose(stio->ifp);
95 }
96 else if (stio->type != '-')
97 result = fclose(stio->ifp);
98 else
99 result = 0;
100 if (result == EOF && fd > 2)
101 fprintf(stderr,"Warning: unable to close filehandle %s properly.\n",
102 stab_name(stab));
103 stio->ofp = stio->ifp = Nullfp;
104 }
105 if (*name == '+' && len > 1 && name[len-1] != '|') { /* scary */
106 mode[1] = *name++;
107 mode[2] = '\0';
108 --len;
109 writing = 1;
110 }
111 else {
112 mode[1] = '\0';
113 }
114 stio->type = *name;
115 if (*name == '|') {
116 for (name++; isspace(*name); name++) ;
117#ifdef TAINT
118 taintenv();
119 taintproper("Insecure dependency in piped open");
120#endif
121 fp = mypopen(name,"w");
122 writing = 1;
123 }
a687059c 124 else if (*name == '>') {
125#ifdef TAINT
126 taintproper("Insecure dependency in open");
127#endif
bf38876a 128 name++;
129 if (*name == '>') {
130 mode[0] = stio->type = 'a';
131 name++;
a687059c 132 }
bf38876a 133 else
a687059c 134 mode[0] = 'w';
a687059c 135 writing = 1;
bf38876a 136 if (*name == '&') {
137 duplicity:
138 name++;
139 while (isspace(*name))
140 name++;
141 if (isdigit(*name))
142 fd = atoi(name);
143 else {
144 stab = stabent(name,FALSE);
145 if (!stab || !stab_io(stab))
146 return FALSE;
147 if (stab_io(stab) && stab_io(stab)->ifp) {
148 fd = fileno(stab_io(stab)->ifp);
149 if (stab_io(stab)->type == 's')
150 stio->type = 's';
151 }
152 else
153 fd = -1;
154 }
155 fp = fdopen(dup(fd),mode);
156 }
157 else {
158 while (isspace(*name))
159 name++;
160 if (strEQ(name,"-")) {
161 fp = stdout;
162 stio->type = '-';
163 }
164 else {
165 fp = fopen(name,mode);
166 }
167 }
a687059c 168 }
169 else {
170 if (*name == '<') {
bf38876a 171 mode[0] = 'r';
172 name++;
173 while (isspace(*name))
174 name++;
175 if (*name == '&')
176 goto duplicity;
a687059c 177 if (strEQ(name,"-")) {
178 fp = stdin;
179 stio->type = '-';
180 }
bf38876a 181 else
a687059c 182 fp = fopen(name,mode);
a687059c 183 }
184 else if (name[len-1] == '|') {
185#ifdef TAINT
186 taintenv();
187 taintproper("Insecure dependency in piped open");
188#endif
189 name[--len] = '\0';
190 while (len && isspace(name[len-1]))
191 name[--len] = '\0';
192 for (; isspace(*name); name++) ;
193 fp = mypopen(name,"r");
194 stio->type = '|';
195 }
196 else {
197 stio->type = '<';
198 for (; isspace(*name); name++) ;
199 if (strEQ(name,"-")) {
200 fp = stdin;
201 stio->type = '-';
202 }
203 else
204 fp = fopen(name,"r");
205 }
206 }
207 Safefree(myname);
208 if (!fp)
209 return FALSE;
210 if (stio->type &&
211 stio->type != '|' && stio->type != '-') {
212 if (fstat(fileno(fp),&statbuf) < 0) {
213 (void)fclose(fp);
214 return FALSE;
215 }
bf38876a 216 result = (statbuf.st_mode & S_IFMT);
bf38876a 217#ifdef S_IFSOCK
218 if (result == S_IFSOCK || result == 0)
219 stio->type = 's'; /* in case a socket was passed in to us */
220#endif
a687059c 221 }
bf38876a 222#if defined(FCNTL) && defined(F_SETFD)
223 fd = fileno(fp);
224 if (fd >= 3)
225 fcntl(fd,F_SETFD,1);
226#endif
a687059c 227 stio->ifp = fp;
bf38876a 228 if (writing) {
229 if (stio->type != 's')
230 stio->ofp = fp;
231 else
232 stio->ofp = fdopen(fileno(fp),"w");
233 }
a687059c 234 return TRUE;
235}
236
237FILE *
238nextargv(stab)
239register STAB *stab;
240{
241 register STR *str;
242 char *oldname;
243 int filemode,fileuid,filegid;
244
245 while (alen(stab_xarray(stab)) >= 0) {
246 str = ashift(stab_xarray(stab));
247 str_sset(stab_val(stab),str);
248 STABSET(stab_val(stab));
249 oldname = str_get(stab_val(stab));
afd9f252 250 if (do_open(stab,oldname,stab_val(stab)->str_cur)) {
a687059c 251 if (inplace) {
252#ifdef TAINT
253 taintproper("Insecure dependency in inplace open");
254#endif
255 filemode = statbuf.st_mode;
256 fileuid = statbuf.st_uid;
257 filegid = statbuf.st_gid;
258 if (*inplace) {
259 str_cat(str,inplace);
260#ifdef RENAME
261 (void)rename(oldname,str->str_ptr);
262#else
263 (void)UNLINK(str->str_ptr);
264 (void)link(oldname,str->str_ptr);
265 (void)UNLINK(oldname);
266#endif
267 }
268 else {
269 (void)UNLINK(oldname);
270 }
271
272 str_nset(str,">",1);
273 str_cat(str,oldname);
274 errno = 0; /* in case sprintf set errno */
afd9f252 275 if (!do_open(argvoutstab,str->str_ptr,str->str_cur))
a687059c 276 fatal("Can't do inplace edit");
277 defoutstab = argvoutstab;
278#ifdef FCHMOD
279 (void)fchmod(fileno(stab_io(argvoutstab)->ifp),filemode);
280#else
281 (void)chmod(oldname,filemode);
282#endif
283#ifdef FCHOWN
284 (void)fchown(fileno(stab_io(argvoutstab)->ifp),fileuid,filegid);
285#else
286 (void)chown(oldname,fileuid,filegid);
287#endif
288 }
289 str_free(str);
290 return stab_io(stab)->ifp;
291 }
292 else
293 fprintf(stderr,"Can't open %s\n",str_get(str));
294 str_free(str);
295 }
296 if (inplace) {
297 (void)do_close(argvoutstab,FALSE);
298 defoutstab = stabent("STDOUT",TRUE);
299 }
300 return Nullfp;
301}
302
afd9f252 303void
304do_pipe(str, rstab, wstab)
305STR *str;
306STAB *rstab;
307STAB *wstab;
308{
309 register STIO *rstio;
310 register STIO *wstio;
311 int fd[2];
312
313 if (!rstab)
314 goto badexit;
315 if (!wstab)
316 goto badexit;
317
318 rstio = stab_io(rstab);
319 wstio = stab_io(wstab);
320
321 if (!rstio)
322 rstio = stab_io(rstab) = stio_new();
323 else if (rstio->ifp)
324 do_close(rstab,FALSE);
325 if (!wstio)
326 wstio = stab_io(wstab) = stio_new();
327 else if (wstio->ifp)
328 do_close(wstab,FALSE);
329
330 if (pipe(fd) < 0)
331 goto badexit;
332 rstio->ifp = fdopen(fd[0], "r");
333 wstio->ofp = fdopen(fd[1], "w");
334 wstio->ifp = wstio->ofp;
335 rstio->type = '<';
336 wstio->type = '>';
337
338 str_sset(str,&str_yes);
339 return;
340
341badexit:
342 str_sset(str,&str_undef);
343 return;
344}
345
a687059c 346bool
347do_close(stab,explicit)
348STAB *stab;
349bool explicit;
350{
351 bool retval = FALSE;
352 register STIO *stio = stab_io(stab);
353 int status;
354
355 if (!stio) { /* never opened */
356 if (dowarn && explicit)
357 warn("Close on unopened file <%s>",stab_name(stab));
358 return FALSE;
359 }
360 if (stio->ifp) {
361 if (stio->type == '|') {
362 status = mypclose(stio->ifp);
363 retval = (status >= 0);
364 statusvalue = (unsigned)status & 0xffff;
365 }
366 else if (stio->type == '-')
367 retval = TRUE;
368 else {
369 if (stio->ofp && stio->ofp != stio->ifp) /* a socket */
370 fclose(stio->ofp);
371 retval = (fclose(stio->ifp) != EOF);
372 }
373 stio->ofp = stio->ifp = Nullfp;
374 }
375 if (explicit)
376 stio->lines = 0;
377 stio->type = ' ';
378 return retval;
379}
380
381bool
382do_eof(stab)
383STAB *stab;
384{
385 register STIO *stio;
386 int ch;
387
388 if (!stab) { /* eof() */
389 if (argvstab)
390 stio = stab_io(argvstab);
391 else
392 return TRUE;
393 }
394 else
395 stio = stab_io(stab);
396
397 if (!stio)
398 return TRUE;
399
400 while (stio->ifp) {
401
402#ifdef STDSTDIO /* (the code works without this) */
403 if (stio->ifp->_cnt > 0) /* cheat a little, since */
404 return FALSE; /* this is the most usual case */
405#endif
406
407 ch = getc(stio->ifp);
408 if (ch != EOF) {
409 (void)ungetc(ch, stio->ifp);
410 return FALSE;
411 }
412 if (!stab) { /* not necessarily a real EOF yet? */
413 if (!nextargv(argvstab)) /* get another fp handy */
414 return TRUE;
415 }
416 else
417 return TRUE; /* normal fp, definitely end of file */
418 }
419 return TRUE;
420}
421
422long
423do_tell(stab)
424STAB *stab;
425{
426 register STIO *stio;
427
428 if (!stab)
429 goto phooey;
430
431 stio = stab_io(stab);
432 if (!stio || !stio->ifp)
433 goto phooey;
434
435 if (feof(stio->ifp))
436 (void)fseek (stio->ifp, 0L, 2); /* ultrix 1.2 workaround */
437
438 return ftell(stio->ifp);
439
440phooey:
441 if (dowarn)
442 warn("tell() on unopened file");
443 return -1L;
444}
445
446bool
447do_seek(stab, pos, whence)
448STAB *stab;
449long pos;
450int whence;
451{
452 register STIO *stio;
453
454 if (!stab)
455 goto nuts;
456
457 stio = stab_io(stab);
458 if (!stio || !stio->ifp)
459 goto nuts;
460
461 if (feof(stio->ifp))
462 (void)fseek (stio->ifp, 0L, 2); /* ultrix 1.2 workaround */
463
464 return fseek(stio->ifp, pos, whence) >= 0;
465
466nuts:
467 if (dowarn)
468 warn("seek() on unopened file");
469 return FALSE;
470}
471
472int
473do_ctl(optype,stab,func,argstr)
474int optype;
475STAB *stab;
476int func;
477STR *argstr;
478{
479 register STIO *stio;
480 register char *s;
481 int retval;
482
483 if (!stab || !argstr)
484 return -1;
485 stio = stab_io(stab);
486 if (!stio)
487 return -1;
488
489 if (argstr->str_pok || !argstr->str_nok) {
490 if (!argstr->str_pok)
491 s = str_get(argstr);
492
493#ifdef IOCPARM_MASK
494#ifndef IOCPARM_LEN
495#define IOCPARM_LEN(x) (((x) >> 16) & IOCPARM_MASK)
496#endif
497#endif
498#ifdef IOCPARM_LEN
499 retval = IOCPARM_LEN(func); /* on BSDish systes we're safe */
500#else
501 retval = 256; /* otherwise guess at what's safe */
502#endif
503 if (argstr->str_cur < retval) {
504 str_grow(argstr,retval+1);
505 argstr->str_cur = retval;
506 }
507
508 s = argstr->str_ptr;
509 s[argstr->str_cur] = 17; /* a little sanity check here */
510 }
511 else {
512 retval = (int)str_gnum(argstr);
513 s = (char*)retval; /* ouch */
514 }
515
516#ifndef lint
517 if (optype == O_IOCTL)
518 retval = ioctl(fileno(stio->ifp), func, s);
519 else
520#ifdef I_FCNTL
521 retval = fcntl(fileno(stio->ifp), func, s);
522#else
523 fatal("fcntl is not implemented");
524#endif
525#else /* lint */
526 retval = 0;
527#endif /* lint */
528
529 if (argstr->str_pok) {
530 if (s[argstr->str_cur] != 17)
531 fatal("Return value overflowed string");
532 s[argstr->str_cur] = 0; /* put our null back */
533 }
534 return retval;
535}
536
537int
538do_stat(str,arg,gimme,arglast)
539STR *str;
540register ARG *arg;
541int gimme;
542int *arglast;
543{
544 register ARRAY *ary = stack;
545 register int sp = arglast[0] + 1;
546 int max = 13;
547 register int i;
548
549 if ((arg[1].arg_type & A_MASK) == A_WORD) {
550 tmpstab = arg[1].arg_ptr.arg_stab;
551 if (tmpstab != defstab) {
552 statstab = tmpstab;
553 str_set(statname,"");
554 if (!stab_io(tmpstab) ||
555 fstat(fileno(stab_io(tmpstab)->ifp),&statcache) < 0) {
556 max = 0;
557 }
558 }
559 }
560 else {
561 str_sset(statname,ary->ary_array[sp]);
562 statstab = Nullstab;
0d3e774c 563#ifdef LSTAT
a687059c 564 if (arg->arg_type == O_LSTAT)
565 i = lstat(str_get(statname),&statcache);
566 else
567#endif
568 i = stat(str_get(statname),&statcache);
569 if (i < 0)
570 max = 0;
571 }
572
573 if (gimme != G_ARRAY) {
574 if (max)
575 str_sset(str,&str_yes);
576 else
577 str_sset(str,&str_undef);
578 STABSET(str);
579 ary->ary_array[sp] = str;
580 return sp;
581 }
582 sp--;
583 if (max) {
584#ifndef lint
585 (void)astore(ary,++sp,
586 str_2static(str_nmake((double)statcache.st_dev)));
587 (void)astore(ary,++sp,
588 str_2static(str_nmake((double)statcache.st_ino)));
589 (void)astore(ary,++sp,
590 str_2static(str_nmake((double)statcache.st_mode)));
591 (void)astore(ary,++sp,
592 str_2static(str_nmake((double)statcache.st_nlink)));
593 (void)astore(ary,++sp,
594 str_2static(str_nmake((double)statcache.st_uid)));
595 (void)astore(ary,++sp,
596 str_2static(str_nmake((double)statcache.st_gid)));
597 (void)astore(ary,++sp,
598 str_2static(str_nmake((double)statcache.st_rdev)));
599 (void)astore(ary,++sp,
600 str_2static(str_nmake((double)statcache.st_size)));
601 (void)astore(ary,++sp,
602 str_2static(str_nmake((double)statcache.st_atime)));
603 (void)astore(ary,++sp,
604 str_2static(str_nmake((double)statcache.st_mtime)));
605 (void)astore(ary,++sp,
606 str_2static(str_nmake((double)statcache.st_ctime)));
607#ifdef STATBLOCKS
608 (void)astore(ary,++sp,
609 str_2static(str_nmake((double)statcache.st_blksize)));
610 (void)astore(ary,++sp,
611 str_2static(str_nmake((double)statcache.st_blocks)));
612#else
613 (void)astore(ary,++sp,
614 str_2static(str_make("",0)));
615 (void)astore(ary,++sp,
616 str_2static(str_make("",0)));
617#endif
618#else /* lint */
619 (void)astore(ary,++sp,str_nmake(0.0));
620#endif /* lint */
621 }
622 return sp;
623}
624
625int
626looks_like_number(str)
627STR *str;
628{
629 register char *s;
630 register char *send;
631
632 if (!str->str_pok)
633 return TRUE;
634 s = str->str_ptr;
635 send = s + str->str_cur;
636 while (isspace(*s))
637 s++;
638 if (s >= send)
639 return FALSE;
640 if (*s == '+' || *s == '-')
641 s++;
642 while (isdigit(*s))
643 s++;
644 if (s == send)
645 return TRUE;
646 if (*s == '.')
647 s++;
648 else if (s == str->str_ptr)
649 return FALSE;
650 while (isdigit(*s))
651 s++;
652 if (s == send)
653 return TRUE;
654 if (*s == 'e' || *s == 'E') {
655 s++;
656 if (*s == '+' || *s == '-')
657 s++;
658 while (isdigit(*s))
659 s++;
660 }
661 while (isspace(*s))
662 s++;
663 if (s >= send)
664 return TRUE;
665 return FALSE;
666}
667
668bool
669do_print(str,fp)
670register STR *str;
671FILE *fp;
672{
673 register char *tmps;
674
675 if (!fp) {
676 if (dowarn)
677 warn("print to unopened file");
678 return FALSE;
679 }
680 if (!str)
681 return FALSE;
682 if (ofmt &&
683 ((str->str_nok && str->str_u.str_nval != 0.0)
684 || (looks_like_number(str) && str_gnum(str) != 0.0) ) )
685 fprintf(fp, ofmt, str->str_u.str_nval);
686 else {
687 tmps = str_get(str);
688 if (*tmps == 'S' && tmps[1] == 't' && tmps[2] == 'a' && tmps[3] == 'b'
689 && str->str_cur == sizeof(STBP) && strlen(tmps) < str->str_cur) {
690 tmps = stab_name(((STAB*)str)); /* a stab value, be nice */
691 str = ((STAB*)str)->str_magic;
692 putc('*',fp);
693 }
694 if (str->str_cur && fwrite(tmps,1,str->str_cur,fp) == 0)
695 return FALSE;
696 }
697 return TRUE;
698}
699
700bool
701do_aprint(arg,fp,arglast)
702register ARG *arg;
703register FILE *fp;
704int *arglast;
705{
706 register STR **st = stack->ary_array;
707 register int sp = arglast[1];
708 register int retval;
709 register int items = arglast[2] - sp;
710
711 if (!fp) {
712 if (dowarn)
713 warn("print to unopened file");
714 return FALSE;
715 }
716 st += ++sp;
717 if (arg->arg_type == O_PRTF) {
718 do_sprintf(arg->arg_ptr.arg_str,items,st);
719 retval = do_print(arg->arg_ptr.arg_str,fp);
720 }
721 else {
722 retval = (items <= 0);
723 for (; items > 0; items--,st++) {
724 if (retval && ofslen) {
725 if (fwrite(ofs, 1, ofslen, fp) == 0) {
726 retval = FALSE;
727 break;
728 }
729 }
730 if (!(retval = do_print(*st, fp)))
731 break;
732 }
733 if (retval && orslen)
734 if (fwrite(ors, 1, orslen, fp) == 0)
735 retval = FALSE;
736 }
737 return retval;
738}
739
740int
741mystat(arg,str)
742ARG *arg;
743STR *str;
744{
745 STIO *stio;
746
747 if (arg[1].arg_type & A_DONT) {
748 stio = stab_io(arg[1].arg_ptr.arg_stab);
749 if (stio && stio->ifp) {
750 statstab = arg[1].arg_ptr.arg_stab;
751 str_set(statname,"");
752 return fstat(fileno(stio->ifp), &statcache);
753 }
754 else {
755 if (arg[1].arg_ptr.arg_stab == defstab)
756 return 0;
757 if (dowarn)
758 warn("Stat on unopened file <%s>",
759 stab_name(arg[1].arg_ptr.arg_stab));
760 statstab = Nullstab;
761 str_set(statname,"");
762 return -1;
763 }
764 }
765 else {
766 statstab = Nullstab;
767 str_sset(statname,str);
768 return stat(str_get(str),&statcache);
769 }
770}
771
772STR *
773do_fttext(arg,str)
774register ARG *arg;
775STR *str;
776{
777 int i;
778 int len;
779 int odd = 0;
780 STDCHAR tbuf[512];
781 register STDCHAR *s;
782 register STIO *stio;
783
784 if (arg[1].arg_type & A_DONT) {
785 if (arg[1].arg_ptr.arg_stab == defstab) {
786 if (statstab)
787 stio = stab_io(statstab);
788 else {
789 str = statname;
790 goto really_filename;
791 }
792 }
793 else {
794 statstab = arg[1].arg_ptr.arg_stab;
795 str_set(statname,"");
796 stio = stab_io(statstab);
797 }
798 if (stio && stio->ifp) {
799#ifdef STDSTDIO
800 fstat(fileno(stio->ifp),&statcache);
801 if (stio->ifp->_cnt <= 0) {
802 i = getc(stio->ifp);
803 if (i != EOF)
804 (void)ungetc(i,stio->ifp);
805 }
806 if (stio->ifp->_cnt <= 0) /* null file is anything */
807 return &str_yes;
808 len = stio->ifp->_cnt + (stio->ifp->_ptr - stio->ifp->_base);
809 s = stio->ifp->_base;
810#else
811 fatal("-T and -B not implemented on filehandles\n");
812#endif
813 }
814 else {
815 if (dowarn)
816 warn("Test on unopened file <%s>",
817 stab_name(arg[1].arg_ptr.arg_stab));
818 return &str_undef;
819 }
820 }
821 else {
822 statstab = Nullstab;
823 str_sset(statname,str);
824 really_filename:
825 i = open(str_get(str),0);
826 if (i < 0)
827 return &str_undef;
828 fstat(i,&statcache);
829 len = read(i,tbuf,512);
830 if (len <= 0) /* null file is anything */
831 return &str_yes;
832 (void)close(i);
833 s = tbuf;
834 }
835
836 /* now scan s to look for textiness */
837
838 for (i = 0; i < len; i++,s++) {
839 if (!*s) { /* null never allowed in text */
840 odd += len;
841 break;
842 }
843 else if (*s & 128)
844 odd++;
845 else if (*s < 32 &&
846 *s != '\n' && *s != '\r' && *s != '\b' &&
847 *s != '\t' && *s != '\f' && *s != 27)
848 odd++;
849 }
850
851 if ((odd * 10 > len) == (arg->arg_type == O_FTTEXT)) /* allow 10% odd */
852 return &str_no;
853 else
854 return &str_yes;
855}
856
857bool
858do_aexec(really,arglast)
859STR *really;
860int *arglast;
861{
862 register STR **st = stack->ary_array;
863 register int sp = arglast[1];
864 register int items = arglast[2] - sp;
865 register char **a;
866 char **argv;
867 char *tmps;
868
869 if (items) {
870 New(401,argv, items+1, char*);
871 a = argv;
872 for (st += ++sp; items > 0; items--,st++) {
873 if (*st)
874 *a++ = str_get(*st);
875 else
876 *a++ = "";
877 }
878 *a = Nullch;
879#ifdef TAINT
880 if (*argv[0] != '/') /* will execvp use PATH? */
881 taintenv(); /* testing IFS here is overkill, probably */
882#endif
883 if (really && *(tmps = str_get(really)))
884 execvp(tmps,argv);
885 else
886 execvp(argv[0],argv);
887 Safefree(argv);
888 }
889 return FALSE;
890}
891
892bool
893do_exec(cmd)
894char *cmd;
895{
896 register char **a;
897 register char *s;
898 char **argv;
899 char flags[10];
900
901#ifdef TAINT
902 taintenv();
903 taintproper("Insecure dependency in exec");
904#endif
905
906 /* save an extra exec if possible */
907
bf38876a 908#ifdef CSH
909 if (strnEQ(cmd,cshname,cshlen) && strnEQ(cmd+cshlen," -c",3)) {
a687059c 910 strcpy(flags,"-c");
bf38876a 911 s = cmd+cshlen+3;
a687059c 912 if (*s == 'f') {
913 s++;
914 strcat(flags,"f");
915 }
916 if (*s == ' ')
917 s++;
918 if (*s++ == '\'') {
919 char *ncmd = s;
920
921 while (*s)
922 s++;
923 if (s[-1] == '\n')
924 *--s = '\0';
925 if (s[-1] == '\'') {
926 *--s = '\0';
bf38876a 927 execl(cshname,"csh", flags,ncmd,(char*)0);
a687059c 928 *s = '\'';
929 return FALSE;
930 }
931 }
932 }
bf38876a 933#endif /* CSH */
a687059c 934
935 /* see if there are shell metacharacters in it */
936
63f2c1e1 937 for (s = cmd; *s && isalpha(*s); s++) ; /* catch VAR=val gizmo */
938 if (*s == '=')
939 goto doshell;
a687059c 940 for (s = cmd; *s; s++) {
941 if (*s != ' ' && !isalpha(*s) && index("$&*(){}[]'\";\\|?<>~`\n",*s)) {
942 if (*s == '\n' && !s[1]) {
943 *s = '\0';
944 break;
945 }
946 doshell:
947 execl("/bin/sh","sh","-c",cmd,(char*)0);
948 return FALSE;
949 }
950 }
951 New(402,argv, (s - cmd) / 2 + 2, char*);
952
953 a = argv;
954 for (s = cmd; *s;) {
955 while (*s && isspace(*s)) s++;
956 if (*s)
957 *(a++) = s;
958 while (*s && !isspace(*s)) s++;
959 if (*s)
960 *s++ = '\0';
961 }
962 *a = Nullch;
963 if (argv[0]) {
964 execvp(argv[0],argv);
965 if (errno == ENOEXEC) /* for system V NIH syndrome */
966 goto doshell;
967 }
968 Safefree(argv);
969 return FALSE;
970}
971
972#ifdef SOCKET
973int
974do_socket(stab, arglast)
975STAB *stab;
976int *arglast;
977{
978 register STR **st = stack->ary_array;
979 register int sp = arglast[1];
980 register STIO *stio;
981 int domain, type, protocol, fd;
982
983 if (!stab)
984 return FALSE;
985
986 stio = stab_io(stab);
987 if (!stio)
988 stio = stab_io(stab) = stio_new();
989 else if (stio->ifp)
990 do_close(stab,FALSE);
991
992 domain = (int)str_gnum(st[++sp]);
993 type = (int)str_gnum(st[++sp]);
994 protocol = (int)str_gnum(st[++sp]);
995#ifdef TAINT
996 taintproper("Insecure dependency in socket");
997#endif
998 fd = socket(domain,type,protocol);
999 if (fd < 0)
1000 return FALSE;
1001 stio->ifp = fdopen(fd, "r"); /* stdio gets confused about sockets */
1002 stio->ofp = fdopen(fd, "w");
1003 stio->type = 's';
1004
1005 return TRUE;
1006}
1007
1008int
1009do_bind(stab, arglast)
1010STAB *stab;
1011int *arglast;
1012{
1013 register STR **st = stack->ary_array;
1014 register int sp = arglast[1];
1015 register STIO *stio;
1016 char *addr;
1017
1018 if (!stab)
1019 goto nuts;
1020
1021 stio = stab_io(stab);
1022 if (!stio || !stio->ifp)
1023 goto nuts;
1024
1025 addr = str_get(st[++sp]);
1026#ifdef TAINT
1027 taintproper("Insecure dependency in bind");
1028#endif
1029 return bind(fileno(stio->ifp), addr, st[sp]->str_cur) >= 0;
1030
1031nuts:
1032 if (dowarn)
1033 warn("bind() on closed fd");
1034 return FALSE;
1035
1036}
1037
1038int
1039do_connect(stab, arglast)
1040STAB *stab;
1041int *arglast;
1042{
1043 register STR **st = stack->ary_array;
1044 register int sp = arglast[1];
1045 register STIO *stio;
1046 char *addr;
1047
1048 if (!stab)
1049 goto nuts;
1050
1051 stio = stab_io(stab);
1052 if (!stio || !stio->ifp)
1053 goto nuts;
1054
1055 addr = str_get(st[++sp]);
1056#ifdef TAINT
1057 taintproper("Insecure dependency in connect");
1058#endif
1059 return connect(fileno(stio->ifp), addr, st[sp]->str_cur) >= 0;
1060
1061nuts:
1062 if (dowarn)
1063 warn("connect() on closed fd");
1064 return FALSE;
1065
1066}
1067
1068int
1069do_listen(stab, arglast)
1070STAB *stab;
1071int *arglast;
1072{
1073 register STR **st = stack->ary_array;
1074 register int sp = arglast[1];
1075 register STIO *stio;
1076 int backlog;
1077
1078 if (!stab)
1079 goto nuts;
1080
1081 stio = stab_io(stab);
1082 if (!stio || !stio->ifp)
1083 goto nuts;
1084
1085 backlog = (int)str_gnum(st[++sp]);
1086 return listen(fileno(stio->ifp), backlog) >= 0;
1087
1088nuts:
1089 if (dowarn)
1090 warn("listen() on closed fd");
1091 return FALSE;
1092}
1093
1094void
1095do_accept(str, nstab, gstab)
1096STR *str;
1097STAB *nstab;
1098STAB *gstab;
1099{
1100 register STIO *nstio;
1101 register STIO *gstio;
1102 int len = sizeof buf;
1103 int fd;
1104
1105 if (!nstab)
1106 goto badexit;
1107 if (!gstab)
1108 goto nuts;
1109
1110 gstio = stab_io(gstab);
1111 nstio = stab_io(nstab);
1112
1113 if (!gstio || !gstio->ifp)
1114 goto nuts;
1115 if (!nstio)
1116 nstio = stab_io(nstab) = stio_new();
1117 else if (nstio->ifp)
1118 do_close(nstab,FALSE);
1119
1120 fd = accept(fileno(gstio->ifp),buf,&len);
1121 if (fd < 0)
1122 goto badexit;
1123 nstio->ifp = fdopen(fd, "r");
1124 nstio->ofp = fdopen(fd, "w");
1125 nstio->type = 's';
1126
1127 str_nset(str, buf, len);
1128 return;
1129
1130nuts:
1131 if (dowarn)
1132 warn("accept() on closed fd");
1133badexit:
1134 str_sset(str,&str_undef);
1135 return;
1136}
1137
1138int
1139do_shutdown(stab, arglast)
1140STAB *stab;
1141int *arglast;
1142{
1143 register STR **st = stack->ary_array;
1144 register int sp = arglast[1];
1145 register STIO *stio;
1146 int how;
1147
1148 if (!stab)
1149 goto nuts;
1150
1151 stio = stab_io(stab);
1152 if (!stio || !stio->ifp)
1153 goto nuts;
1154
1155 how = (int)str_gnum(st[++sp]);
1156 return shutdown(fileno(stio->ifp), how) >= 0;
1157
1158nuts:
1159 if (dowarn)
1160 warn("shutdown() on closed fd");
1161 return FALSE;
1162
1163}
1164
1165int
1166do_sopt(optype, stab, arglast)
1167int optype;
1168STAB *stab;
1169int *arglast;
1170{
1171 register STR **st = stack->ary_array;
1172 register int sp = arglast[1];
1173 register STIO *stio;
1174 int fd;
1175 int lvl;
1176 int optname;
1177
1178 if (!stab)
1179 goto nuts;
1180
1181 stio = stab_io(stab);
1182 if (!stio || !stio->ifp)
1183 goto nuts;
1184
1185 fd = fileno(stio->ifp);
1186 lvl = (int)str_gnum(st[sp+1]);
1187 optname = (int)str_gnum(st[sp+2]);
1188 switch (optype) {
1189 case O_GSOCKOPT:
1190 st[sp] = str_2static(str_new(257));
1191 st[sp]->str_cur = 256;
bf38876a 1192 st[sp]->str_pok = 1;
a687059c 1193 if (getsockopt(fd, lvl, optname, st[sp]->str_ptr, &st[sp]->str_cur) < 0)
1194 goto nuts;
1195 break;
1196 case O_SSOCKOPT:
1197 st[sp] = st[sp+3];
1198 if (setsockopt(fd, lvl, optname, st[sp]->str_ptr, st[sp]->str_cur) < 0)
1199 goto nuts;
1200 st[sp] = &str_yes;
1201 break;
1202 }
1203
1204 return sp;
1205
1206nuts:
1207 if (dowarn)
bf38876a 1208 warn("[gs]etsockopt() on closed fd");
a687059c 1209 st[sp] = &str_undef;
1210 return sp;
1211
1212}
1213
1214int
1215do_getsockname(optype, stab, arglast)
1216int optype;
1217STAB *stab;
1218int *arglast;
1219{
1220 register STR **st = stack->ary_array;
1221 register int sp = arglast[1];
1222 register STIO *stio;
1223 int fd;
1224
1225 if (!stab)
1226 goto nuts;
1227
1228 stio = stab_io(stab);
1229 if (!stio || !stio->ifp)
1230 goto nuts;
1231
1232 st[sp] = str_2static(str_new(257));
1233 st[sp]->str_cur = 256;
bf38876a 1234 st[sp]->str_pok = 1;
a687059c 1235 fd = fileno(stio->ifp);
1236 switch (optype) {
1237 case O_GETSOCKNAME:
1238 if (getsockname(fd, st[sp]->str_ptr, &st[sp]->str_cur) < 0)
1239 goto nuts;
1240 break;
1241 case O_GETPEERNAME:
1242 if (getpeername(fd, st[sp]->str_ptr, &st[sp]->str_cur) < 0)
1243 goto nuts;
1244 break;
1245 }
1246
1247 return sp;
1248
1249nuts:
1250 if (dowarn)
bf38876a 1251 warn("get{sock,peer}name() on closed fd");
a687059c 1252 st[sp] = &str_undef;
1253 return sp;
1254
1255}
1256
1257int
1258do_ghent(which,gimme,arglast)
1259int which;
1260int gimme;
1261int *arglast;
1262{
1263 register ARRAY *ary = stack;
1264 register int sp = arglast[0];
1265 register char **elem;
1266 register STR *str;
bf38876a 1267 struct hostent *gethostbyname();
a687059c 1268 struct hostent *gethostbyaddr();
1269#ifdef GETHOSTENT
1270 struct hostent *gethostent();
1271#endif
1272 struct hostent *hent;
1273 unsigned long len;
1274
1275 if (gimme != G_ARRAY) {
1276 astore(ary, ++sp, str_static(&str_undef));
1277 return sp;
1278 }
1279
1280 if (which == O_GHBYNAME) {
1281 char *name = str_get(ary->ary_array[sp+1]);
1282
1283 hent = gethostbyname(name);
1284 }
1285 else if (which == O_GHBYADDR) {
1286 STR *addrstr = ary->ary_array[sp+1];
1287 int addrtype = (int)str_gnum(ary->ary_array[sp+2]);
1288 char *addr = str_get(addrstr);
1289
1290 hent = gethostbyaddr(addr,addrstr->str_cur,addrtype);
1291 }
1292 else
1293#ifdef GETHOSTENT
1294 hent = gethostent();
1295#else
1296 fatal("gethostent not implemented");
1297#endif
1298 if (hent) {
1299#ifndef lint
1300 (void)astore(ary, ++sp, str = str_static(&str_no));
1301 str_set(str, hent->h_name);
1302 (void)astore(ary, ++sp, str = str_static(&str_no));
1303 for (elem = hent->h_aliases; *elem; elem++) {
1304 str_cat(str, *elem);
1305 if (elem[1])
1306 str_ncat(str," ",1);
1307 }
1308 (void)astore(ary, ++sp, str = str_static(&str_no));
1309 str_numset(str, (double)hent->h_addrtype);
1310 (void)astore(ary, ++sp, str = str_static(&str_no));
1311 len = hent->h_length;
1312 str_numset(str, (double)len);
1313#ifdef h_addr
1314 for (elem = hent->h_addr_list; *elem; elem++) {
1315 (void)astore(ary, ++sp, str = str_static(&str_no));
1316 str_nset(str, *elem, len);
1317 }
1318#else
1319 (void)astore(ary, ++sp, str = str_static(&str_no));
1320 str_nset(str, hent->h_addr, len);
1321#endif /* h_addr */
1322#else /* lint */
1323 elem = Nullch;
1324 elem = elem;
1325 (void)astore(ary, ++sp, str_static(&str_no));
1326#endif /* lint */
1327 }
1328
1329 return sp;
1330}
1331
1332int
1333do_gnent(which,gimme,arglast)
1334int which;
1335int gimme;
1336int *arglast;
1337{
1338 register ARRAY *ary = stack;
1339 register int sp = arglast[0];
1340 register char **elem;
1341 register STR *str;
1342 struct netent *getnetbyname();
1343 struct netent *getnetbyaddr();
1344 struct netent *getnetent();
1345 struct netent *nent;
1346
1347 if (gimme != G_ARRAY) {
1348 astore(ary, ++sp, str_static(&str_undef));
1349 return sp;
1350 }
1351
1352 if (which == O_GNBYNAME) {
1353 char *name = str_get(ary->ary_array[sp+1]);
1354
1355 nent = getnetbyname(name);
1356 }
1357 else if (which == O_GNBYADDR) {
1358 STR *addrstr = ary->ary_array[sp+1];
1359 int addrtype = (int)str_gnum(ary->ary_array[sp+2]);
1360 char *addr = str_get(addrstr);
1361
1362 nent = getnetbyaddr(addr,addrtype);
1363 }
1364 else
1365 nent = getnetent();
1366
1367 if (nent) {
1368#ifndef lint
1369 (void)astore(ary, ++sp, str = str_static(&str_no));
1370 str_set(str, nent->n_name);
1371 (void)astore(ary, ++sp, str = str_static(&str_no));
1372 for (elem = nent->n_aliases; *elem; elem++) {
1373 str_cat(str, *elem);
1374 if (elem[1])
1375 str_ncat(str," ",1);
1376 }
1377 (void)astore(ary, ++sp, str = str_static(&str_no));
1378 str_numset(str, (double)nent->n_addrtype);
1379 (void)astore(ary, ++sp, str = str_static(&str_no));
1380 str_numset(str, (double)nent->n_net);
1381#else /* lint */
1382 elem = Nullch;
1383 elem = elem;
1384 (void)astore(ary, ++sp, str_static(&str_no));
1385#endif /* lint */
1386 }
1387
1388 return sp;
1389}
1390
1391int
1392do_gpent(which,gimme,arglast)
1393int which;
1394int gimme;
1395int *arglast;
1396{
1397 register ARRAY *ary = stack;
1398 register int sp = arglast[0];
1399 register char **elem;
1400 register STR *str;
1401 struct protoent *getprotobyname();
1402 struct protoent *getprotobynumber();
1403 struct protoent *getprotoent();
1404 struct protoent *pent;
1405
1406 if (gimme != G_ARRAY) {
1407 astore(ary, ++sp, str_static(&str_undef));
1408 return sp;
1409 }
1410
1411 if (which == O_GPBYNAME) {
1412 char *name = str_get(ary->ary_array[sp+1]);
1413
1414 pent = getprotobyname(name);
1415 }
1416 else if (which == O_GPBYNUMBER) {
1417 int proto = (int)str_gnum(ary->ary_array[sp+1]);
1418
1419 pent = getprotobynumber(proto);
1420 }
1421 else
1422 pent = getprotoent();
1423
1424 if (pent) {
1425#ifndef lint
1426 (void)astore(ary, ++sp, str = str_static(&str_no));
1427 str_set(str, pent->p_name);
1428 (void)astore(ary, ++sp, str = str_static(&str_no));
1429 for (elem = pent->p_aliases; *elem; elem++) {
1430 str_cat(str, *elem);
1431 if (elem[1])
1432 str_ncat(str," ",1);
1433 }
1434 (void)astore(ary, ++sp, str = str_static(&str_no));
1435 str_numset(str, (double)pent->p_proto);
1436#else /* lint */
1437 elem = Nullch;
1438 elem = elem;
1439 (void)astore(ary, ++sp, str_static(&str_no));
1440#endif /* lint */
1441 }
1442
1443 return sp;
1444}
1445
1446int
1447do_gsent(which,gimme,arglast)
1448int which;
1449int gimme;
1450int *arglast;
1451{
1452 register ARRAY *ary = stack;
1453 register int sp = arglast[0];
1454 register char **elem;
1455 register STR *str;
1456 struct servent *getservbyname();
1457 struct servent *getservbynumber();
1458 struct servent *getservent();
1459 struct servent *sent;
1460
1461 if (gimme != G_ARRAY) {
1462 astore(ary, ++sp, str_static(&str_undef));
1463 return sp;
1464 }
1465
1466 if (which == O_GSBYNAME) {
1467 char *name = str_get(ary->ary_array[sp+1]);
1468 char *proto = str_get(ary->ary_array[sp+2]);
1469
1470 if (proto && !*proto)
1471 proto = Nullch;
1472
1473 sent = getservbyname(name,proto);
1474 }
1475 else if (which == O_GSBYPORT) {
1476 int port = (int)str_gnum(ary->ary_array[sp+1]);
1477 char *proto = str_get(ary->ary_array[sp+2]);
1478
1479 sent = getservbyport(port,proto);
1480 }
1481 else
1482 sent = getservent();
1483 if (sent) {
1484#ifndef lint
1485 (void)astore(ary, ++sp, str = str_static(&str_no));
1486 str_set(str, sent->s_name);
1487 (void)astore(ary, ++sp, str = str_static(&str_no));
1488 for (elem = sent->s_aliases; *elem; elem++) {
1489 str_cat(str, *elem);
1490 if (elem[1])
1491 str_ncat(str," ",1);
1492 }
1493 (void)astore(ary, ++sp, str = str_static(&str_no));
1494#ifdef NTOHS
1495 str_numset(str, (double)ntohs(sent->s_port));
1496#else
1497 str_numset(str, (double)(sent->s_port));
1498#endif
1499 (void)astore(ary, ++sp, str = str_static(&str_no));
1500 str_set(str, sent->s_proto);
1501#else /* lint */
1502 elem = Nullch;
1503 elem = elem;
1504 (void)astore(ary, ++sp, str_static(&str_no));
1505#endif /* lint */
1506 }
1507
1508 return sp;
1509}
1510
1511int
1512do_select(gimme,arglast)
1513int gimme;
1514int *arglast;
1515{
1516 register STR **st = stack->ary_array;
1517 register int sp = arglast[0];
1518 register int i;
1519 register int j;
1520 register char *s;
1521 register STR *str;
1522 double value;
1523 int maxlen = 0;
1524 int nfound;
1525 struct timeval timebuf;
1526 struct timeval *tbuf = &timebuf;
663a0e37 1527 int growsize;
1528#if BYTEORDER != 0x1234 && BYTEORDER != 0x12345678
1529 int masksize;
1530 int offset;
1531 char *fd_sets[4];
1532 int k;
1533
1534#if BYTEORDER & 0xf0000
1535#define ORDERBYTE (0x88888888 - BYTEORDER)
1536#else
1537#define ORDERBYTE (0x4444 - BYTEORDER)
1538#endif
1539
1540#endif
a687059c 1541
1542 for (i = 1; i <= 3; i++) {
663a0e37 1543 j = st[sp+i]->str_cur;
a687059c 1544 if (maxlen < j)
1545 maxlen = j;
1546 }
663a0e37 1547
1548#if BYTEORDER == 0x1234 || BYTEORDER == 0x12345678
1549 growsize = maxlen; /* little endians can use vecs directly */
1550#else
1551#ifdef NFDBITS
1552
1553#ifndef NBBY
1554#define NBBY 8
1555#endif
1556
1557 masksize = NFDBITS / NBBY;
1558#else
1559 masksize = sizeof(long); /* documented int, everyone seems to use long */
1560#endif
1561 growsize = maxlen + (masksize - (maxlen % masksize));
1562 Zero(&fd_sets[0], 4, char*);
1563#endif
1564
a687059c 1565 for (i = 1; i <= 3; i++) {
1566 str = st[sp+i];
1567 j = str->str_len;
663a0e37 1568 if (j < growsize) {
a687059c 1569 if (str->str_pok) {
663a0e37 1570 str_grow(str,growsize);
a687059c 1571 s = str_get(str) + j;
663a0e37 1572 while (++j <= growsize) {
a687059c 1573 *s++ = '\0';
1574 }
1575 }
1576 else if (str->str_ptr) {
1577 Safefree(str->str_ptr);
1578 str->str_ptr = Nullch;
1579 }
1580 }
663a0e37 1581#if BYTEORDER != 0x1234 && BYTEORDER != 0x12345678
1582 s = str->str_ptr;
1583 if (s) {
1584 New(403, fd_sets[i], growsize, char);
1585 for (offset = 0; offset < growsize; offset += masksize) {
1586 for (j = 0, k=ORDERBYTE; j < masksize; j++, (k >>= 4))
1587 fd_sets[i][j+offset] = s[(k % masksize) + offset];
1588 }
1589 }
1590#endif
a687059c 1591 }
1592 str = st[sp+4];
1593 if (str->str_nok || str->str_pok) {
1594 value = str_gnum(str);
1595 if (value < 0.0)
1596 value = 0.0;
1597 timebuf.tv_sec = (long)value;
1598 value -= (double)timebuf.tv_sec;
1599 timebuf.tv_usec = (long)(value * 1000000.0);
1600 }
1601 else
1602 tbuf = Null(struct timeval*);
1603
663a0e37 1604#if BYTEORDER == 0x1234 || BYTEORDER == 0x12345678
a687059c 1605 nfound = select(
1606 maxlen * 8,
1607 st[sp+1]->str_ptr,
1608 st[sp+2]->str_ptr,
1609 st[sp+3]->str_ptr,
1610 tbuf);
663a0e37 1611#else
1612 nfound = select(
1613 maxlen * 8,
1614 fd_sets[1],
1615 fd_sets[2],
1616 fd_sets[3],
1617 tbuf);
1618 for (i = 1; i <= 3; i++) {
1619 if (fd_sets[i]) {
1620 str = st[sp+i];
1621 s = str->str_ptr;
1622 for (offset = 0; offset < growsize; offset += masksize) {
1623 for (j = 0, k=ORDERBYTE; j < masksize; j++, (k >>= 4))
1624 s[(k % masksize) + offset] = fd_sets[i][j+offset];
1625 }
1626 }
1627 }
1628#endif
a687059c 1629
1630 st[++sp] = str_static(&str_no);
1631 str_numset(st[sp], (double)nfound);
1632 if (gimme == G_ARRAY && tbuf) {
1633 value = (double)(timebuf.tv_sec) +
1634 (double)(timebuf.tv_usec) / 1000000.0;
1635 st[++sp] = str_static(&str_no);
1636 str_numset(st[sp], value);
1637 }
1638 return sp;
1639}
1640
1641int
1642do_spair(stab1, stab2, arglast)
1643STAB *stab1;
1644STAB *stab2;
1645int *arglast;
1646{
1647 register STR **st = stack->ary_array;
1648 register int sp = arglast[2];
1649 register STIO *stio1;
1650 register STIO *stio2;
1651 int domain, type, protocol, fd[2];
1652
1653 if (!stab1 || !stab2)
1654 return FALSE;
1655
1656 stio1 = stab_io(stab1);
1657 stio2 = stab_io(stab2);
1658 if (!stio1)
1659 stio1 = stab_io(stab1) = stio_new();
1660 else if (stio1->ifp)
1661 do_close(stab1,FALSE);
1662 if (!stio2)
1663 stio2 = stab_io(stab2) = stio_new();
1664 else if (stio2->ifp)
1665 do_close(stab2,FALSE);
1666
1667 domain = (int)str_gnum(st[++sp]);
1668 type = (int)str_gnum(st[++sp]);
1669 protocol = (int)str_gnum(st[++sp]);
1670#ifdef TAINT
1671 taintproper("Insecure dependency in socketpair");
1672#endif
1673#ifdef SOCKETPAIR
1674 if (socketpair(domain,type,protocol,fd) < 0)
1675 return FALSE;
1676#else
1677 fatal("Socketpair unimplemented");
1678#endif
1679 stio1->ifp = fdopen(fd[0], "r");
1680 stio1->ofp = fdopen(fd[0], "w");
1681 stio1->type = 's';
1682 stio2->ifp = fdopen(fd[1], "r");
1683 stio2->ofp = fdopen(fd[1], "w");
1684 stio2->type = 's';
1685
1686 return TRUE;
1687}
1688
1689#endif /* SOCKET */
1690
1691int
1692do_gpwent(which,gimme,arglast)
1693int which;
1694int gimme;
1695int *arglast;
1696{
1697#ifdef I_PWD
1698 register ARRAY *ary = stack;
1699 register int sp = arglast[0];
1700 register char **elem;
1701 register STR *str;
1702 struct passwd *getpwnam();
1703 struct passwd *getpwuid();
1704 struct passwd *getpwent();
1705 struct passwd *pwent;
1706 unsigned long len;
1707
1708 if (gimme != G_ARRAY) {
1709 astore(ary, ++sp, str_static(&str_undef));
1710 return sp;
1711 }
1712
1713 if (which == O_GPWNAM) {
1714 char *name = str_get(ary->ary_array[sp+1]);
1715
1716 pwent = getpwnam(name);
1717 }
1718 else if (which == O_GPWUID) {
1719 int uid = (int)str_gnum(ary->ary_array[sp+1]);
1720
1721 pwent = getpwuid(uid);
1722 }
1723 else
1724 pwent = getpwent();
1725
1726 if (pwent) {
1727 (void)astore(ary, ++sp, str = str_static(&str_no));
1728 str_set(str, pwent->pw_name);
1729 (void)astore(ary, ++sp, str = str_static(&str_no));
1730 str_set(str, pwent->pw_passwd);
1731 (void)astore(ary, ++sp, str = str_static(&str_no));
1732 str_numset(str, (double)pwent->pw_uid);
1733 (void)astore(ary, ++sp, str = str_static(&str_no));
1734 str_numset(str, (double)pwent->pw_gid);
1735 (void)astore(ary, ++sp, str = str_static(&str_no));
03a14243 1736#ifdef PWCHANGE
1737 str_numset(str, (double)pwent->pw_change);
1738#else
a687059c 1739#ifdef PWQUOTA
1740 str_numset(str, (double)pwent->pw_quota);
1741#else
1742#ifdef PWAGE
1743 str_set(str, pwent->pw_age);
1744#endif
1745#endif
03a14243 1746#endif
a687059c 1747 (void)astore(ary, ++sp, str = str_static(&str_no));
03a14243 1748#ifdef PWCLASS
1749 str_set(str,pwent->pw_class);
1750#else
a687059c 1751 str_set(str, pwent->pw_comment);
03a14243 1752#endif
a687059c 1753 (void)astore(ary, ++sp, str = str_static(&str_no));
1754 str_set(str, pwent->pw_gecos);
1755 (void)astore(ary, ++sp, str = str_static(&str_no));
1756 str_set(str, pwent->pw_dir);
1757 (void)astore(ary, ++sp, str = str_static(&str_no));
1758 str_set(str, pwent->pw_shell);
03a14243 1759#ifdef PWEXPIRE
1760 (void)astore(ary, ++sp, str = str_static(&str_no));
1761 str_numset(str, (double)pwent->pw_expire);
1762#endif
a687059c 1763 }
1764
1765 return sp;
1766#else
1767 fatal("password routines not implemented");
1768#endif
1769}
1770
1771int
1772do_ggrent(which,gimme,arglast)
1773int which;
1774int gimme;
1775int *arglast;
1776{
1777#ifdef I_GRP
1778 register ARRAY *ary = stack;
1779 register int sp = arglast[0];
1780 register char **elem;
1781 register STR *str;
1782 struct group *getgrnam();
1783 struct group *getgrgid();
1784 struct group *getgrent();
1785 struct group *grent;
1786 unsigned long len;
1787
1788 if (gimme != G_ARRAY) {
1789 astore(ary, ++sp, str_static(&str_undef));
1790 return sp;
1791 }
1792
1793 if (which == O_GGRNAM) {
1794 char *name = str_get(ary->ary_array[sp+1]);
1795
1796 grent = getgrnam(name);
1797 }
1798 else if (which == O_GGRGID) {
1799 int gid = (int)str_gnum(ary->ary_array[sp+1]);
1800
1801 grent = getgrgid(gid);
1802 }
1803 else
1804 grent = getgrent();
1805
1806 if (grent) {
1807 (void)astore(ary, ++sp, str = str_static(&str_no));
1808 str_set(str, grent->gr_name);
1809 (void)astore(ary, ++sp, str = str_static(&str_no));
1810 str_set(str, grent->gr_passwd);
1811 (void)astore(ary, ++sp, str = str_static(&str_no));
1812 str_numset(str, (double)grent->gr_gid);
1813 (void)astore(ary, ++sp, str = str_static(&str_no));
1814 for (elem = grent->gr_mem; *elem; elem++) {
1815 str_cat(str, *elem);
1816 if (elem[1])
1817 str_ncat(str," ",1);
1818 }
1819 }
1820
1821 return sp;
1822#else
1823 fatal("group routines not implemented");
1824#endif
1825}
1826
1827int
1828do_dirop(optype,stab,gimme,arglast)
1829int optype;
1830STAB *stab;
1831int gimme;
1832int *arglast;
1833{
0d3e774c 1834#if defined(DIRENT) && defined(READDIR)
a687059c 1835 register ARRAY *ary = stack;
1836 register STR **st = ary->ary_array;
1837 register int sp = arglast[1];
1838 register STIO *stio;
1839 long along;
bf38876a 1840#ifndef telldir
a687059c 1841 long telldir();
bf38876a 1842#endif
a687059c 1843 struct DIRENT *readdir();
1844 register struct DIRENT *dp;
1845
1846 if (!stab)
1847 goto nope;
1848 if (!(stio = stab_io(stab)))
1849 stio = stab_io(stab) = stio_new();
1850 if (!stio->dirp && optype != O_OPENDIR)
1851 goto nope;
1852 st[sp] = &str_yes;
1853 switch (optype) {
1854 case O_OPENDIR:
1855 if (stio->dirp)
1856 closedir(stio->dirp);
1857 if (!(stio->dirp = opendir(str_get(st[sp+1]))))
1858 goto nope;
1859 break;
1860 case O_READDIR:
1861 if (gimme == G_ARRAY) {
1862 --sp;
1863 while (dp = readdir(stio->dirp)) {
1864#ifdef DIRNAMLEN
1865 (void)astore(ary,++sp,
1866 str_2static(str_make(dp->d_name,dp->d_namlen)));
1867#else
1868 (void)astore(ary,++sp,
1869 str_2static(str_make(dp->d_name,0)));
1870#endif
1871 }
1872 }
1873 else {
1874 if (!(dp = readdir(stio->dirp)))
1875 goto nope;
1876 st[sp] = str_static(&str_undef);
1877#ifdef DIRNAMLEN
1878 str_nset(st[sp], dp->d_name, dp->d_namlen);
1879#else
1880 str_set(st[sp], dp->d_name);
1881#endif
1882 }
1883 break;
1884 case O_TELLDIR:
1885 st[sp] = str_static(&str_undef);
1886 str_numset(st[sp], (double)telldir(stio->dirp));
1887 break;
1888 case O_SEEKDIR:
1889 st[sp] = str_static(&str_undef);
1890 along = (long)str_gnum(st[sp+1]);
1891 (void)seekdir(stio->dirp,along);
1892 break;
1893 case O_REWINDDIR:
1894 st[sp] = str_static(&str_undef);
1895 (void)rewinddir(stio->dirp);
1896 break;
1897 case O_CLOSEDIR:
1898 st[sp] = str_static(&str_undef);
1899 (void)closedir(stio->dirp);
1900 stio->dirp = 0;
1901 break;
1902 }
1903 return sp;
1904
1905nope:
1906 st[sp] = &str_undef;
1907 return sp;
1908
1909#else
1910 fatal("Unimplemented directory operation");
1911#endif
1912}
1913
1914apply(type,arglast)
1915int type;
1916int *arglast;
1917{
1918 register STR **st = stack->ary_array;
1919 register int sp = arglast[1];
1920 register int items = arglast[2] - sp;
1921 register int val;
1922 register int val2;
1923 register int tot = 0;
1924 char *s;
1925
1926#ifdef TAINT
1927 for (st += ++sp; items--; st++)
1928 tainted |= (*st)->str_tainted;
1929 st = stack->ary_array;
1930 sp = arglast[1];
1931 items = arglast[2] - sp;
1932#endif
1933 switch (type) {
1934 case O_CHMOD:
1935#ifdef TAINT
1936 taintproper("Insecure dependency in chmod");
1937#endif
1938 if (--items > 0) {
1939 tot = items;
1940 val = (int)str_gnum(st[++sp]);
1941 while (items--) {
1942 if (chmod(str_get(st[++sp]),val))
1943 tot--;
1944 }
1945 }
1946 break;
1947 case O_CHOWN:
1948#ifdef TAINT
1949 taintproper("Insecure dependency in chown");
1950#endif
1951 if (items > 2) {
1952 items -= 2;
1953 tot = items;
1954 val = (int)str_gnum(st[++sp]);
1955 val2 = (int)str_gnum(st[++sp]);
1956 while (items--) {
1957 if (chown(str_get(st[++sp]),val,val2))
1958 tot--;
1959 }
1960 }
1961 break;
1962 case O_KILL:
1963#ifdef TAINT
1964 taintproper("Insecure dependency in kill");
1965#endif
1966 if (--items > 0) {
1967 tot = items;
1968 s = str_get(st[++sp]);
1969 if (isupper(*s)) {
1970 if (*s == 'S' && s[1] == 'I' && s[2] == 'G')
1971 s += 3;
1972 if (!(val = whichsig(s)))
1973 fatal("Unrecognized signal name \"%s\"",s);
1974 }
1975 else
1976 val = (int)str_gnum(st[sp]);
1977 if (val < 0) {
1978 val = -val;
1979 while (items--) {
1980 int proc = (int)str_gnum(st[++sp]);
1981#ifdef KILLPG
1982 if (killpg(proc,val)) /* BSD */
1983#else
1984 if (kill(-proc,val)) /* SYSV */
1985#endif
1986 tot--;
1987 }
1988 }
1989 else {
1990 while (items--) {
1991 if (kill((int)(str_gnum(st[++sp])),val))
1992 tot--;
1993 }
1994 }
1995 }
1996 break;
1997 case O_UNLINK:
1998#ifdef TAINT
1999 taintproper("Insecure dependency in unlink");
2000#endif
2001 tot = items;
2002 while (items--) {
2003 s = str_get(st[++sp]);
2004 if (euid || unsafe) {
2005 if (UNLINK(s))
2006 tot--;
2007 }
2008 else { /* don't let root wipe out directories without -U */
0d3e774c 2009#ifdef LSTAT
a687059c 2010 if (lstat(s,&statbuf) < 0 ||
2011#else
2012 if (stat(s,&statbuf) < 0 ||
2013#endif
2014 (statbuf.st_mode & S_IFMT) == S_IFDIR )
2015 tot--;
2016 else {
2017 if (UNLINK(s))
2018 tot--;
2019 }
2020 }
2021 }
2022 break;
2023 case O_UTIME:
2024#ifdef TAINT
2025 taintproper("Insecure dependency in utime");
2026#endif
2027 if (items > 2) {
663a0e37 2028#ifdef I_UTIME
2029 struct utimbuf utbuf;
2030#else
a687059c 2031 struct {
663a0e37 2032 long actime;
2033 long modtime;
a687059c 2034 } utbuf;
663a0e37 2035#endif
a687059c 2036
afd9f252 2037 Zero(&utbuf, sizeof utbuf, char);
663a0e37 2038 utbuf.actime = (long)str_gnum(st[++sp]); /* time accessed */
2039 utbuf.modtime = (long)str_gnum(st[++sp]); /* time modified */
a687059c 2040 items -= 2;
2041#ifndef lint
2042 tot = items;
2043 while (items--) {
2044 if (utime(str_get(st[++sp]),&utbuf))
2045 tot--;
2046 }
2047#endif
2048 }
2049 else
2050 items = 0;
2051 break;
2052 }
2053 return tot;
2054}
2055
2056/* Do the permissions allow some operation? Assumes statcache already set. */
2057
2058int
2059cando(bit, effective, statbufp)
2060int bit;
2061int effective;
2062register struct stat *statbufp;
2063{
2064 if ((effective ? euid : uid) == 0) { /* root is special */
2065 if (bit == S_IEXEC) {
2066 if (statbufp->st_mode & 0111 ||
2067 (statbufp->st_mode & S_IFMT) == S_IFDIR )
2068 return TRUE;
2069 }
2070 else
2071 return TRUE; /* root reads and writes anything */
2072 return FALSE;
2073 }
2074 if (statbufp->st_uid == (effective ? euid : uid) ) {
2075 if (statbufp->st_mode & bit)
2076 return TRUE; /* ok as "user" */
2077 }
2078 else if (ingroup((int)statbufp->st_gid,effective)) {
2079 if (statbufp->st_mode & bit >> 3)
2080 return TRUE; /* ok as "group" */
2081 }
2082 else if (statbufp->st_mode & bit >> 6)
2083 return TRUE; /* ok as "other" */
2084 return FALSE;
2085}
2086
2087int
2088ingroup(testgid,effective)
2089int testgid;
2090int effective;
2091{
2092 if (testgid == (effective ? egid : gid))
2093 return TRUE;
2094#ifdef GETGROUPS
2095#ifndef NGROUPS
2096#define NGROUPS 32
2097#endif
2098 {
2099 GIDTYPE gary[NGROUPS];
2100 int anum;
2101
2102 anum = getgroups(NGROUPS,gary);
2103 while (--anum >= 0)
2104 if (gary[anum] == testgid)
2105 return TRUE;
2106 }
2107#endif
2108 return FALSE;
2109}