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