Retire old subvers file
[dragonfly.git] / contrib / tcsh / tc.os.c
1 /* $Header: /src/pub/tcsh/tc.os.c,v 3.53 2002/03/08 17:36:47 christos Exp $ */
2 /*
3  * tc.os.c: OS Dependent builtin functions
4  */
5 /*-
6  * Copyright (c) 1980, 1991 The Regents of the University of California.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33 #include "sh.h"
34
35 RCSID("$Id: tc.os.c,v 3.53 2002/03/08 17:36:47 christos Exp $")
36
37 #include "tw.h"
38 #include "ed.h"
39 #include "ed.defns.h"           /* for the function names */
40 #include "sh.decls.h"
41
42 #ifdef _UWIN
43 #define TIOCGPGRP TIOCGETPGRP
44 #define TIOCSPGRP TIOCSETPGRP
45 #endif
46
47 /***
48  *** MACH
49  ***/
50
51 #ifdef MACH
52 /* dosetpath -- setpath built-in command
53  *
54  **********************************************************************
55  * HISTORY
56  * 08-May-88  Richard Draves (rpd) at Carnegie-Mellon University
57  *      Major changes to remove artificial limits on sizes and numbers
58  *      of paths.
59  *
60  **********************************************************************
61  */
62
63 #ifdef MACH
64 static Char STRCPATH[] = {'C', 'P', 'A', 'T', 'H', '\0'};
65 static Char STRLPATH[] = {'L', 'P', 'A', 'T', 'H', '\0'};
66 static Char STRMPATH[] = {'M', 'P', 'A', 'T', 'H', '\0'};
67 # if EPATH
68 static Char STREPATH[] = {'E', 'P', 'A', 'T', 'H', '\0'};
69 # endif
70 #endif /* MACH */
71 static Char *syspaths[] = {STRKPATH, STRCPATH, STRLPATH, STRMPATH, 
72
73 #if EPATH
74         STREPATH,
75 #endif
76          0};
77 #define LOCALSYSPATH    "/usr/local"
78
79 /*ARGSUSED*/
80 void
81 dosetpath(arglist, c)
82     Char  **arglist;
83     struct command *c;
84 {
85     extern char *getenv();
86     sigmask_t omask;
87     Char  **pathvars, **cmdargs;
88     char  **spaths, **cpaths, **cmds;
89     char   *tcp;
90     unsigned int npaths, ncmds;
91     int     i, sysflag;
92
93     omask = sigsetmask(sigmask(SIGINT));
94
95     /*
96      * setpath(3) uses stdio and we want 0, 1, 2 to work...
97      */
98     if (!didfds) {
99         (void) dcopy(SHIN, 0);
100         (void) dcopy(SHOUT, 1);
101         (void) dcopy(SHDIAG, 2);
102         didfds = 1;
103     }
104
105     for (i = 1; arglist[i] && (arglist[i][0] != '-'); i++);
106     npaths = i - 1;
107
108     cmdargs = &arglist[i];
109     for (; arglist[i]; i++);
110     ncmds = i - npaths - 1;
111
112     if (npaths) {
113         sysflag = 0;
114         pathvars = &arglist[1];
115     }
116     else {
117         sysflag = 1;
118         npaths = (sizeof syspaths / sizeof *syspaths) - 1;
119         pathvars = syspaths;
120     }
121
122     /* note that npaths != 0 */
123
124     spaths = (char **) xmalloc((size_t) npaths * sizeof *spaths);
125     setzero((char *) spaths, npaths * sizeof *spaths);
126     cpaths = (char **) xmalloc((size_t) (npaths + 1) * sizeof *cpaths);
127     setzero((char *) cpaths, (npaths + 1) * sizeof *cpaths);
128     cmds = (char **) xmalloc((size_t) (ncmds + 1) * sizeof *cmds);
129     setzero((char *) cmds, (ncmds + 1) * sizeof *cmds);
130     for (i = 0; i < npaths; i++) {
131         char   *val = getenv(short2str(pathvars[i]));
132
133         if (val == NULL)
134             val = "";
135
136         spaths[i] = (char *) xmalloc((size_t) (Strlen(pathvars[i]) +
137                                       strlen(val) + 2) * sizeof **spaths);
138         (void) strcpy(spaths[i], short2str(pathvars[i]));
139         (void) strcat(spaths[i], "=");
140         (void) strcat(spaths[i], val);
141         cpaths[i] = spaths[i];
142     }
143
144     for (i = 0; i < ncmds; i++) {
145         Char   *val = globone(cmdargs[i], G_ERROR);
146
147         if (val == NULL)
148             goto abortpath;
149         cmds[i] = (char *) xmalloc((size_t) Strlen(val) + 1);
150         (void) strcpy(cmds[i], short2str(val));
151     }
152
153
154     if (setpath(cpaths, cmds, LOCALSYSPATH, sysflag, 1) < 0) {
155 abortpath:
156         if (spaths) {
157             for (i = 0; i < npaths; i++)
158                 if (spaths[i])
159                     xfree((ptr_t) spaths[i]);
160             xfree((ptr_t) spaths);
161         }
162         if (cpaths)
163             xfree((ptr_t) cpaths);
164         if (cmds) {
165             for (i = 0; i < ncmds; i++)
166                 if (cmds[i])
167                     xfree((ptr_t) cmds[i]);
168             xfree((ptr_t) cmds);
169         }
170
171         (void) sigsetmask(omask);
172         donefds();
173         return;
174     }
175
176     for (i = 0; i < npaths; i++) {
177         Char    *val, *name;
178
179         name = str2short(cpaths[i]);
180         for (val = str2short(cpaths[i]); val && *val && *val != '='; val++);
181         if (val && *val == '=') {
182             *val++ = '\0';
183
184             tsetenv(name, val);
185             if (Strcmp(name, STRKPATH) == 0) {
186                 importpath(val);
187                 if (havhash)
188                     dohash(NULL, NULL);
189             }
190             *--val = '=';
191         }
192     }
193     (void) sigsetmask(omask);
194     donefds();
195 }
196 #endif /* MACH */
197
198 /***
199  *** AIX
200  ***/
201 #ifdef TCF
202 /* ARGSUSED */
203 void
204 dogetxvers(v, c)
205     Char  **v;
206     struct command *c;
207 {
208     char    xvers[MAXPATHLEN];
209
210     if (getxvers(xvers, MAXPATHLEN) == -1)
211         stderror(ERR_SYSTEM, "getxvers", strerror(errno));
212     xprintf("%s\n", xvers);
213     flush();
214 }
215
216 /*ARGSUSED*/
217 void
218 dosetxvers(v, c)
219     Char  **v;
220     struct command *c;
221 {
222     char   *xvers;
223
224     ++v;
225     if (!*v || *v[0] == '\0')
226         xvers = "";
227     else
228         xvers = short2str(*v);
229     if (setxvers(xvers) == -1)
230         stderror(ERR_SYSTEM, "setxvers", strerror(errno));
231 }
232
233 #include <sf.h>
234 #ifdef _AIXPS2
235 # define XC_PDP11       0x01
236 # define XC_23          0x02
237 # define XC_Z8K         0x03
238 # define XC_8086        0x04
239 # define XC_68K         0x05
240 # define XC_Z80         0x06
241 # define XC_VAX         0x07
242 # define XC_16032       0x08
243 # define XC_286         0x09
244 # define XC_386         0x0a
245 # define XC_S370        0x0b
246 #else
247 # include <sys/x.out.h>
248 #endif /* _AIXPS2 */
249
250 static struct xc_cpu_t {
251     short   xc_id;
252     char   *xc_name;
253 }       xcpu[] =
254 {
255     { XC_PDP11, "pdp11"   },
256     { XC_23,    "i370"    },
257     { XC_Z8K,   "z8000"   },
258     { XC_8086,  "i86"     },
259     { XC_68K,   "mc68000" },
260     { XC_Z80,   "x80"     },
261     { XC_VAX,   "vax"     },
262     { XC_16032, "ns16032" },
263     { XC_286,   "i286"    },
264     { XC_386,   "i386"    },
265     { XC_S370,  "xa370"   },
266     { 0,        NULL      }
267 };
268
269 /*
270  * our local hack table, stolen from x.out.h
271  */
272 static char *
273 getxcode(xcid)
274     short   xcid;
275 {
276     int     i;
277
278     for (i = 0; xcpu[i].xc_name != NULL; i++)
279         if (xcpu[i].xc_id == xcid)
280             return (xcpu[i].xc_name);
281     return (NULL);
282 }
283
284 static short
285 getxid(xcname)
286     char   *xcname;
287 {
288     int     i;
289
290     for (i = 0; xcpu[i].xc_name != NULL; i++)
291         if (strcmp(xcpu[i].xc_name, xcname) == 0)
292             return (xcpu[i].xc_id);
293     return ((short) -1);
294 }
295
296
297 /*ARGSUSED*/
298 void
299 dogetspath(v, c)
300     Char  **v;
301     struct command *c;
302 {
303     int     i, j;
304     sitepath_t p[MAXSITE];
305     struct sf *st;
306     static char *local = "LOCAL ";
307
308     if ((j = getspath(p, MAXSITE)) == -1)
309         stderror(ERR_SYSTEM, "getspath", strerror(errno));
310     for (i = 0; i < j && (p[i] & SPATH_CPU) != NOSITE; i++) {
311         if (p[i] & SPATH_CPU) {
312             if ((p[i] & SPATH_MASK) == NULLSITE)
313                 xprintf(local);
314             else if ((st = sfxcode((short) (p[i] & SPATH_MASK))) != NULL)
315                 xprintf("%s ", st->sf_ctype);
316             else {
317                 char   *xc = getxcode(p[i] & SPATH_MASK);
318
319                 if (xc != NULL)
320                     xprintf("%s ", xc);
321                 else
322                     xprintf("*cpu %d* ", (int) (p[i] & SPATH_MASK));
323                 /* 
324                  * BUG in the aix code... needs that cause if
325                  * sfxcode fails once it fails for ever 
326                  */
327                 endsf();        
328             }
329         }
330         else {
331             if (p[i] == NULLSITE)
332                 xprintf(local);
333             else if ((st = sfnum(p[i])) != NULL)
334                 xprintf("%s ", st->sf_sname);
335             else
336                 xprintf("*site %d* ", (int) (p[i] & SPATH_MASK));
337         }
338     }
339     xputchar('\n');
340     flush();
341 }
342
343 /*ARGSUSED*/
344 void
345 dosetspath(v, c)
346     Char  **v;
347     struct command *c;
348 {
349     int     i;
350     short   j;
351     char   *s;
352     sitepath_t p[MAXSITE];
353     struct sf *st;
354
355     /*
356      * sfname() on AIX G9.9 at least, mallocs too pointers p, q
357      * then does the equivalent of while (*p++ == *q++) continue;
358      * and then tries to free(p,q) them! Congrats to the wizard who
359      * wrote that one. I bet he tested it really well too.
360      * Sooo, we set dont_free :-)
361      */
362     dont_free = 1;
363     for (i = 0, v++; *v && *v[0] != '\0'; v++, i++) {
364         s = short2str(*v);
365         if (Isdigit(*s))
366             p[i] = atoi(s);
367         else if (strcmp(s, "LOCAL") == 0)
368             p[i] = NULLSITE;
369         else if ((st = sfctype(s)) != NULL)
370             p[i] = SPATH_CPU | st->sf_ccode;
371         else if ((j = getxid(s)) != -1)
372             p[i] = SPATH_CPU | j;
373         else if ((st = sfname(s)) != NULL)
374             p[i] = st->sf_id;
375         else {
376             setname(s);
377             stderror(ERR_NAME | ERR_STRING, CGETS(23, 1, "Bad cpu/site name"));
378         }
379         if (i == MAXSITE - 1)
380             stderror(ERR_NAME | ERR_STRING, CGETS(23, 2, "Site path too long"));
381     }
382     if (setspath(p, i) == -1)
383         stderror(ERR_SYSTEM, "setspath", strerror(errno));
384     dont_free = 0;
385 }
386
387 /* sitename():
388  *      Return the site name where the process is running
389  */
390 char   *
391 sitename(pid)
392     pid_t   pid;
393 {
394     siteno_t ss;
395     struct sf *st;
396
397     if ((ss = site(pid)) == -1 || (st = sfnum(ss)) == NULL)
398         return CGETS(23, 3, "unknown");
399     else
400         return st->sf_sname;
401 }
402
403 static int
404 migratepid(pid, new_site)
405     pid_t   pid;
406     siteno_t new_site;
407 {
408     struct sf *st;
409     int     need_local;
410
411     need_local = (pid == 0) || (pid == getpid());
412
413     if (kill3((pid_t) pid, SIGMIGRATE, new_site) < 0) {
414         xprintf("%d: %s\n", pid, strerror(errno));
415         return (-1);
416     }
417
418     if (need_local) {
419         if ((new_site = site(0)) == -1) {
420             xprintf(CGETS(23, 4, "site: %s\n"), strerror(errno));
421             return (-1);
422         }
423         if ((st = sfnum(new_site)) == NULL) {
424             xprintf(CGETS(23, 5, "%d: Site not found\n"), new_site);
425             return (-1);
426         }
427         if (setlocal(st->sf_local, strlen(st->sf_local)) == -1) {
428             xprintf(CGETS(23, 6, "setlocal: %s: %s\n"),
429                           st->sf_local, strerror(errno));
430             return (-1);
431         }
432     }
433     return (0);
434 }
435
436 /*ARGSUSED*/
437 void
438 domigrate(v, c)
439     Char  **v;
440     struct command *c;
441 {
442     struct sf *st;
443     char   *s;
444     Char   *cp;
445     struct process *pp;
446     int    err1 = 0;
447     int    pid = 0;
448     siteno_t new_site = 0;
449     sigmask_t omask;
450
451 #ifdef BSDSIGS
452     omask = sigmask(SIGCHLD);
453     if (setintr)
454         omask |= sigmask(SIGINT);
455     omask = sigblock(omask) & ~omask;
456 #else
457     if (setintr)
458         (void) sighold(SIGINT);
459     (void) sighold(SIGCHLD);
460 #endif /* BSDSIGS */
461
462     ++v;
463     if (*v[0] == '-') {
464         /*
465          * Do the -site.
466          */
467         s = short2str(&v[0][1]);
468         /*
469          * see comment in setspath()
470          */
471         dont_free = 1;
472         if ((st = sfname(s)) == NULL) {
473             setname(s);
474             stderror(ERR_NAME | ERR_STRING, CGETS(23, 7, "Site not found"));
475         }
476         dont_free = 0;
477         new_site = st->sf_id;
478         ++v;
479     }
480
481     if (!*v || *v[0] == '\0') {
482         if (migratepid(0, new_site) == -1)
483             err1++;
484     }
485     else {
486         gflag = 0, tglob(v);
487         if (gflag) {
488             v = globall(v);
489             if (v == 0)
490                 stderror(ERR_NAME | ERR_NOMATCH);
491         }
492         else {
493             v = gargv = saveblk(v);
494             trim(v);
495         }
496
497         while (v && (cp = *v)) {
498             if (*cp == '%') {
499                 pp = pfind(cp);
500                 if (kill3((pid_t) - pp->p_jobid, SIGMIGRATE, new_site) < 0) {
501                     xprintf("%S: %s\n", cp, strerror(errno));
502                     err1++;
503                 }
504             }
505             else if (!(Isdigit(*cp) || *cp == '-'))
506                 stderror(ERR_NAME | ERR_JOBARGS);
507             else {
508                 pid = atoi(short2str(cp));
509                 if (migratepid(pid, new_site) == -1)
510                     err1++;
511             }
512             v++;
513         }
514         if (gargv)
515             blkfree(gargv), gargv = 0;
516     }
517
518 done:
519 #ifdef BSDSIGS
520     (void) sigsetmask(omask);
521 #else
522     (void) sigrelse(SIGCHLD);
523     if (setintr)
524         (void) sigrelse(SIGINT);
525 #endif /* BSDSIGS */
526     if (err1)
527         stderror(ERR_SILENT);
528 }
529
530 #endif /* TCF */
531
532 /***
533  *** CRAY ddmode <velo@sesun3.epfl.ch> (Martin Ouwehand EPFL-SIC/SE)
534  ***/
535 #if defined(_CRAY) && !defined(_CRAYMPP)
536 void
537 dodmmode(v, c)
538     Char  **v;
539     struct command *c;
540 {
541     Char *cp = v[1];
542
543     USE(c);
544
545     if ( !cp ) {
546         int mode;
547
548         mode = dmmode(0);
549         dmmode(mode);
550         xprintf("%d\n",mode);
551     }
552     else {
553         if (cp[1] != '\0')
554             stderror(ERR_NAME | ERR_STRING, 
555                      CGETS(23, 30, "Too many arguments"));
556         else
557             switch(*cp) {
558             case '0':
559                 dmmode(0);
560                 break;
561             case '1':
562                 dmmode(1);
563                 break;
564             default:
565                 stderror(ERR_NAME | ERR_STRING, 
566                          CGETS(23, 31, "Invalid argument"));
567             }
568     }
569 }
570 #endif /* _CRAY && !_CRAYMPP */
571
572
573 /***
574  *** CONVEX Warps.
575  ***/
576
577 #ifdef WARP
578 /*
579  * handle the funky warping of symlinks
580  */
581 #include <warpdb.h>
582 #include <sys/warp.h>
583
584 static jmp_buf sigsys_buf;
585
586 static  sigret_t
587 catch_sigsys()
588 {
589     longjmp(sigsys_buf, 1);
590 }
591
592
593 /*ARGSUSED*/
594 void
595 dowarp(v, c)
596     Char  **v;
597     struct command *c;
598 {
599     int     warp, oldwarp;
600     struct warpent *we;
601     void    (*old_sigsys_handler) () = 0;
602     char   *newwarp;
603
604     if (setjmp(sigsys_buf)) {
605         signal(SIGSYS, old_sigsys_handler);
606         stderror(ERR_NAME | ERR_STRING, 
607                  CGETS(23, 8, "You're trapped in a universe you never made"));
608         return;
609     }
610     old_sigsys_handler = signal(SIGSYS, catch_sigsys);
611
612     warp = getwarp();
613
614     v++;
615     if (*v == 0) {              /* display warp value */
616         if (warp < 0)
617             stderror(ERR_NAME | ERR_STRING, CGETS(23, 9, "Getwarp failed"));
618         we = getwarpbyvalue(warp);
619         if (we)
620             printf("%s\n", we->w_name);
621         else
622             printf("%d\n", warp);
623     }
624     else {                      /* set warp value */
625         oldwarp = warp;
626         newwarp = short2str(*v);
627         if (Isdigit(*v[0]))
628             warp = atoi(newwarp);
629         else {
630             we = getwarpbyname(newwarp);
631             if (we)
632                 warp = we->w_value;
633             else
634                 warp = -1;
635         }
636         if ((warp < 0) || (warp >= WARP_MAXLINK))
637             stderror(ERR_NAME | ERR_STRING, CGETS(23, 10, "Invalid warp"));
638         if ((setwarp(warp) < 0) || (getwarp() != warp)) {
639             (void) setwarp(oldwarp);
640             stderror(ERR_NAME | ERR_STRING, CGETS(23, 11, "Setwarp failed"));
641         }
642     }
643     signal(SIGSYS, old_sigsys_handler);
644     return;
645 }
646 #endif /* WARP */
647
648 /***
649  *** Masscomp or HCX
650  ***/
651 /* Added, DAS DEC-90. */
652 #if defined(masscomp) || defined(_CX_UX)
653 /*ARGSUSED*/
654 void
655 douniverse(v, c)
656     register Char **v;
657     struct command *c;
658 {
659     register Char *cp = v[1];
660     register Char *cp2;         /* dunno how many elements v comes in with */
661     char    ubuf[100];
662 #ifdef BSDSIGS
663     register sigmask_t omask = 0;
664 #endif /* BSDSIGS */
665
666     if (cp == 0) {
667         (void) getuniverse(ubuf);
668         xprintf("%s\n", ubuf);
669     }
670     else {
671         cp2 = v[2];
672         if (cp2 == 0) {
673             if (*cp == '\0' || setuniverse(short2str(cp)) != 0)
674                 stderror(ERR_NAME | ERR_STRING, CGETS(23, 12, "Illegal universe"));
675             }
676         else {
677             (void) getuniverse(ubuf);
678             if (*cp == '\0' || setuniverse(short2str(cp)) != 0)
679         stderror(ERR_NAME | ERR_STRING, CGETS(23, 12, "Illegal universe"));
680             if (setintr)
681 #ifdef BSDSIGS
682                 omask = sigblock(sigmask(SIGINT)) & ~sigmask(SIGINT);
683 #else /* !BSDSIGS */
684                 (void) sighold(SIGINT);
685 #endif /* BSDSIGS */
686             lshift(v, 2);
687             if (setintr)
688 #ifdef BSDSIGS
689                 (void) sigsetmask(omask);
690 #else /* !BSDSIGS */
691                 (void) sigrelse (SIGINT);
692 #endif /* BSDSIGS */
693             reexecute(c);
694             (void) setuniverse(ubuf);
695         }
696     }
697 }
698 #endif /* masscomp || _CX_UX */
699
700 #if defined(_CX_UX)
701 /*ARGSUSED*/
702 void
703 doatt(v, c)
704     register Char **v;
705     struct command *c;
706 {
707     register Char *cp = v[1];
708     char    ubuf[100];
709 #ifdef BSDSIGS
710     register sigmask_t omask = 0;
711 #endif /* BSDSIGS */
712
713     if (cp == 0)
714         (void) setuniverse("att");
715     else {
716         (void) getuniverse(ubuf);
717         (void) setuniverse("att");
718         if (setintr)
719 #ifdef BSDSIGS
720             omask = sigblock(sigmask(SIGINT)) & ~sigmask(SIGINT);
721 #else /* !BSDSIGS */
722             (void) sighold(SIGINT);
723 #endif /* BSDSIGS */
724         lshift(v, 1);
725         if (setintr)
726 #ifdef BSDSIGS
727             (void) sigsetmask(omask);
728 #else /* !BSDSIGS */
729             (void) sigrelse (SIGINT);
730 #endif /* BSDSIGS */
731         reexecute(c);
732         (void) setuniverse(ubuf);
733     }
734 }
735
736 /*ARGSUSED*/
737 void
738 doucb(v, c)
739     register Char **v;
740     struct command *c;
741 {
742     register Char *cp = v[1];
743     char    ubuf[100];
744 #ifdef BSDSIGS
745     register sigmask_t omask = 0;
746 #endif /* BSDSIGS */
747
748     if (cp == 0)
749         (void) setuniverse("ucb");
750     else {
751         (void) getuniverse(ubuf);
752         (void) setuniverse("ucb");
753         if (setintr)
754 #ifdef BSDSIGS
755             omask = sigblock(sigmask(SIGINT)) & ~sigmask(SIGINT);
756 #else /* !BSDSIGS */
757             (void) sighold(SIGINT);
758 #endif /* BSDSIGS */
759         lshift(v, 1);
760         if (setintr)
761 #ifdef BSDSIGS
762             (void) sigsetmask(omask);
763 #else /* !BSDSIGS */
764             (void) sigrelse (SIGINT);
765 #endif /* BSDSIGS */
766         reexecute(c);
767         (void) setuniverse(ubuf);
768     }
769 }
770 #endif /* _CX_UX */
771
772 #ifdef _SEQUENT_
773 /*
774  * Compute the difference in process stats.
775  */
776 void
777 pr_stat_sub(p2, p1, pr)
778     struct process_stats *p2, *p1, *pr;
779 {
780     pr->ps_utime.tv_sec = p2->ps_utime.tv_sec - p1->ps_utime.tv_sec;
781     pr->ps_utime.tv_usec = p2->ps_utime.tv_usec - p1->ps_utime.tv_usec;
782     if (pr->ps_utime.tv_usec < 0) {
783         pr->ps_utime.tv_sec -= 1;
784         pr->ps_utime.tv_usec += 1000000;
785     }
786     pr->ps_stime.tv_sec = p2->ps_stime.tv_sec - p1->ps_stime.tv_sec;
787     pr->ps_stime.tv_usec = p2->ps_stime.tv_usec - p1->ps_stime.tv_usec;
788     if (pr->ps_stime.tv_usec < 0) {
789         pr->ps_stime.tv_sec -= 1;
790         pr->ps_stime.tv_usec += 1000000;
791     }
792
793     pr->ps_maxrss = p2->ps_maxrss - p1->ps_maxrss;
794     pr->ps_pagein = p2->ps_pagein - p1->ps_pagein;
795     pr->ps_reclaim = p2->ps_reclaim - p1->ps_reclaim;
796     pr->ps_zerofill = p2->ps_zerofill - p1->ps_zerofill;
797     pr->ps_pffincr = p2->ps_pffincr - p1->ps_pffincr;
798     pr->ps_pffdecr = p2->ps_pffdecr - p1->ps_pffdecr;
799     pr->ps_swap = p2->ps_swap - p1->ps_swap;
800     pr->ps_syscall = p2->ps_syscall - p1->ps_syscall;
801     pr->ps_volcsw = p2->ps_volcsw - p1->ps_volcsw;
802     pr->ps_involcsw = p2->ps_involcsw - p1->ps_involcsw;
803     pr->ps_signal = p2->ps_signal - p1->ps_signal;
804     pr->ps_lread = p2->ps_lread - p1->ps_lread;
805     pr->ps_lwrite = p2->ps_lwrite - p1->ps_lwrite;
806     pr->ps_bread = p2->ps_bread - p1->ps_bread;
807     pr->ps_bwrite = p2->ps_bwrite - p1->ps_bwrite;
808     pr->ps_phread = p2->ps_phread - p1->ps_phread;
809     pr->ps_phwrite = p2->ps_phwrite - p1->ps_phwrite;
810 }
811
812 #endif /* _SEQUENT_ */
813
814
815 #ifdef NEEDmemset
816 /* This is a replacement for a missing memset function */
817 ptr_t xmemset(loc, value, len)
818     ptr_t loc;
819     int len;
820     size_t value;
821 {
822     char *ptr = (char *) loc;
823   
824     while (len--)
825         *ptr++ = value;
826     return loc;
827 }
828 #endif /* NEEDmemset */
829
830
831 #ifdef NEEDmemmove
832 /* memmove():
833  *      This is the ANSI form of bcopy() with the arguments backwards...
834  *      Unlike memcpy(), it handles overlaps between source and 
835  *      destination memory
836  */
837 ptr_t
838 xmemmove(vdst, vsrc, len)
839     ptr_t vdst;
840     const ptr_t vsrc;
841     size_t len;
842 {
843     const char *src = (const char *) vsrc;
844     char *dst = (char *) vdst;
845
846     if (src == dst)
847         return vdst;
848
849     if (src > dst) {
850         while (len--) 
851             *dst++ = *src++;
852     }
853     else {
854         src += len;
855         dst += len;
856         while (len--) 
857             *--dst = *--src;
858     }
859     return vdst;
860 }
861 #endif /* NEEDmemmove */
862
863
864 #ifndef WINNT_NATIVE
865 #ifdef tcgetpgrp
866 int
867 xtcgetpgrp(fd)
868     int     fd;
869 {
870     int     pgrp;
871
872     /* ioctl will handle setting errno correctly. */
873     if (ioctl(fd, TIOCGPGRP, (ioctl_t) & pgrp) < 0)
874         return (-1);
875     return (pgrp);
876 }
877
878 /*
879  * XXX: tcsetpgrp is not a macro any more cause on some systems,
880  * pid_t is a short, but the ioctl() takes a pointer to int (pyr)
881  * Thanks to Simon Day (simon@pharaoh.cyborg.bt.co.uk) for pointing
882  * this out.
883  */
884 int
885 xtcsetpgrp(fd, pgrp)
886     int fd, pgrp;
887 {
888     return ioctl(fd, TIOCSPGRP, (ioctl_t) &pgrp);
889 }
890
891 #endif  /* tcgetpgrp */
892 #endif /* WINNT_NATIVE */
893
894
895 #ifdef YPBUGS
896 void
897 fix_yp_bugs()
898 {
899     char   *mydomain;
900
901     extern int yp_get_default_domain __P((char **));
902     /*
903      * PWP: The previous version assumed that yp domain was the same as the
904      * internet name domain.  This isn't allways true. (Thanks to Mat Landau
905      * <mlandau@bbn.com> for the original version of this.)
906      */
907     if (yp_get_default_domain(&mydomain) == 0) {        /* if we got a name */
908         extern void yp_unbind __P((const char *));
909
910         yp_unbind(mydomain);
911     }
912 }
913
914 #endif /* YPBUGS */
915
916 #ifdef STRCOLLBUG
917 void
918 fix_strcoll_bug()
919 {
920 #if defined(NLS) && !defined(NOSTRCOLL)
921     /*
922      * SunOS4 checks the file descriptor from openlocale() for <= 0
923      * instead of == -1. Someone should tell sun that file descriptor 0
924      * is valid! Our portable hack: open one so we call it with 0 used...
925      * We have to call this routine every time the locale changes...
926      *
927      * Of course it also tries to free the constant locale "C" it initially
928      * had allocated, with the sequence 
929      * > setenv LANG "fr"
930      * > ls^D
931      * > unsetenv LANG
932      * But we are smarter than that and just print a warning message.
933      */
934     int fd = -1;
935     static char *root = "/";
936
937     if (!didfds)
938         fd = open(root, O_RDONLY);
939
940     (void) strcoll(root, root);
941
942     if (fd != -1)
943         (void) close(fd);
944 #endif
945 }
946 #endif /* STRCOLLBUG */
947
948
949 #ifdef OREO
950 #include <compat.h>
951 #endif /* OREO */
952
953 void
954 osinit()
955 {
956 #ifdef OREO
957     set42sig();
958     setcompat(getcompat() & ~COMPAT_EXEC);
959     sigignore(SIGIO);           /* ignore SIGIO */
960 #endif /* OREO */
961
962 #ifdef aiws
963     {
964         struct sigstack inst;
965         inst.ss_sp = (char *) xmalloc((size_t) 4192) + 4192;
966         inst.ss_onstack = 0;
967         sigstack(&inst, NULL);
968     }
969 #endif /* aiws */
970
971 #ifdef apollo
972     (void) isapad();
973 #endif
974
975 #ifdef _SX
976     /* 
977      * kill(SIGCONT) problems, don't know what this syscall does
978      * [schott@rzg.mpg.de]
979      */
980     syscall(151, getpid(), getpid());
981 #endif /* _SX */
982 }
983
984 #ifdef strerror
985 char *
986 xstrerror(i)
987     int i;
988 {
989     static char errbuf[128];
990
991     if (i >= 0 && i < sys_nerr) {
992         return sys_errlist[i];
993     } else {
994         (void) xsnprintf(errbuf, sizeof(errbuf),
995             CGETS(23, 13, "Unknown Error: %d"), i);
996         return errbuf;
997     }
998 }
999 #endif /* strerror */
1000     
1001 #ifdef gethostname
1002 # if !defined(_MINIX) && !defined(__EMX__) && !defined(WINNT_NATIVE)
1003 #  include <sys/utsname.h>
1004 # endif /* !_MINIX && !__EMX__ && !WINNT_NATIVE */
1005
1006 int
1007 xgethostname(name, namlen)
1008     char   *name;
1009     int     namlen;
1010 {
1011 # if !defined(_MINIX) && !defined(__EMX__) && !defined(WINNT_NATIVE)
1012     int     i, retval;
1013     struct utsname uts;
1014
1015     retval = uname(&uts);
1016
1017 #  ifdef DEBUG
1018     xprintf(CGETS(23, 14, "sysname:  %s\n"), uts.sysname);
1019     xprintf(CGETS(23, 15, "nodename: %s\n"), uts.nodename);
1020     xprintf(CGETS(23, 16, "release:  %s\n"), uts.release);
1021     xprintf(CGETS(23, 17, "version:  %s\n"), uts.version);
1022     xprintf(CGETS(23, 18, "machine:  %s\n"), uts.machine);
1023 #  endif /* DEBUG */
1024     i = strlen(uts.nodename) + 1;
1025     (void) strncpy(name, uts.nodename, i < namlen ? i : namlen);
1026
1027     return retval;
1028 # else /* !_MINIX && !__EMX__ */
1029     if (namlen > 0) {
1030 #  ifdef __EMX__
1031         (void) strncpy(name, "OS/2", namlen);
1032 #  else /* _MINIX */
1033         (void) strncpy(name, "minix", namlen);
1034 #  endif /* __EMX__ */
1035         name[namlen-1] = '\0';
1036     }
1037     return(0);
1038 #endif /* _MINIX && !__EMX__ */
1039 } /* end xgethostname */
1040 #endif /* gethostname */
1041
1042 #ifdef nice
1043 # if defined(_MINIX) && defined(NICE)
1044 #  undef _POSIX_SOURCE  /* redefined in <lib.h> */
1045 #  undef _MINIX         /* redefined in <lib.h> */
1046 #  undef HZ             /* redefined in <minix/const.h> */
1047 #  include <lib.h>
1048 # endif /* _MINIX && NICE */
1049 int 
1050 xnice(incr)
1051     int incr;
1052 {
1053 #if defined(_MINIX) && defined(NICE)
1054     return callm1(MM, NICE, incr, 0, 0, NIL_PTR, NIL_PTR, NIL_PTR);
1055 #else
1056     return /* incr ? 0 : */ 0;
1057 #endif /* _MINIX && NICE */
1058 } /* end xnice */
1059 #endif /* nice */
1060
1061 #ifdef NEEDgetcwd
1062 static char *strnrcpy __P((char *, char *, size_t));
1063
1064 /* xgetcwd():
1065  *      Return the pathname of the current directory, or return
1066  *      an error message in pathname.
1067  */
1068
1069 # ifdef hp9000s500
1070 /*
1071  *  From: Bernd Mohr <mohr@faui77.informatik.uni-erlangen.de>
1072  *  I also ported the tcsh to the HP9000 Series 500. This computer
1073  *  is a little bit different than the other HP 9000 computer. It has
1074  *  a HP Chip instead of a Motorola CPU and it is no "real" UNIX. It runs
1075  *  HP-UX which is emulated in top of a HP operating system. So, the last
1076  *  supported version of HP-UX is 5.2 on the HP9000s500. This has two
1077  *  consequences: it supports no job control and it has a filesystem
1078  *  without "." and ".." !!!
1079  */
1080 char *
1081 xgetcwd(pathname, pathlen)
1082     char *pathname;
1083     size_t pathlen;
1084 {
1085     char pathbuf[MAXNAMLEN];    /* temporary pathname buffer */
1086     char *pnptr = &pathbuf[(sizeof pathbuf)-1]; /* pathname pointer */
1087     dev_t rdev;                 /* root device number */
1088     DIR *dirp = NULL;           /* directory stream */
1089     ino_t rino;                 /* root inode number */
1090     off_t rsize;                /* root size */
1091     struct direct *dir;         /* directory entry struct */
1092     struct stat d, dd;          /* file status struct */
1093     int serrno;
1094
1095     *pnptr = '\0';
1096     (void) stat("/.", &d);
1097     rdev = d.st_dev;
1098     rino = d.st_ino;
1099     rsize = d.st_size;
1100     for (;;) {
1101         if (stat(".", &d) == -1) {
1102             (void) xsnprintf(pathname, pathlen, CGETS(23, 24,
1103                 "getcwd: Cannot stat \".\" (%s)"), strerror(errno));
1104             goto fail;
1105         }
1106         if (d.st_ino == rino && d.st_dev == rdev && d.st_size == rsize)
1107             break;              /* reached root directory */
1108         if ((dirp = opendir("..")) == NULL) {
1109             (void) xsnprintf(pathname, pathlen, CGETS(23, 19,
1110                 "getcwd: Cannot open \"..\" (%s)"), strerror(errno));
1111             goto fail;
1112         }
1113         if (chdir("..") == -1) {
1114             (void) xsnprintf(pathname, pathlen, CGETS(23, 20,
1115                 "getcwd: Cannot chdir to \"..\" (%s)"), strerror(errno));
1116             goto fail;
1117         }
1118         do {
1119             if ((dir = readdir(dirp)) == NULL) {
1120                 (void) xsnprintf(pathname, pathlen, 
1121                     CGETS(23, 21, "getcwd: Read error in \"..\" (%s)"),
1122                     strerror(errno));
1123                 goto fail;
1124             }
1125             if (stat(dir->d_name, &dd) == -1) {
1126                 (void) xsnprintf(pathname, pathlen,
1127                     CGETS(23, 25, "getcwd: Cannot stat directory \"%s\" (%s)"),
1128                     dir->d_name, strerror(errno));
1129                 goto fail;
1130             }
1131         } while (dd.st_ino  != d.st_ino  ||
1132                  dd.st_dev  != d.st_dev  ||
1133                  dd.st_size != d.st_size);
1134         (void) closedir(dirp);
1135         dirp = NULL;
1136         pnptr = strnrcpy(dirp->d_name, pnptr, pnptr - pathbuf);
1137         pnptr = strnrcpy("/", pnptr, pnptr - pathbuf);
1138     }
1139
1140     if (*pnptr == '\0')         /* current dir == root dir */
1141         (void) strncpy(pathname, "/", pathlen);
1142     else {
1143         (void) strncpy(pathname, pnptr, pathlen);
1144         pathname[pathlen - 1] = '\0';
1145         if (chdir(pnptr) == -1) {
1146             (void) xsnprintf(pathname, MAXPATHLEN, CGETS(23, 22,
1147                     "getcwd: Cannot change back to \".\" (%s)"),
1148                     strerror(errno));
1149             return NULL;
1150         }
1151     }
1152     return pathname;
1153
1154 fail:
1155     serrno = errno;
1156     (void) chdir(strnrcpy(".", pnptr, pnptr - pathbuf));
1157     errno = serrno;
1158     return NULL;
1159 }
1160
1161 # else /* ! hp9000s500 */
1162
1163 #  if (SYSVREL != 0 && !defined(d_fileno)) || defined(_VMS_POSIX) || defined(WINNT) || defined(_MINIX_VMD)
1164 #   define d_fileno d_ino
1165 #  endif
1166
1167 char *
1168 xgetcwd(pathname, pathlen)
1169     char   *pathname;
1170     size_t pathlen;
1171 {
1172     DIR    *dp;
1173     struct dirent *d;
1174
1175     struct stat st_root, st_cur, st_next, st_dotdot;
1176     char    pathbuf[MAXPATHLEN], nextpathbuf[MAXPATHLEN * 2];
1177     char   *pathptr, *nextpathptr, *cur_name_add;
1178     int    save_errno = 0;
1179
1180     /* find the inode of root */
1181     if (stat("/", &st_root) == -1) {
1182         (void) xsnprintf(pathname, pathlen, CGETS(23, 23, 
1183                         "getcwd: Cannot stat \"/\" (%s)"),
1184                         strerror(errno));
1185         return NULL;
1186     }
1187     pathbuf[MAXPATHLEN - 1] = '\0';
1188     pathptr = &pathbuf[MAXPATHLEN - 1];
1189     nextpathbuf[MAXPATHLEN - 1] = '\0';
1190     cur_name_add = nextpathptr = &nextpathbuf[MAXPATHLEN - 1];
1191
1192     /* find the inode of the current directory */
1193     if (lstat(".", &st_cur) == -1) {
1194         (void) xsnprintf(pathname, pathlen, CGETS(23, 24,
1195                          "getcwd: Cannot stat \".\" (%s)"),
1196                          strerror(errno));
1197         return NULL;
1198     }
1199     nextpathptr = strnrcpy(nextpathptr, "../", nextpathptr - nextpathbuf);
1200
1201     /* Descend to root */
1202     for (;;) {
1203
1204         /* look if we found root yet */
1205         if (st_cur.st_ino == st_root.st_ino &&
1206             DEV_DEV_COMPARE(st_cur.st_dev, st_root.st_dev)) {
1207             (void) strncpy(pathname, *pathptr != '/' ? "/" : pathptr, pathlen);
1208             pathname[pathlen - 1] = '\0';
1209             return pathname;
1210         }
1211
1212         /* open the parent directory */
1213         if (stat(nextpathptr, &st_dotdot) == -1) {
1214             (void) xsnprintf(pathname, pathlen, CGETS(23, 25,
1215                              "getcwd: Cannot stat directory \"%s\" (%s)"),
1216                              nextpathptr, strerror(errno));
1217             return NULL;
1218         }
1219         if ((dp = opendir(nextpathptr)) == NULL) {
1220             (void) xsnprintf(pathname, pathlen, CGETS(23, 26,
1221                              "getcwd: Cannot open directory \"%s\" (%s)"),
1222                              nextpathptr, strerror(errno));
1223             return NULL;
1224         }
1225
1226         /* look in the parent for the entry with the same inode */
1227         if (DEV_DEV_COMPARE(st_dotdot.st_dev, st_cur.st_dev)) {
1228             /* Parent has same device. No need to stat every member */
1229             for (d = readdir(dp); d != NULL; d = readdir(dp)) {
1230 #ifdef __clipper__
1231                 if (((unsigned long)d->d_fileno & 0xffff) == st_cur.st_ino)
1232                     break;
1233 #else
1234                 if (d->d_fileno == st_cur.st_ino)
1235                     break;
1236 #endif
1237             }
1238         }
1239         else {
1240             /* 
1241              * Parent has a different device. This is a mount point so we 
1242              * need to stat every member 
1243              */
1244             for (d = readdir(dp); d != NULL; d = readdir(dp)) {
1245                 if (ISDOT(d->d_name) || ISDOTDOT(d->d_name))
1246                     continue;
1247                 (void)strncpy(cur_name_add, d->d_name,
1248                     (size_t) (&nextpathbuf[sizeof(nextpathbuf) - 1] - cur_name_add));
1249                 if (lstat(nextpathptr, &st_next) == -1) {
1250                     /*
1251                      * We might not be able to stat() some path components
1252                      * if we are using afs, but this is not an error as
1253                      * long as we find the one we need; we also save the
1254                      * first error to report it if we don't finally succeed.
1255                      */
1256                     if (save_errno == 0)
1257                         save_errno = errno;
1258                     continue;
1259                 }
1260                 /* check if we found it yet */
1261                 if (st_next.st_ino == st_cur.st_ino &&
1262                     DEV_DEV_COMPARE(st_next.st_dev, st_cur.st_dev)) 
1263                     break;
1264             }
1265         }
1266         if (d == NULL) {
1267             (void) xsnprintf(pathname, pathlen, CGETS(23, 27,
1268                              "getcwd: Cannot find \".\" in \"..\" (%s)"),
1269                              strerror(save_errno ? save_errno : ENOENT));
1270             (void) closedir(dp);
1271             return NULL;
1272         }
1273         else
1274             save_errno = 0;
1275         st_cur = st_dotdot;
1276         pathptr = strnrcpy(pathptr, d->d_name, pathptr - pathbuf);
1277         pathptr = strnrcpy(pathptr, "/", pathptr - pathbuf);
1278         nextpathptr = strnrcpy(nextpathptr, "../", nextpathptr - nextpathbuf);
1279         *cur_name_add = '\0';
1280         (void) closedir(dp);
1281     }
1282 } /* end getcwd */
1283 # endif /* hp9000s500 */
1284
1285 /* strnrcpy():
1286  *      Like strncpy, going backwards and returning the new pointer
1287  */
1288 static char *
1289 strnrcpy(ptr, str, siz)
1290     register char *ptr, *str;
1291     size_t siz;
1292 {
1293     register int len = strlen(str);
1294     if (siz == 0)
1295         return ptr;
1296
1297     while (len && siz--)
1298         *--ptr = str[--len];
1299
1300     return (ptr);
1301 } /* end strnrcpy */
1302 #endif /* getcwd */
1303
1304 #ifdef apollo
1305 /***
1306  *** Domain/OS
1307  ***/
1308 #include <apollo/base.h>
1309 #include <apollo/loader.h>
1310 #include <apollo/error.h>
1311
1312
1313 static char *
1314 apperr(st)
1315     status_$t *st;
1316 {
1317     static char buf[BUFSIZE];
1318     short e_subl, e_modl, e_codel;
1319     error_$string_t e_sub, e_mod, e_code;
1320
1321     error_$get_text(*st, e_sub, &e_subl, e_mod, &e_modl, e_code, &e_codel);
1322     e_sub[e_subl] = '\0';
1323     e_code[e_codel] = '\0';
1324     e_mod[e_modl] = '\0';
1325     (void) xsnprintf(buf, sizeof(buf), "%s (%s/%s)", e_code, e_sub, e_mod);
1326
1327     return(buf);
1328 }
1329
1330 static int
1331 llib(s)
1332     Char *s;
1333 {
1334     short len = Strlen(s);
1335     status_$t st;
1336     char *t;
1337
1338     loader_$inlib(t = short2str(s), len, &st);
1339     if (st.all != status_$ok) 
1340         stderror(ERR_SYSTEM, t, apperr(&st));
1341 }
1342
1343 /*ARGSUSED*/
1344 void
1345 doinlib(v, c)
1346     Char **v;
1347     struct command *c;
1348 {
1349     setname(short2str(*v++));
1350     gflag = 0, tglob(v);
1351     if (gflag) {
1352         v = globall(v);
1353         if (v == 0)
1354             stderror(ERR_NAME | ERR_NOMATCH);
1355     }
1356     else {
1357         v = gargv = saveblk(v);
1358         trim(v);
1359     }
1360
1361     while (v && *v) 
1362         llib(*v++);
1363     if (gargv)
1364         blkfree(gargv), gargv = 0;
1365 }
1366
1367 int
1368 getv(v)
1369     Char *v;
1370 {
1371     if (eq(v, STRbsd43))
1372         return(1);
1373     else if (eq(v, STRsys53))
1374         return(0);
1375     else 
1376         stderror(ERR_NAME | ERR_SYSTEM, short2str(v),
1377                  CGETS(23, 28, "Invalid system type"));
1378     /*NOTREACHED*/
1379     return(0);
1380 }
1381
1382 /*ARGSUSED*/
1383 void
1384 dover(v, c)
1385     Char **v;
1386     struct command *c;
1387 {
1388     Char *p;
1389
1390     setname(short2str(*v++));
1391     if (!*v) {
1392         if (!(p = tgetenv(STRSYSTYPE)))
1393             stderror(ERR_NAME | ERR_STRING,
1394                      CGETS(23, 29, "System type is not set"));
1395         xprintf("%S\n", p);
1396     }
1397     else {
1398         tsetenv(STRSYSTYPE, getv(*v) ? STRbsd43 : STRsys53);
1399         dohash(NULL, NULL);
1400     }
1401 }
1402
1403 /*
1404  * Many thanks to rees@citi.umich.edu (Jim Rees) and
1405  *                mathys@ssdt-tempe.sps.mot.com (Yves Mathys)
1406  * For figuring out how to do this... I could have never done
1407  * it without their help.
1408  */
1409 typedef short enum {
1410         name_$wdir_type,
1411         name_$ndir_type,
1412         name_$node_dir_type,
1413 } name_$dir_type_t;
1414
1415 /*ARGSUSED*/
1416 void
1417 dorootnode(v, c)
1418     Char **v;
1419     struct command *c;
1420 {
1421     name_$dir_type_t dirtype = name_$node_dir_type;
1422     uid_$t uid;
1423     status_$t st;
1424     char *name;
1425     short namelen;
1426
1427     setname(short2str(*v++));
1428
1429     name = short2str(*v);
1430     namelen = strlen(name);
1431
1432     name_$resolve(name, &namelen, &uid, &st);
1433     if (st.all != status_$ok) 
1434         stderror(ERR_SYSTEM, name, apperr(&st));
1435     namelen = 0;
1436     name_$set_diru(&uid, "", &namelen, &dirtype, &st);
1437     if (st.all != status_$ok) 
1438         stderror(ERR_SYSTEM, name, apperr(&st));
1439     dohash(NULL, NULL);
1440 }
1441
1442 int
1443 isapad()
1444 {
1445     static int res = -1;
1446     static status_$t st;
1447
1448     if (res == -1) {
1449         int strm;
1450         if (isatty(0))
1451             strm = 0;
1452         if (isatty(1))
1453             strm = 1;
1454         if (isatty(2))
1455             strm = 2;
1456         else {
1457             res = 0;
1458             st.all = status_$ok;
1459             return(res);
1460         }
1461         res = stream_$isavt(&strm, &st);
1462         res = res ? 1 : 0;
1463     }
1464     else {
1465         if (st.all != status_$ok) 
1466             stderror(ERR_SYSTEM, "stream_$isavt", apperr(&st));
1467     }
1468     return(res);
1469 }
1470 #endif