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