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