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