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