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