1232633Smp/* $Header: /p/tcsh/cvsroot/tcsh/tc.os.c,v 3.72 2011/01/25 13:58:19 christos Exp $ */
259243Sobrien/*
359243Sobrien * tc.os.c: OS Dependent builtin functions
459243Sobrien */
559243Sobrien/*-
659243Sobrien * Copyright (c) 1980, 1991 The Regents of the University of California.
759243Sobrien * All rights reserved.
859243Sobrien *
959243Sobrien * Redistribution and use in source and binary forms, with or without
1059243Sobrien * modification, are permitted provided that the following conditions
1159243Sobrien * are met:
1259243Sobrien * 1. Redistributions of source code must retain the above copyright
1359243Sobrien *    notice, this list of conditions and the following disclaimer.
1459243Sobrien * 2. Redistributions in binary form must reproduce the above copyright
1559243Sobrien *    notice, this list of conditions and the following disclaimer in the
1659243Sobrien *    documentation and/or other materials provided with the distribution.
17100616Smp * 3. Neither the name of the University nor the names of its contributors
1859243Sobrien *    may be used to endorse or promote products derived from this software
1959243Sobrien *    without specific prior written permission.
2059243Sobrien *
2159243Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2259243Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2359243Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2459243Sobrien * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2559243Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2659243Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2759243Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2859243Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2959243Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3059243Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3159243Sobrien * SUCH DAMAGE.
3259243Sobrien */
3359243Sobrien#include "sh.h"
3459243Sobrien
35232633SmpRCSID("$tcsh: tc.os.c,v 3.72 2011/01/25 13:58:19 christos Exp $")
3659243Sobrien
3759243Sobrien#include "tw.h"
3859243Sobrien#include "ed.h"
3959243Sobrien#include "ed.defns.h"		/* for the function names */
4059243Sobrien#include "sh.decls.h"
4159243Sobrien
4259243Sobrien#ifdef _UWIN
4359243Sobrien#define TIOCGPGRP TIOCGETPGRP
4459243Sobrien#define TIOCSPGRP TIOCSETPGRP
4559243Sobrien#endif
4659243Sobrien
4759243Sobrien/***
4859243Sobrien *** MACH
4959243Sobrien ***/
5059243Sobrien
5159243Sobrien#ifdef MACH
5259243Sobrien/* dosetpath -- setpath built-in command
5359243Sobrien *
5459243Sobrien **********************************************************************
5559243Sobrien * HISTORY
5659243Sobrien * 08-May-88  Richard Draves (rpd) at Carnegie-Mellon University
5759243Sobrien *	Major changes to remove artificial limits on sizes and numbers
5859243Sobrien *	of paths.
5959243Sobrien *
6059243Sobrien **********************************************************************
6159243Sobrien */
6259243Sobrien
6359243Sobrien#ifdef MACH
6459243Sobrienstatic Char STRCPATH[] = {'C', 'P', 'A', 'T', 'H', '\0'};
6559243Sobrienstatic Char STRLPATH[] = {'L', 'P', 'A', 'T', 'H', '\0'};
6659243Sobrienstatic Char STRMPATH[] = {'M', 'P', 'A', 'T', 'H', '\0'};
6759243Sobrien# if EPATH
6859243Sobrienstatic Char STREPATH[] = {'E', 'P', 'A', 'T', 'H', '\0'};
6959243Sobrien# endif
7059243Sobrien#endif /* MACH */
7159243Sobrienstatic Char *syspaths[] = {STRKPATH, STRCPATH, STRLPATH, STRMPATH,
7259243Sobrien
7359243Sobrien#if EPATH
7459243Sobrien	STREPATH,
7559243Sobrien#endif
7659243Sobrien	 0};
7759243Sobrien#define LOCALSYSPATH	"/usr/local"
7859243Sobrien
7959243Sobrien/*ARGSUSED*/
8059243Sobrienvoid
81167465Smpdosetpath(Char **arglist, struct command *c)
8259243Sobrien{
8359243Sobrien    extern char *getenv();
8459243Sobrien    Char  **pathvars, **cmdargs;
8559243Sobrien    char  **spaths, **cpaths, **cmds;
8659243Sobrien    char   *tcp;
8759243Sobrien    unsigned int npaths, ncmds;
8859243Sobrien    int     i, sysflag;
8959243Sobrien
90167465Smp    pintr_disabled++;
91167465Smp    cleanup_push(&pintr_disabled, disabled_cleanup);
9259243Sobrien
9359243Sobrien    /*
9459243Sobrien     * setpath(3) uses stdio and we want 0, 1, 2 to work...
9559243Sobrien     */
9659243Sobrien    if (!didfds) {
9759243Sobrien	(void) dcopy(SHIN, 0);
9859243Sobrien	(void) dcopy(SHOUT, 1);
9959243Sobrien	(void) dcopy(SHDIAG, 2);
10059243Sobrien	didfds = 1;
10159243Sobrien    }
10259243Sobrien
10359243Sobrien    for (i = 1; arglist[i] && (arglist[i][0] != '-'); i++);
10459243Sobrien    npaths = i - 1;
10559243Sobrien
10659243Sobrien    cmdargs = &arglist[i];
10759243Sobrien    for (; arglist[i]; i++);
10859243Sobrien    ncmds = i - npaths - 1;
10959243Sobrien
11059243Sobrien    if (npaths) {
11159243Sobrien	sysflag = 0;
11259243Sobrien	pathvars = &arglist[1];
11359243Sobrien    }
11459243Sobrien    else {
11559243Sobrien	sysflag = 1;
11659243Sobrien	npaths = (sizeof syspaths / sizeof *syspaths) - 1;
11759243Sobrien	pathvars = syspaths;
11859243Sobrien    }
11959243Sobrien
12059243Sobrien    /* note that npaths != 0 */
12159243Sobrien
122167465Smp    spaths = xmalloc(npaths * sizeof *spaths);
123167465Smp    setzero(spaths, npaths * sizeof *spaths);
124167465Smp    cpaths = xmalloc((npaths + 1) * sizeof *cpaths);
125167465Smp    setzero(cpaths, (npaths + 1) * sizeof *cpaths);
126167465Smp    cmds = xmalloc((ncmds + 1) * sizeof *cmds);
127167465Smp    setzero(cmds, (ncmds + 1) * sizeof *cmds);
12859243Sobrien    for (i = 0; i < npaths; i++) {
12959243Sobrien	char   *val = getenv(short2str(pathvars[i]));
13059243Sobrien
13159243Sobrien	if (val == NULL)
13259243Sobrien	    val = "";
13359243Sobrien
134167465Smp	spaths[i] = xmalloc((Strlen(pathvars[i]) + strlen(val) + 2) *
135167465Smp			    sizeof **spaths);
13659243Sobrien	(void) strcpy(spaths[i], short2str(pathvars[i]));
13759243Sobrien	(void) strcat(spaths[i], "=");
13859243Sobrien	(void) strcat(spaths[i], val);
13959243Sobrien	cpaths[i] = spaths[i];
14059243Sobrien    }
14159243Sobrien
14259243Sobrien    for (i = 0; i < ncmds; i++) {
143167465Smp	Char   *val = globone(cmdargs[i], G_ERROR);/*FIXRESET*/
14459243Sobrien
14559243Sobrien	if (val == NULL)
14659243Sobrien	    goto abortpath;
147167465Smp	cmds[i] = strsave(short2str(val));
14859243Sobrien    }
14959243Sobrien
15059243Sobrien
15159243Sobrien    if (setpath(cpaths, cmds, LOCALSYSPATH, sysflag, 1) < 0) {
15259243Sobrienabortpath:
15359243Sobrien	if (spaths) {
15459243Sobrien	    for (i = 0; i < npaths; i++)
155167465Smp		xfree(spaths[i]);
156167465Smp	    xfree(spaths);
15759243Sobrien	}
158167465Smp	xfree(cpaths);
15959243Sobrien	if (cmds) {
16059243Sobrien	    for (i = 0; i < ncmds; i++)
161167465Smp		xfree(cmds[i]);
162167465Smp	    xfree(cmds);
16359243Sobrien	}
16459243Sobrien
165167465Smp	cleanup_until(&pintr_disabled);
16659243Sobrien	donefds();
16759243Sobrien	return;
16859243Sobrien    }
16959243Sobrien
17059243Sobrien    for (i = 0; i < npaths; i++) {
17159243Sobrien	Char	*val, *name;
17259243Sobrien
17359243Sobrien	name = str2short(cpaths[i]);
17459243Sobrien	for (val = str2short(cpaths[i]); val && *val && *val != '='; val++);
17559243Sobrien	if (val && *val == '=') {
17659243Sobrien	    *val++ = '\0';
17759243Sobrien
178167465Smp	    tsetenv(name, val);/*FIXRESET*/
17959243Sobrien	    if (Strcmp(name, STRKPATH) == 0) {
180167465Smp		importpath(val);/*FIXRESET*/
18159243Sobrien		if (havhash)
182167465Smp		    dohash(NULL, NULL);/*FIXRESET*/
18359243Sobrien	    }
18459243Sobrien	    *--val = '=';
18559243Sobrien	}
18659243Sobrien    }
187167465Smp    cleanup_until(&pintr_disabled);
18859243Sobrien    donefds();
18959243Sobrien}
19059243Sobrien#endif /* MACH */
19159243Sobrien
19259243Sobrien/***
19359243Sobrien *** AIX
19459243Sobrien ***/
19559243Sobrien#ifdef TCF
19659243Sobrien/* ARGSUSED */
19759243Sobrienvoid
198167465Smpdogetxvers(Char **v, struct command *c)
19959243Sobrien{
20059243Sobrien    char    xvers[MAXPATHLEN];
20159243Sobrien
20259243Sobrien    if (getxvers(xvers, MAXPATHLEN) == -1)
20359243Sobrien	stderror(ERR_SYSTEM, "getxvers", strerror(errno));
20459243Sobrien    xprintf("%s\n", xvers);
20559243Sobrien    flush();
20659243Sobrien}
20759243Sobrien
20859243Sobrien/*ARGSUSED*/
20959243Sobrienvoid
210167465Smpdosetxvers(Char **v, struct command *c)
21159243Sobrien{
21259243Sobrien    char   *xvers;
21359243Sobrien
21459243Sobrien    ++v;
21559243Sobrien    if (!*v || *v[0] == '\0')
21659243Sobrien	xvers = "";
21759243Sobrien    else
21859243Sobrien	xvers = short2str(*v);
21959243Sobrien    if (setxvers(xvers) == -1)
22059243Sobrien	stderror(ERR_SYSTEM, "setxvers", strerror(errno));
22159243Sobrien}
22259243Sobrien
22359243Sobrien#include <sf.h>
22459243Sobrien#ifdef _AIXPS2
22559243Sobrien# define XC_PDP11	0x01
22659243Sobrien# define XC_23		0x02
22759243Sobrien# define XC_Z8K		0x03
22859243Sobrien# define XC_8086	0x04
22959243Sobrien# define XC_68K		0x05
23059243Sobrien# define XC_Z80		0x06
23159243Sobrien# define XC_VAX		0x07
23259243Sobrien# define XC_16032	0x08
23359243Sobrien# define XC_286		0x09
23459243Sobrien# define XC_386		0x0a
23559243Sobrien# define XC_S370	0x0b
23659243Sobrien#else
23759243Sobrien# include <sys/x.out.h>
23859243Sobrien#endif /* _AIXPS2 */
23959243Sobrien
24059243Sobrienstatic struct xc_cpu_t {
24159243Sobrien    short   xc_id;
24259243Sobrien    char   *xc_name;
24359243Sobrien}       xcpu[] =
24459243Sobrien{
24559243Sobrien    { XC_PDP11,	"pdp11"   },
24659243Sobrien    { XC_23,	"i370"    },
24759243Sobrien    { XC_Z8K,	"z8000"   },
24859243Sobrien    { XC_8086,	"i86"	  },
24959243Sobrien    { XC_68K,	"mc68000" },
25059243Sobrien    { XC_Z80,	"x80"	  },
25159243Sobrien    { XC_VAX,	"vax"	  },
25259243Sobrien    { XC_16032,	"ns16032" },
25359243Sobrien    { XC_286,	"i286"	  },
25459243Sobrien    { XC_386,	"i386"	  },
25559243Sobrien    { XC_S370,	"xa370"	  },
25659243Sobrien    { 0,	NULL      }
25759243Sobrien};
25859243Sobrien
25959243Sobrien/*
26059243Sobrien * our local hack table, stolen from x.out.h
26159243Sobrien */
26259243Sobrienstatic char *
263167465Smpgetxcode(short xcid)
26459243Sobrien{
26559243Sobrien    int     i;
26659243Sobrien
26759243Sobrien    for (i = 0; xcpu[i].xc_name != NULL; i++)
26859243Sobrien	if (xcpu[i].xc_id == xcid)
26959243Sobrien	    return (xcpu[i].xc_name);
27059243Sobrien    return (NULL);
27159243Sobrien}
27259243Sobrien
27359243Sobrienstatic short
274167465Smpgetxid(char *xcname)
27559243Sobrien{
27659243Sobrien    int     i;
27759243Sobrien
27859243Sobrien    for (i = 0; xcpu[i].xc_name != NULL; i++)
27959243Sobrien	if (strcmp(xcpu[i].xc_name, xcname) == 0)
28059243Sobrien	    return (xcpu[i].xc_id);
28159243Sobrien    return ((short) -1);
28259243Sobrien}
28359243Sobrien
28459243Sobrien
28559243Sobrien/*ARGSUSED*/
28659243Sobrienvoid
287167465Smpdogetspath(Char **v, struct command *c)
28859243Sobrien{
28959243Sobrien    int     i, j;
29059243Sobrien    sitepath_t p[MAXSITE];
29159243Sobrien    struct sf *st;
29259243Sobrien    static char *local = "LOCAL ";
29359243Sobrien
29459243Sobrien    if ((j = getspath(p, MAXSITE)) == -1)
29559243Sobrien	stderror(ERR_SYSTEM, "getspath", strerror(errno));
29659243Sobrien    for (i = 0; i < j && (p[i] & SPATH_CPU) != NOSITE; i++) {
29759243Sobrien	if (p[i] & SPATH_CPU) {
29859243Sobrien	    if ((p[i] & SPATH_MASK) == NULLSITE)
29959243Sobrien		xprintf(local);
30059243Sobrien	    else if ((st = sfxcode((short) (p[i] & SPATH_MASK))) != NULL)
30159243Sobrien		xprintf("%s ", st->sf_ctype);
30259243Sobrien	    else {
30359243Sobrien		char   *xc = getxcode(p[i] & SPATH_MASK);
30459243Sobrien
30559243Sobrien		if (xc != NULL)
30659243Sobrien		    xprintf("%s ", xc);
30759243Sobrien		else
30859243Sobrien		    xprintf("*cpu %d* ", (int) (p[i] & SPATH_MASK));
30959243Sobrien		/*
31059243Sobrien		 * BUG in the aix code... needs that cause if
31159243Sobrien		 * sfxcode fails once it fails for ever
31259243Sobrien		 */
31359243Sobrien		endsf();
31459243Sobrien	    }
31559243Sobrien	}
31659243Sobrien	else {
31759243Sobrien	    if (p[i] == NULLSITE)
31859243Sobrien		xprintf(local);
31959243Sobrien	    else if ((st = sfnum(p[i])) != NULL)
32059243Sobrien		xprintf("%s ", st->sf_sname);
32159243Sobrien	    else
32259243Sobrien		xprintf("*site %d* ", (int) (p[i] & SPATH_MASK));
32359243Sobrien	}
32459243Sobrien    }
32559243Sobrien    xputchar('\n');
32659243Sobrien    flush();
32759243Sobrien}
32859243Sobrien
32959243Sobrien/*ARGSUSED*/
33059243Sobrienvoid
331167465Smpdosetspath(Char **v, struct command *c)
33259243Sobrien{
33359243Sobrien    int     i;
33459243Sobrien    short   j;
33559243Sobrien    char   *s;
33659243Sobrien    sitepath_t p[MAXSITE];
33759243Sobrien    struct sf *st;
33859243Sobrien
33959243Sobrien    /*
34059243Sobrien     * sfname() on AIX G9.9 at least, mallocs too pointers p, q
34159243Sobrien     * then does the equivalent of while (*p++ == *q++) continue;
34259243Sobrien     * and then tries to free(p,q) them! Congrats to the wizard who
34359243Sobrien     * wrote that one. I bet he tested it really well too.
34459243Sobrien     * Sooo, we set dont_free :-)
34559243Sobrien     */
34659243Sobrien    dont_free = 1;
34759243Sobrien    for (i = 0, v++; *v && *v[0] != '\0'; v++, i++) {
34859243Sobrien	s = short2str(*v);
349145479Smp	if (isdigit(*s))
35059243Sobrien	    p[i] = atoi(s);
35159243Sobrien	else if (strcmp(s, "LOCAL") == 0)
35259243Sobrien	    p[i] = NULLSITE;
35359243Sobrien	else if ((st = sfctype(s)) != NULL)
35459243Sobrien	    p[i] = SPATH_CPU | st->sf_ccode;
35559243Sobrien	else if ((j = getxid(s)) != -1)
35659243Sobrien	    p[i] = SPATH_CPU | j;
35759243Sobrien	else if ((st = sfname(s)) != NULL)
35859243Sobrien	    p[i] = st->sf_id;
35959243Sobrien	else {
36059243Sobrien	    setname(s);
36159243Sobrien	    stderror(ERR_NAME | ERR_STRING, CGETS(23, 1, "Bad cpu/site name"));
36259243Sobrien	}
36359243Sobrien	if (i == MAXSITE - 1)
36459243Sobrien	    stderror(ERR_NAME | ERR_STRING, CGETS(23, 2, "Site path too long"));
36559243Sobrien    }
36659243Sobrien    if (setspath(p, i) == -1)
36759243Sobrien	stderror(ERR_SYSTEM, "setspath", strerror(errno));
36859243Sobrien    dont_free = 0;
36959243Sobrien}
37059243Sobrien
37159243Sobrien/* sitename():
37259243Sobrien *	Return the site name where the process is running
37359243Sobrien */
37459243Sobrienchar   *
375167465Smpsitename(pid_t pid)
37659243Sobrien{
37759243Sobrien    siteno_t ss;
37859243Sobrien    struct sf *st;
37959243Sobrien
38059243Sobrien    if ((ss = site(pid)) == -1 || (st = sfnum(ss)) == NULL)
38159243Sobrien	return CGETS(23, 3, "unknown");
38259243Sobrien    else
38359243Sobrien	return st->sf_sname;
38459243Sobrien}
38559243Sobrien
38659243Sobrienstatic int
387167465Smpmigratepid(pit_t pid, siteno_t new_site)
38859243Sobrien{
38959243Sobrien    struct sf *st;
39059243Sobrien    int     need_local;
39159243Sobrien
39259243Sobrien    need_local = (pid == 0) || (pid == getpid());
39359243Sobrien
394167465Smp    if (kill3(pid, SIGMIGRATE, new_site) < 0) {
39559243Sobrien	xprintf("%d: %s\n", pid, strerror(errno));
39659243Sobrien	return (-1);
39759243Sobrien    }
39859243Sobrien
39959243Sobrien    if (need_local) {
40059243Sobrien	if ((new_site = site(0)) == -1) {
40159243Sobrien	    xprintf(CGETS(23, 4, "site: %s\n"), strerror(errno));
40259243Sobrien	    return (-1);
40359243Sobrien	}
40459243Sobrien	if ((st = sfnum(new_site)) == NULL) {
40559243Sobrien	    xprintf(CGETS(23, 5, "%d: Site not found\n"), new_site);
40659243Sobrien	    return (-1);
40759243Sobrien	}
40859243Sobrien	if (setlocal(st->sf_local, strlen(st->sf_local)) == -1) {
40959243Sobrien	    xprintf(CGETS(23, 6, "setlocal: %s: %s\n"),
41059243Sobrien			  st->sf_local, strerror(errno));
41159243Sobrien	    return (-1);
41259243Sobrien	}
41359243Sobrien    }
41459243Sobrien    return (0);
41559243Sobrien}
41659243Sobrien
41759243Sobrien/*ARGSUSED*/
41859243Sobrienvoid
419167465Smpdomigrate(Char **v, struct command *c)
42059243Sobrien{
42159243Sobrien    struct sf *st;
42259243Sobrien    char   *s;
42359243Sobrien    Char   *cp;
42459243Sobrien    struct process *pp;
42559243Sobrien    int    err1 = 0;
42659243Sobrien    int    pid = 0;
42759243Sobrien    siteno_t new_site = 0;
42859243Sobrien
429167465Smp    pchild_disabled++;
430167465Smp    cleanup_push(&pchild_disabled, disabled_cleanup);
431167465Smp    if (setintr) {
432167465Smp	pintr_disabled++;
433167465Smp	cleanup_push(&pintr_disabled, disabled_cleanup);
434167465Smp    }
43559243Sobrien
43659243Sobrien    ++v;
43759243Sobrien    if (*v[0] == '-') {
43859243Sobrien	/*
43959243Sobrien	 * Do the -site.
44059243Sobrien	 */
44159243Sobrien	s = short2str(&v[0][1]);
44259243Sobrien	/*
44359243Sobrien	 * see comment in setspath()
44459243Sobrien	 */
44559243Sobrien	dont_free = 1;
44659243Sobrien	if ((st = sfname(s)) == NULL) {
447167465Smp	    dont_free = 0;
44859243Sobrien	    setname(s);
44959243Sobrien	    stderror(ERR_NAME | ERR_STRING, CGETS(23, 7, "Site not found"));
45059243Sobrien	}
45159243Sobrien	dont_free = 0;
45259243Sobrien	new_site = st->sf_id;
45359243Sobrien	++v;
45459243Sobrien    }
45559243Sobrien
45659243Sobrien    if (!*v || *v[0] == '\0') {
45759243Sobrien	if (migratepid(0, new_site) == -1)
45859243Sobrien	    err1++;
45959243Sobrien    }
46059243Sobrien    else {
461167465Smp	Char **globbed;
46259243Sobrien
463167465Smp	v = glob_all_or_error(v);
464167465Smp	globbed = v;
465167465Smp	cleanup_push(globbed, blk_cleanup);
466167465Smp
46759243Sobrien	while (v && (cp = *v)) {
46859243Sobrien	    if (*cp == '%') {
46959243Sobrien		pp = pfind(cp);
470167465Smp		if (kill3(- pp->p_jobid, SIGMIGRATE, new_site) < 0) {
47159243Sobrien		    xprintf("%S: %s\n", cp, strerror(errno));
47259243Sobrien		    err1++;
47359243Sobrien		}
47459243Sobrien	    }
47559243Sobrien	    else if (!(Isdigit(*cp) || *cp == '-'))
47659243Sobrien		stderror(ERR_NAME | ERR_JOBARGS);
47759243Sobrien	    else {
47859243Sobrien		pid = atoi(short2str(cp));
47959243Sobrien		if (migratepid(pid, new_site) == -1)
48059243Sobrien		    err1++;
48159243Sobrien	    }
48259243Sobrien	    v++;
48359243Sobrien	}
484167465Smp	cleanup_until(globbed);
48559243Sobrien    }
48659243Sobrien
48759243Sobriendone:
488167465Smp    cleanup_until(&pchild_disabled);
48959243Sobrien    if (err1)
49059243Sobrien	stderror(ERR_SILENT);
49159243Sobrien}
49259243Sobrien
49359243Sobrien#endif /* TCF */
49459243Sobrien
49559243Sobrien/***
49659243Sobrien *** CRAY ddmode <velo@sesun3.epfl.ch> (Martin Ouwehand EPFL-SIC/SE)
49759243Sobrien ***/
49859243Sobrien#if defined(_CRAY) && !defined(_CRAYMPP)
49959243Sobrienvoid
500167465Smpdodmmode(Char **v, struct command *c)
50159243Sobrien{
50259243Sobrien    Char *cp = v[1];
50359243Sobrien
50459243Sobrien    USE(c);
50559243Sobrien
50659243Sobrien    if ( !cp ) {
50759243Sobrien	int mode;
50859243Sobrien
50959243Sobrien	mode = dmmode(0);
51059243Sobrien	dmmode(mode);
51159243Sobrien	xprintf("%d\n",mode);
51259243Sobrien    }
51359243Sobrien    else {
51459243Sobrien	if (cp[1] != '\0')
515167465Smp	    stderror(ERR_NAME | ERR_STRING,
51659243Sobrien		     CGETS(23, 30, "Too many arguments"));
51759243Sobrien	else
51859243Sobrien	    switch(*cp) {
51959243Sobrien	    case '0':
52059243Sobrien		dmmode(0);
52159243Sobrien		break;
52259243Sobrien	    case '1':
52359243Sobrien		dmmode(1);
52459243Sobrien		break;
52559243Sobrien	    default:
526167465Smp		stderror(ERR_NAME | ERR_STRING,
52759243Sobrien			 CGETS(23, 31, "Invalid argument"));
52859243Sobrien	    }
52959243Sobrien    }
53059243Sobrien}
53159243Sobrien#endif /* _CRAY && !_CRAYMPP */
53259243Sobrien
53359243Sobrien
53459243Sobrien/***
53559243Sobrien *** CONVEX Warps.
53659243Sobrien ***/
53759243Sobrien
53859243Sobrien#ifdef WARP
53959243Sobrien/*
54059243Sobrien * handle the funky warping of symlinks
54159243Sobrien */
54259243Sobrien#include <warpdb.h>
54359243Sobrien#include <sys/warp.h>
54459243Sobrien
54559243Sobrienstatic jmp_buf sigsys_buf;
54659243Sobrien
547167465Smpstatic void
548167465Smpcatch_sigsys(void)
54959243Sobrien{
550167465Smp    sigset_t set;
551167465Smp    sigemptyset(&set, SIGSYS);
552167465Smp    (void)sigprocmask(SIG_UNBLOCK, &set, NULL);
55359243Sobrien    longjmp(sigsys_buf, 1);
55459243Sobrien}
55559243Sobrien
55659243Sobrien
55759243Sobrien/*ARGSUSED*/
55859243Sobrienvoid
559167465Smpdowarp(Char **v, struct command *c)
56059243Sobrien{
56159243Sobrien    int     warp, oldwarp;
56259243Sobrien    struct warpent *we;
563167465Smp    volatile struct sigaction old_sigsys_handler;
56459243Sobrien    char   *newwarp;
56559243Sobrien
56659243Sobrien    if (setjmp(sigsys_buf)) {
567167465Smp	sigaction(SIGSYS, &old_sigsys_handler, NULL);
568167465Smp	stderror(ERR_NAME | ERR_STRING,
56959243Sobrien		 CGETS(23, 8, "You're trapped in a universe you never made"));
57059243Sobrien	return;
57159243Sobrien    }
572167465Smp    sigaction(SIGSYS, NULL, &old_sigsys_handler);
573167465Smp    signal(SIGSYS, catch_sigsys);
57459243Sobrien
57559243Sobrien    warp = getwarp();
57659243Sobrien
57759243Sobrien    v++;
57859243Sobrien    if (*v == 0) {		/* display warp value */
57959243Sobrien	if (warp < 0)
58059243Sobrien	    stderror(ERR_NAME | ERR_STRING, CGETS(23, 9, "Getwarp failed"));
58159243Sobrien	we = getwarpbyvalue(warp);
58259243Sobrien	if (we)
58359243Sobrien	    printf("%s\n", we->w_name);
58459243Sobrien	else
58559243Sobrien	    printf("%d\n", warp);
58659243Sobrien    }
58759243Sobrien    else {			/* set warp value */
58859243Sobrien	oldwarp = warp;
58959243Sobrien	newwarp = short2str(*v);
59059243Sobrien	if (Isdigit(*v[0]))
59159243Sobrien	    warp = atoi(newwarp);
59259243Sobrien	else {
59359243Sobrien	    we = getwarpbyname(newwarp);
59459243Sobrien	    if (we)
59559243Sobrien		warp = we->w_value;
59659243Sobrien	    else
59759243Sobrien		warp = -1;
59859243Sobrien	}
59959243Sobrien	if ((warp < 0) || (warp >= WARP_MAXLINK))
60059243Sobrien	    stderror(ERR_NAME | ERR_STRING, CGETS(23, 10, "Invalid warp"));
60159243Sobrien	if ((setwarp(warp) < 0) || (getwarp() != warp)) {
60259243Sobrien	    (void) setwarp(oldwarp);
60359243Sobrien	    stderror(ERR_NAME | ERR_STRING, CGETS(23, 11, "Setwarp failed"));
60459243Sobrien	}
60559243Sobrien    }
606167465Smp    sigaction(SIGSYS, &old_sigsys_handler, NULL);
60759243Sobrien}
60859243Sobrien#endif /* WARP */
60959243Sobrien
61059243Sobrien/***
61159243Sobrien *** Masscomp or HCX
61259243Sobrien ***/
61359243Sobrien/* Added, DAS DEC-90. */
61459243Sobrien#if defined(masscomp) || defined(_CX_UX)
615167465Smpstatic void
616167465Smpsetuniverse_cleanup(void *xbuf)
617167465Smp{
618167465Smp    char *buf;
619167465Smp
620167465Smp    buf = xbuf;
621167465Smp    setuniverse(buf);
622167465Smp}
623167465Smp
62459243Sobrien/*ARGSUSED*/
62559243Sobrienvoid
626167465Smpdouniverse(Char **v, struct command *c)
62759243Sobrien{
628145479Smp    Char *cp = v[1];
629145479Smp    Char *cp2;		/* dunno how many elements v comes in with */
63059243Sobrien    char    ubuf[100];
63159243Sobrien
63259243Sobrien    if (cp == 0) {
63359243Sobrien	(void) getuniverse(ubuf);
63459243Sobrien	xprintf("%s\n", ubuf);
63559243Sobrien    }
63659243Sobrien    else {
63759243Sobrien	cp2 = v[2];
63859243Sobrien	if (cp2 == 0) {
63959243Sobrien	    if (*cp == '\0' || setuniverse(short2str(cp)) != 0)
64059243Sobrien		stderror(ERR_NAME | ERR_STRING, CGETS(23, 12, "Illegal universe"));
64159243Sobrien	    }
64259243Sobrien	else {
64359243Sobrien	    (void) getuniverse(ubuf);
64459243Sobrien	    if (*cp == '\0' || setuniverse(short2str(cp)) != 0)
645167465Smp		stderror(ERR_NAME | ERR_STRING, CGETS(23, 12, "Illegal universe"));
646167465Smp	    cleanup_push(ubuf, setuniverse_cleanup);
647167465Smp	    if (setintr) {
648167465Smp		pintr_disabled++;
649167465Smp		cleanup_push(&pintr_disabled, disabled_cleanup);
650167465Smp	    }
65159243Sobrien	    lshift(v, 2);
65259243Sobrien	    if (setintr)
653167465Smp		cleanup_until(&pintr_disabled);
65459243Sobrien	    reexecute(c);
655167465Smp	    cleanup_until(ubuf);
65659243Sobrien	}
65759243Sobrien    }
65859243Sobrien}
65959243Sobrien#endif /* masscomp || _CX_UX */
66059243Sobrien
661131962Smp/***
662131962Smp *** BS2000/OSD POSIX (Fujitsu Siemens Computers)
663131962Smp ***/
664131962Smp#if defined(_OSD_POSIX)
665131962Smpstatic int
666131962Smpbs2upcase(char *str)
667131962Smp{
668131962Smp    enum { outside = ' ', singlequote='\'', doublequote='"'} string = outside;
669131962Smp
670131962Smp    char *white;
671131962Smp
672131962Smp    for (white = str + strlen(str) - 1; isspace(*white) && white > str; --white)
673131962Smp        *white = '\0';
674131962Smp
675131962Smp    for (; *str != '\0'; ++str)
676131962Smp    {
677131962Smp        if (string == outside)
678131962Smp        {
679131962Smp            *str = toupper (*str);
680131962Smp        }
681131962Smp        if (*str == '\'')
682131962Smp        {
683131962Smp            if (string == outside)
684131962Smp                string = singlequote;
685131962Smp            else if (string != doublequote)
686131962Smp                string = outside;
687131962Smp        }
688131962Smp        else if (*str == '"')
689131962Smp        {
690131962Smp            if (string == outside)
691131962Smp                string = doublequote;
692131962Smp            else if (string != singlequote)
693131962Smp                string = outside;
694131962Smp        }
695131962Smp    }
696131962Smp    if (string != outside)
697131962Smp    {
698131962Smp        stderror(ERR_NAME | ERR_UNMATCHED, (Char) string);
699131962Smp        return 1;
700131962Smp    }
701131962Smp    return 0;
702131962Smp}
703131962Smpstatic int
704131962Smpbs2cmdlist(char *str)
705131962Smp{
706131962Smp    char *str_beg = NULL;
707131962Smp    int ret = 0;
708131962Smp
709131962Smp    enum { outside = ' ', singlequote='\'', doublequote='"'} string = outside;
710131962Smp
711131962Smp    while (*str != '\0')
712131962Smp    {
713131962Smp        while (isspace(*str))
714131962Smp            ++str;
715131962Smp
716131962Smp        if (*str == '\0')
717131962Smp            break;
718131962Smp
719131962Smp        str_beg = str;
720131962Smp
721131962Smp        for (; *str != '\0'; ++str)
722131962Smp        {
723131962Smp            if (string == outside && *str == ';') /* End of command */
724131962Smp            {
725131962Smp                *str++ = '\0';
726131962Smp                break;    /* continue with next command */
727131962Smp            }
728131962Smp            if (*str == '\'')
729131962Smp            {
730131962Smp                if (string == outside)
731131962Smp                    string = singlequote;
732131962Smp                else if (string != doublequote)
733131962Smp                    string = outside;
734131962Smp            }
735131962Smp            else if (*str == '"')
736131962Smp            {
737131962Smp                if (string == outside)
738131962Smp                    string = doublequote;
739131962Smp                else if (string != singlequote)
740131962Smp                    string = outside;
741131962Smp            }
742131962Smp        }
743131962Smp        if (strlen(str_beg) != 0)
744131962Smp        {
745131962Smp            ret = bs2system(str_beg);
746131962Smp	    flush();
747131962Smp            if (ret != 0 /*&& !option.err_ignore*/)
748131962Smp                break; /* do not continue after errors */
749131962Smp        }
750131962Smp    }
751131962Smp
752131962Smp    if (string != outside)
753131962Smp    {
754131962Smp        stderror(ERR_NAME | ERR_UNMATCHED, (Char) string);
755131962Smp        return -1;
756131962Smp    }
757131962Smp
758131962Smp    return ret;
759131962Smp}
760131962Smp/*ARGSUSED*/
761131962Smpvoid
762167465Smpdobs2cmd(Char **v, struct command *c)
763131962Smp{
764167465Smp    Char *cp, **globbed;
765145479Smp    int  i = 0, len = 0;
766131962Smp    char *cmd = NULL;
767131962Smp    int     pvec[2];
768131962Smp    struct command faket;
769131962Smp    Char   *fakecom[2];
770131962Smp    char    tibuf[BUFSIZE];
771167465Smp    int     icnt, old_pintr_disabled;
772131962Smp    static const Char STRbs2cmd[] = { 'b','s','2','c','m','d','\0' };
773131962Smp
774167465Smp    v++;
775131962Smp    if (setintr)
776167465Smp	pintr_push_enable(&old_pintr_disabled);
777167465Smp    v = glob_all_or_error(v);
778167465Smp    if (setintr)
779167465Smp	cleanup_until(&old_pintr_disabled);
780167465Smp    globbed = v;
781167465Smp    cleanup_push(globbed, blk_cleanup);
782131962Smp
783131962Smp    /* First round: count the string lengths */
784131962Smp    for (i=0; v[i]; ++i) {
785167465Smp	len += Strlen(v[i]) + (v[i+1] != NULL);
786131962Smp    }
787131962Smp
788167465Smp    cmd = xmalloc(len+1); /* 1 for the final '\0' *//* FIXME: memory leak? */
789131962Smp
790131962Smp    /* 2nd round: fill cmd buffer */
791131962Smp    i = 0;
792131962Smp    while ((cp = *v++) != 0) {
793145479Smp	int c;
794131962Smp	while (c = *cp++)
795131962Smp	    cmd[i++] = (char)c;
796131962Smp        if (*v)
797131962Smp	    cmd[i++] = ' ';
798131962Smp    }
799131962Smp    cmd[i] = '\0';
800131962Smp
801131962Smp    /* Make upper case */
802131962Smp    bs2upcase(cmd);
803131962Smp
804131962Smp    faket.t_dtyp = NODE_COMMAND;
805131962Smp    faket.t_dflg = F_BACKQ|F_STDERR;
806131962Smp    faket.t_dlef = 0;
807131962Smp    faket.t_drit = 0;
808131962Smp    faket.t_dspr = 0;
809131962Smp    faket.t_dcom = fakecom;
810167465Smp    fakecom[0] = (Char *)STRbs2cmd;
811131962Smp    fakecom[1] = 0;
812131962Smp
813131962Smp    mypipe(pvec);
814167465Smp    cleanup_push(&pvec[0], open_cleanup);
815167465Smp    cleanup_push(&pvec[1], open_cleanup);
816131962Smp    if (pfork(&faket, -1) == 0) {
817167465Smp	sigset_t set;
818131962Smp        /* child */
819167465Smp        xclose(pvec[0]);
820131962Smp        (void) dmove(pvec[1], 1);
821131962Smp        (void) dmove(SHDIAG,  2);
822131962Smp        initdesc();
823167465Smp	sigemptyset(&set);
824167465Smp	sigaddset(&set, SIGINT);
825167465Smp	(void)sigprocmask(SIG_UNBLOCK, &set, NULL);
826131962Smp#ifdef SIGTSTP
827167465Smp        signal(SIGTSTP, SIG_IGN);
828131962Smp#endif
829131962Smp#ifdef SIGTTIN
830167465Smp        signal(SIGTTIN, SIG_IGN);
831131962Smp#endif
832131962Smp#ifdef SIGTTOU
833167465Smp        signal(SIGTTOU, SIG_IGN);
834131962Smp#endif
835131962Smp        xexit(bs2cmdlist(cmd));
836131962Smp    }
837167465Smp    cleanup_until(&pvec[1]);
838131962Smp    for(;;) {
839167465Smp	int old_pintr_disabled;
840167465Smp
841167465Smp	if (setintr)
842167465Smp	    pintr_push_enable(&old_pintr_disabled);
843167465Smp	icnt = xread(pvec[0], tibuf, sizeof(tibuf));
844167465Smp	if (setintr)
845167465Smp	    cleanup_until(&old_pintr_disabled);
846131962Smp        if (icnt <= 0)
847131962Smp            break;
848131962Smp        for (i = 0; i < icnt; i++)
849131962Smp            xputchar((unsigned char) tibuf[i]);
850131962Smp    }
851167465Smp    cleanup_until(&pvec[0]);
852131962Smp    pwait();
853131962Smp
854131962Smp    flush();
855131962Smp
856167465Smp    cleanup_until(globbed);
857131962Smp}
858131962Smp#endif /* _OSD_POSIX */
859131962Smp
86059243Sobrien#if defined(_CX_UX)
861167465Smpstatic void
862167465Smpsetuniverse_cleanup(void *xbuf)
863167465Smp{
864167465Smp    char *buf;
865167465Smp
866167465Smp    buf = xbuf;
867167465Smp    setuniverse(buf);
868167465Smp}
869167465Smp
87059243Sobrien/*ARGSUSED*/
87159243Sobrienvoid
872167465Smpdoatt(Char **v, struct command *c)
87359243Sobrien{
874145479Smp    Char *cp = v[1];
87559243Sobrien    char    ubuf[100];
87659243Sobrien
87759243Sobrien    if (cp == 0)
87859243Sobrien	(void) setuniverse("att");
87959243Sobrien    else {
88059243Sobrien	(void) getuniverse(ubuf);
88159243Sobrien	(void) setuniverse("att");
882167465Smp	cleanup_push(ubuf, setuniverse_cleanup);
883167465Smp	if (setintr) {
884167465Smp	    pintr_disabled++;
885167465Smp	    cleanup_push(&pintr_disabled, disabled_cleanup);
886167465Smp	}
88759243Sobrien	lshift(v, 1);
88859243Sobrien	if (setintr)
889167465Smp	    cleanup_until(&pintr_disabled);
89059243Sobrien	reexecute(c);
891167465Smp	cleanup_until(ubuf);
89259243Sobrien    }
89359243Sobrien}
89459243Sobrien
89559243Sobrien/*ARGSUSED*/
89659243Sobrienvoid
897167465Smpdoucb(Char **v, struct command *c)
89859243Sobrien{
899145479Smp    Char *cp = v[1];
90059243Sobrien    char    ubuf[100];
90159243Sobrien
90259243Sobrien    if (cp == 0)
90359243Sobrien	(void) setuniverse("ucb");
90459243Sobrien    else {
90559243Sobrien	(void) getuniverse(ubuf);
90659243Sobrien	(void) setuniverse("ucb");
907167465Smp	cleanup_push(ubuf, setuniverse_cleanup);
908167465Smp	if (setintr) {
909167465Smp	    pintr_disabled++;
910167465Smp	    cleanup_push(&pintr_disabled, disabled_cleanup);
911167465Smp	}
91259243Sobrien	lshift(v, 1);
91359243Sobrien	if (setintr)
914167465Smp	    cleanup_until(&pintr_disabled);
91559243Sobrien	reexecute(c);
916167465Smp	cleanup_until(ubuf);
91759243Sobrien    }
91859243Sobrien}
91959243Sobrien#endif /* _CX_UX */
92059243Sobrien
92159243Sobrien#ifdef _SEQUENT_
92259243Sobrien/*
92359243Sobrien * Compute the difference in process stats.
92459243Sobrien */
92559243Sobrienvoid
926167465Smppr_stat_sub(struct process_stats *p2, struct process_stats *p1,
927167465Smp	    struct process_stats *pr)
92859243Sobrien{
92959243Sobrien    pr->ps_utime.tv_sec = p2->ps_utime.tv_sec - p1->ps_utime.tv_sec;
93059243Sobrien    pr->ps_utime.tv_usec = p2->ps_utime.tv_usec - p1->ps_utime.tv_usec;
93159243Sobrien    if (pr->ps_utime.tv_usec < 0) {
93259243Sobrien	pr->ps_utime.tv_sec -= 1;
93359243Sobrien	pr->ps_utime.tv_usec += 1000000;
93459243Sobrien    }
93559243Sobrien    pr->ps_stime.tv_sec = p2->ps_stime.tv_sec - p1->ps_stime.tv_sec;
93659243Sobrien    pr->ps_stime.tv_usec = p2->ps_stime.tv_usec - p1->ps_stime.tv_usec;
93759243Sobrien    if (pr->ps_stime.tv_usec < 0) {
93859243Sobrien	pr->ps_stime.tv_sec -= 1;
93959243Sobrien	pr->ps_stime.tv_usec += 1000000;
94059243Sobrien    }
94159243Sobrien
94259243Sobrien    pr->ps_maxrss = p2->ps_maxrss - p1->ps_maxrss;
94359243Sobrien    pr->ps_pagein = p2->ps_pagein - p1->ps_pagein;
94459243Sobrien    pr->ps_reclaim = p2->ps_reclaim - p1->ps_reclaim;
94559243Sobrien    pr->ps_zerofill = p2->ps_zerofill - p1->ps_zerofill;
94659243Sobrien    pr->ps_pffincr = p2->ps_pffincr - p1->ps_pffincr;
94759243Sobrien    pr->ps_pffdecr = p2->ps_pffdecr - p1->ps_pffdecr;
94859243Sobrien    pr->ps_swap = p2->ps_swap - p1->ps_swap;
94959243Sobrien    pr->ps_syscall = p2->ps_syscall - p1->ps_syscall;
95059243Sobrien    pr->ps_volcsw = p2->ps_volcsw - p1->ps_volcsw;
95159243Sobrien    pr->ps_involcsw = p2->ps_involcsw - p1->ps_involcsw;
95259243Sobrien    pr->ps_signal = p2->ps_signal - p1->ps_signal;
95359243Sobrien    pr->ps_lread = p2->ps_lread - p1->ps_lread;
95459243Sobrien    pr->ps_lwrite = p2->ps_lwrite - p1->ps_lwrite;
95559243Sobrien    pr->ps_bread = p2->ps_bread - p1->ps_bread;
95659243Sobrien    pr->ps_bwrite = p2->ps_bwrite - p1->ps_bwrite;
95759243Sobrien    pr->ps_phread = p2->ps_phread - p1->ps_phread;
95859243Sobrien    pr->ps_phwrite = p2->ps_phwrite - p1->ps_phwrite;
95959243Sobrien}
96059243Sobrien
96159243Sobrien#endif /* _SEQUENT_ */
96259243Sobrien
96359243Sobrien
964145479Smp#ifndef HAVE_MEMSET
96559243Sobrien/* This is a replacement for a missing memset function */
966167465Smpvoid *xmemset(void *loc, int value, size_t len)
96759243Sobrien{
968167465Smp    char *ptr = loc;
969167465Smp
97059243Sobrien    while (len--)
97159243Sobrien	*ptr++ = value;
97259243Sobrien    return loc;
97359243Sobrien}
974145479Smp#endif /* !HAVE_MEMSET */
97559243Sobrien
97659243Sobrien
977145479Smp#ifndef HAVE_MEMMOVE
97859243Sobrien/* memmove():
97959243Sobrien * 	This is the ANSI form of bcopy() with the arguments backwards...
98059243Sobrien *	Unlike memcpy(), it handles overlaps between source and
98159243Sobrien *	destination memory
98259243Sobrien */
983167465Smpvoid *
984167465Smpxmemmove(void *vdst, const void *vsrc, size_t len)
98559243Sobrien{
986167465Smp    const char *src = vsrc;
987167465Smp    char *dst = vdst;
98859243Sobrien
98959243Sobrien    if (src == dst)
99059243Sobrien	return vdst;
99159243Sobrien
99259243Sobrien    if (src > dst) {
99359243Sobrien	while (len--)
99459243Sobrien	    *dst++ = *src++;
99559243Sobrien    }
99659243Sobrien    else {
99759243Sobrien	src += len;
99859243Sobrien	dst += len;
99959243Sobrien	while (len--)
100059243Sobrien	    *--dst = *--src;
100159243Sobrien    }
100259243Sobrien    return vdst;
100359243Sobrien}
1004145479Smp#endif /* HAVE_MEMMOVE */
100559243Sobrien
100659243Sobrien
100769408Sache#ifndef WINNT_NATIVE
1008145479Smp#ifdef NEEDtcgetpgrp
1009167465Smppid_t
1010167465Smpxtcgetpgrp(int fd)
101159243Sobrien{
101259243Sobrien    int     pgrp;
101359243Sobrien
101459243Sobrien    /* ioctl will handle setting errno correctly. */
101559243Sobrien    if (ioctl(fd, TIOCGPGRP, (ioctl_t) & pgrp) < 0)
101659243Sobrien	return (-1);
101759243Sobrien    return (pgrp);
101859243Sobrien}
101959243Sobrien
102059243Sobrien/*
102159243Sobrien * XXX: tcsetpgrp is not a macro any more cause on some systems,
102259243Sobrien * pid_t is a short, but the ioctl() takes a pointer to int (pyr)
102359243Sobrien * Thanks to Simon Day (simon@pharaoh.cyborg.bt.co.uk) for pointing
102459243Sobrien * this out.
102559243Sobrien */
102659243Sobrienint
1027167465Smpxtcsetpgrp(int fd, int pgrp)
102859243Sobrien{
102959243Sobrien    return ioctl(fd, TIOCSPGRP, (ioctl_t) &pgrp);
103059243Sobrien}
103159243Sobrien
1032145479Smp#endif	/* NEEDtcgetpgrp */
103369408Sache#endif /* WINNT_NATIVE */
103459243Sobrien
103559243Sobrien
103659243Sobrien#ifdef YPBUGS
103759243Sobrienvoid
1038167465Smpfix_yp_bugs(void)
103959243Sobrien{
104059243Sobrien    char   *mydomain;
104159243Sobrien
1042167465Smp    extern int yp_get_default_domain (char **);
104359243Sobrien    /*
104459243Sobrien     * PWP: The previous version assumed that yp domain was the same as the
104559243Sobrien     * internet name domain.  This isn't allways true. (Thanks to Mat Landau
104659243Sobrien     * <mlandau@bbn.com> for the original version of this.)
104759243Sobrien     */
104859243Sobrien    if (yp_get_default_domain(&mydomain) == 0) {	/* if we got a name */
1049167465Smp	extern void yp_unbind (const char *);
105059243Sobrien
105159243Sobrien	yp_unbind(mydomain);
105259243Sobrien    }
105359243Sobrien}
105459243Sobrien
105559243Sobrien#endif /* YPBUGS */
105659243Sobrien
105759243Sobrien#ifdef STRCOLLBUG
105859243Sobrienvoid
1059167465Smpfix_strcoll_bug(void)
106059243Sobrien{
1061167465Smp#if defined(NLS) && defined(HAVE_STRCOLL)
106259243Sobrien    /*
106359243Sobrien     * SunOS4 checks the file descriptor from openlocale() for <= 0
106459243Sobrien     * instead of == -1. Someone should tell sun that file descriptor 0
106559243Sobrien     * is valid! Our portable hack: open one so we call it with 0 used...
106659243Sobrien     * We have to call this routine every time the locale changes...
106759243Sobrien     *
106859243Sobrien     * Of course it also tries to free the constant locale "C" it initially
106959243Sobrien     * had allocated, with the sequence
107059243Sobrien     * > setenv LANG "fr"
107159243Sobrien     * > ls^D
107259243Sobrien     * > unsetenv LANG
107359243Sobrien     * But we are smarter than that and just print a warning message.
107459243Sobrien     */
107559243Sobrien    int fd = -1;
107659243Sobrien    static char *root = "/";
107759243Sobrien
107859243Sobrien    if (!didfds)
1079167465Smp	fd = xopen(root, O_RDONLY|O_LARGEFILE);
108059243Sobrien
108159243Sobrien    (void) strcoll(root, root);
108259243Sobrien
108359243Sobrien    if (fd != -1)
1084167465Smp	xclose(fd);
108559243Sobrien#endif
108659243Sobrien}
108759243Sobrien#endif /* STRCOLLBUG */
108859243Sobrien
108959243Sobrien
109059243Sobrien#ifdef OREO
109159243Sobrien#include <compat.h>
109259243Sobrien#endif /* OREO */
109359243Sobrien
109459243Sobrienvoid
1095167465Smposinit(void)
109659243Sobrien{
109759243Sobrien#ifdef OREO
109859243Sobrien    set42sig();
109959243Sobrien    setcompat(getcompat() & ~COMPAT_EXEC);
1100167465Smp    signal(SIGIO, SIG_IGN);		/* ignore SIGIO */
110159243Sobrien#endif /* OREO */
110259243Sobrien
110359243Sobrien#ifdef aiws
110459243Sobrien    {
110559243Sobrien	struct sigstack inst;
1106167465Smp	inst.ss_sp = xmalloc(4192) + 4192;
110759243Sobrien	inst.ss_onstack = 0;
110859243Sobrien	sigstack(&inst, NULL);
110959243Sobrien    }
111059243Sobrien#endif /* aiws */
111159243Sobrien
111259243Sobrien#ifdef apollo
111359243Sobrien    (void) isapad();
111459243Sobrien#endif
111559243Sobrien
111659243Sobrien#ifdef _SX
111759243Sobrien    /*
111859243Sobrien     * kill(SIGCONT) problems, don't know what this syscall does
111959243Sobrien     * [schott@rzg.mpg.de]
112059243Sobrien     */
112159243Sobrien    syscall(151, getpid(), getpid());
112259243Sobrien#endif /* _SX */
112359243Sobrien}
112459243Sobrien
1125145479Smp#ifndef HAVE_STRERROR
1126167465Smpextern int sys_nerr;
1127167465Smpextern char *sys_errlist[];
112859243Sobrienchar *
1129167465Smpxstrerror(int i)
113059243Sobrien{
113159243Sobrien    if (i >= 0 && i < sys_nerr) {
113259243Sobrien	return sys_errlist[i];
113359243Sobrien    } else {
1134167465Smp	static char *errbuf; /* = NULL; */
1135167465Smp
1136167465Smp	xfree(errbuf);
1137167465Smp	errbuf = xasprintf(CGETS(23, 13, "Unknown Error: %d"), i);
113859243Sobrien	return errbuf;
113959243Sobrien    }
114059243Sobrien}
1141145479Smp#endif /* !HAVE_STRERROR */
114259243Sobrien
1143145479Smp#ifndef HAVE_GETHOSTNAME
114469408Sache# if !defined(_MINIX) && !defined(__EMX__) && !defined(WINNT_NATIVE)
114559243Sobrien#  include <sys/utsname.h>
114669408Sache# endif /* !_MINIX && !__EMX__ && !WINNT_NATIVE */
114759243Sobrien
114859243Sobrienint
1149167465Smpxgethostname(char *name, int namlen)
115059243Sobrien{
115169408Sache# if !defined(_MINIX) && !defined(__EMX__) && !defined(WINNT_NATIVE)
115259243Sobrien    int     i, retval;
115359243Sobrien    struct utsname uts;
115459243Sobrien
115559243Sobrien    retval = uname(&uts);
115659243Sobrien
115759243Sobrien#  ifdef DEBUG
115859243Sobrien    xprintf(CGETS(23, 14, "sysname:  %s\n"), uts.sysname);
115959243Sobrien    xprintf(CGETS(23, 15, "nodename: %s\n"), uts.nodename);
116059243Sobrien    xprintf(CGETS(23, 16, "release:  %s\n"), uts.release);
116159243Sobrien    xprintf(CGETS(23, 17, "version:  %s\n"), uts.version);
116259243Sobrien    xprintf(CGETS(23, 18, "machine:  %s\n"), uts.machine);
116359243Sobrien#  endif /* DEBUG */
116459243Sobrien    i = strlen(uts.nodename) + 1;
116559243Sobrien    (void) strncpy(name, uts.nodename, i < namlen ? i : namlen);
116659243Sobrien
116759243Sobrien    return retval;
116859243Sobrien# else /* !_MINIX && !__EMX__ */
116959243Sobrien    if (namlen > 0) {
117059243Sobrien#  ifdef __EMX__
117159243Sobrien	(void) strncpy(name, "OS/2", namlen);
117259243Sobrien#  else /* _MINIX */
117359243Sobrien	(void) strncpy(name, "minix", namlen);
117459243Sobrien#  endif /* __EMX__ */
117559243Sobrien	name[namlen-1] = '\0';
117659243Sobrien    }
117759243Sobrien    return(0);
117859243Sobrien#endif /* _MINIX && !__EMX__ */
117959243Sobrien} /* end xgethostname */
1180145479Smp#endif /* !HAVE_GETHOSTNAME */
118159243Sobrien
1182145479Smp#ifndef HAVE_NICE
118359243Sobrien# if defined(_MINIX) && defined(NICE)
118459243Sobrien#  undef _POSIX_SOURCE	/* redefined in <lib.h> */
118559243Sobrien#  undef _MINIX		/* redefined in <lib.h> */
118659243Sobrien#  undef HZ		/* redefined in <minix/const.h> */
118759243Sobrien#  include <lib.h>
118859243Sobrien# endif /* _MINIX && NICE */
118959243Sobrienint
1190167465Smpxnice(int incr)
119159243Sobrien{
119259243Sobrien#if defined(_MINIX) && defined(NICE)
119359243Sobrien    return callm1(MM, NICE, incr, 0, 0, NIL_PTR, NIL_PTR, NIL_PTR);
119459243Sobrien#else
119559243Sobrien    return /* incr ? 0 : */ 0;
119659243Sobrien#endif /* _MINIX && NICE */
119759243Sobrien} /* end xnice */
1198145479Smp#endif /* !HAVE_NICE */
119959243Sobrien
1200145479Smp#ifndef HAVE_GETCWD
1201167465Smpstatic char *strnrcpy (char *, char *, size_t);
120259243Sobrien
120359243Sobrien/* xgetcwd():
120459243Sobrien *	Return the pathname of the current directory, or return
120559243Sobrien *	an error message in pathname.
120659243Sobrien */
120759243Sobrien
120859243Sobrien# ifdef hp9000s500
120959243Sobrien/*
121059243Sobrien *  From: Bernd Mohr <mohr@faui77.informatik.uni-erlangen.de>
121159243Sobrien *  I also ported the tcsh to the HP9000 Series 500. This computer
121259243Sobrien *  is a little bit different than the other HP 9000 computer. It has
121359243Sobrien *  a HP Chip instead of a Motorola CPU and it is no "real" UNIX. It runs
121459243Sobrien *  HP-UX which is emulated in top of a HP operating system. So, the last
121559243Sobrien *  supported version of HP-UX is 5.2 on the HP9000s500. This has two
121659243Sobrien *  consequences: it supports no job control and it has a filesystem
121759243Sobrien *  without "." and ".." !!!
121859243Sobrien */
121959243Sobrienchar *
1220167465Smpxgetcwd(char *pathname, size_t pathlen)
122159243Sobrien{
1222167465Smp    char pathbuf[MAXPATHLEN];	/* temporary pathname buffer */
122359243Sobrien    char *pnptr = &pathbuf[(sizeof pathbuf)-1]; /* pathname pointer */
122459243Sobrien    dev_t rdev;			/* root device number */
122559243Sobrien    DIR *dirp = NULL;		/* directory stream */
122659243Sobrien    ino_t rino;			/* root inode number */
122759243Sobrien    off_t rsize;		/* root size */
122859243Sobrien    struct direct *dir;		/* directory entry struct */
122959243Sobrien    struct stat d, dd;		/* file status struct */
123059243Sobrien    int serrno;
123159243Sobrien
123259243Sobrien    *pnptr = '\0';
123359243Sobrien    (void) stat("/.", &d);
123459243Sobrien    rdev = d.st_dev;
123559243Sobrien    rino = d.st_ino;
123659243Sobrien    rsize = d.st_size;
123759243Sobrien    for (;;) {
123859243Sobrien	if (stat(".", &d) == -1) {
123959243Sobrien	    (void) xsnprintf(pathname, pathlen, CGETS(23, 24,
124059243Sobrien		"getcwd: Cannot stat \".\" (%s)"), strerror(errno));
124159243Sobrien	    goto fail;
124259243Sobrien	}
124359243Sobrien	if (d.st_ino == rino && d.st_dev == rdev && d.st_size == rsize)
124459243Sobrien	    break;		/* reached root directory */
124559243Sobrien	if ((dirp = opendir("..")) == NULL) {
124659243Sobrien	    (void) xsnprintf(pathname, pathlen, CGETS(23, 19,
124759243Sobrien		"getcwd: Cannot open \"..\" (%s)"), strerror(errno));
124859243Sobrien	    goto fail;
124959243Sobrien	}
125059243Sobrien	if (chdir("..") == -1) {
125159243Sobrien	    (void) xsnprintf(pathname, pathlen, CGETS(23, 20,
125259243Sobrien		"getcwd: Cannot chdir to \"..\" (%s)"), strerror(errno));
125359243Sobrien	    goto fail;
125459243Sobrien	}
125559243Sobrien	do {
125659243Sobrien	    if ((dir = readdir(dirp)) == NULL) {
125759243Sobrien		(void) xsnprintf(pathname, pathlen,
125859243Sobrien		    CGETS(23, 21, "getcwd: Read error in \"..\" (%s)"),
125959243Sobrien		    strerror(errno));
126059243Sobrien		goto fail;
126159243Sobrien	    }
126259243Sobrien	    if (stat(dir->d_name, &dd) == -1) {
126359243Sobrien		(void) xsnprintf(pathname, pathlen,
126459243Sobrien		    CGETS(23, 25, "getcwd: Cannot stat directory \"%s\" (%s)"),
126559243Sobrien		    dir->d_name, strerror(errno));
126659243Sobrien		goto fail;
126759243Sobrien	    }
126859243Sobrien	} while (dd.st_ino  != d.st_ino  ||
126959243Sobrien		 dd.st_dev  != d.st_dev  ||
127059243Sobrien		 dd.st_size != d.st_size);
1271167465Smp	closedir(dirp);
127259243Sobrien	dirp = NULL;
127359243Sobrien	pnptr = strnrcpy(dirp->d_name, pnptr, pnptr - pathbuf);
127459243Sobrien	pnptr = strnrcpy("/", pnptr, pnptr - pathbuf);
127559243Sobrien    }
127659243Sobrien
127759243Sobrien    if (*pnptr == '\0')		/* current dir == root dir */
127859243Sobrien	(void) strncpy(pathname, "/", pathlen);
127959243Sobrien    else {
128059243Sobrien	(void) strncpy(pathname, pnptr, pathlen);
128159243Sobrien	pathname[pathlen - 1] = '\0';
128259243Sobrien	if (chdir(pnptr) == -1) {
128359243Sobrien	    (void) xsnprintf(pathname, MAXPATHLEN, CGETS(23, 22,
128459243Sobrien		    "getcwd: Cannot change back to \".\" (%s)"),
128559243Sobrien		    strerror(errno));
128659243Sobrien	    return NULL;
128759243Sobrien	}
128859243Sobrien    }
128959243Sobrien    return pathname;
129059243Sobrien
129159243Sobrienfail:
129259243Sobrien    serrno = errno;
129359243Sobrien    (void) chdir(strnrcpy(".", pnptr, pnptr - pathbuf));
129459243Sobrien    errno = serrno;
129559243Sobrien    return NULL;
129659243Sobrien}
129759243Sobrien
129859243Sobrien# else /* ! hp9000s500 */
129959243Sobrien
130059243Sobrien
130159243Sobrienchar *
1302167465Smpxgetcwd(char *pathname, size_t pathlen)
130359243Sobrien{
130459243Sobrien    DIR    *dp;
130559243Sobrien    struct dirent *d;
130659243Sobrien
130759243Sobrien    struct stat st_root, st_cur, st_next, st_dotdot;
130859243Sobrien    char    pathbuf[MAXPATHLEN], nextpathbuf[MAXPATHLEN * 2];
130959243Sobrien    char   *pathptr, *nextpathptr, *cur_name_add;
131059243Sobrien    int	   save_errno = 0;
131159243Sobrien
131259243Sobrien    /* find the inode of root */
131359243Sobrien    if (stat("/", &st_root) == -1) {
131459243Sobrien	(void) xsnprintf(pathname, pathlen, CGETS(23, 23,
131559243Sobrien			"getcwd: Cannot stat \"/\" (%s)"),
131659243Sobrien			strerror(errno));
131759243Sobrien	return NULL;
131859243Sobrien    }
131959243Sobrien    pathbuf[MAXPATHLEN - 1] = '\0';
132059243Sobrien    pathptr = &pathbuf[MAXPATHLEN - 1];
132159243Sobrien    nextpathbuf[MAXPATHLEN - 1] = '\0';
132259243Sobrien    cur_name_add = nextpathptr = &nextpathbuf[MAXPATHLEN - 1];
132359243Sobrien
132459243Sobrien    /* find the inode of the current directory */
132559243Sobrien    if (lstat(".", &st_cur) == -1) {
132659243Sobrien	(void) xsnprintf(pathname, pathlen, CGETS(23, 24,
132759243Sobrien			 "getcwd: Cannot stat \".\" (%s)"),
132859243Sobrien			 strerror(errno));
132959243Sobrien	return NULL;
133059243Sobrien    }
133159243Sobrien    nextpathptr = strnrcpy(nextpathptr, "../", nextpathptr - nextpathbuf);
133259243Sobrien
133359243Sobrien    /* Descend to root */
133459243Sobrien    for (;;) {
133559243Sobrien
133659243Sobrien	/* look if we found root yet */
133759243Sobrien	if (st_cur.st_ino == st_root.st_ino &&
133859243Sobrien	    DEV_DEV_COMPARE(st_cur.st_dev, st_root.st_dev)) {
133959243Sobrien	    (void) strncpy(pathname, *pathptr != '/' ? "/" : pathptr, pathlen);
134059243Sobrien	    pathname[pathlen - 1] = '\0';
134159243Sobrien	    return pathname;
134259243Sobrien	}
134359243Sobrien
134459243Sobrien	/* open the parent directory */
134559243Sobrien	if (stat(nextpathptr, &st_dotdot) == -1) {
134659243Sobrien	    (void) xsnprintf(pathname, pathlen, CGETS(23, 25,
134759243Sobrien			     "getcwd: Cannot stat directory \"%s\" (%s)"),
134859243Sobrien			     nextpathptr, strerror(errno));
134959243Sobrien	    return NULL;
135059243Sobrien	}
135159243Sobrien	if ((dp = opendir(nextpathptr)) == NULL) {
135259243Sobrien	    (void) xsnprintf(pathname, pathlen, CGETS(23, 26,
135359243Sobrien			     "getcwd: Cannot open directory \"%s\" (%s)"),
135459243Sobrien			     nextpathptr, strerror(errno));
135559243Sobrien	    return NULL;
135659243Sobrien	}
135759243Sobrien
135859243Sobrien	/* look in the parent for the entry with the same inode */
135959243Sobrien	if (DEV_DEV_COMPARE(st_dotdot.st_dev, st_cur.st_dev)) {
136059243Sobrien	    /* Parent has same device. No need to stat every member */
136159243Sobrien	    for (d = readdir(dp); d != NULL; d = readdir(dp)) {
136259243Sobrien#ifdef __clipper__
1363145479Smp		if (((unsigned long)d->d_ino & 0xffff) == st_cur.st_ino)
136459243Sobrien		    break;
136559243Sobrien#else
1366145479Smp		if (d->d_ino == st_cur.st_ino)
136759243Sobrien		    break;
136859243Sobrien#endif
136959243Sobrien	    }
137059243Sobrien	}
137159243Sobrien	else {
137259243Sobrien	    /*
137359243Sobrien	     * Parent has a different device. This is a mount point so we
137459243Sobrien	     * need to stat every member
137559243Sobrien	     */
137659243Sobrien	    for (d = readdir(dp); d != NULL; d = readdir(dp)) {
137759243Sobrien		if (ISDOT(d->d_name) || ISDOTDOT(d->d_name))
137859243Sobrien		    continue;
137959243Sobrien		(void)strncpy(cur_name_add, d->d_name,
138059243Sobrien		    (size_t) (&nextpathbuf[sizeof(nextpathbuf) - 1] - cur_name_add));
138159243Sobrien		if (lstat(nextpathptr, &st_next) == -1) {
138259243Sobrien		    /*
138359243Sobrien		     * We might not be able to stat() some path components
138459243Sobrien		     * if we are using afs, but this is not an error as
138559243Sobrien		     * long as we find the one we need; we also save the
138659243Sobrien		     * first error to report it if we don't finally succeed.
138759243Sobrien		     */
138859243Sobrien		    if (save_errno == 0)
138959243Sobrien			save_errno = errno;
139059243Sobrien		    continue;
139159243Sobrien		}
139259243Sobrien		/* check if we found it yet */
139359243Sobrien		if (st_next.st_ino == st_cur.st_ino &&
139459243Sobrien		    DEV_DEV_COMPARE(st_next.st_dev, st_cur.st_dev))
139559243Sobrien		    break;
139659243Sobrien	    }
139759243Sobrien	}
139859243Sobrien	if (d == NULL) {
139959243Sobrien	    (void) xsnprintf(pathname, pathlen, CGETS(23, 27,
140059243Sobrien			     "getcwd: Cannot find \".\" in \"..\" (%s)"),
140159243Sobrien			     strerror(save_errno ? save_errno : ENOENT));
1402167465Smp	    closedir(dp);
140359243Sobrien	    return NULL;
140459243Sobrien	}
140559243Sobrien	else
140659243Sobrien	    save_errno = 0;
140759243Sobrien	st_cur = st_dotdot;
140859243Sobrien	pathptr = strnrcpy(pathptr, d->d_name, pathptr - pathbuf);
140959243Sobrien	pathptr = strnrcpy(pathptr, "/", pathptr - pathbuf);
141059243Sobrien	nextpathptr = strnrcpy(nextpathptr, "../", nextpathptr - nextpathbuf);
141159243Sobrien	*cur_name_add = '\0';
1412167465Smp	closedir(dp);
141359243Sobrien    }
141459243Sobrien} /* end getcwd */
141559243Sobrien# endif /* hp9000s500 */
141659243Sobrien
141759243Sobrien/* strnrcpy():
141859243Sobrien *	Like strncpy, going backwards and returning the new pointer
141959243Sobrien */
142059243Sobrienstatic char *
1421167465Smpstrnrcpy(char *ptr, char *str, size_t siz)
142259243Sobrien{
1423145479Smp    int len = strlen(str);
142459243Sobrien    if (siz == 0)
142559243Sobrien	return ptr;
142659243Sobrien
142759243Sobrien    while (len && siz--)
142859243Sobrien	*--ptr = str[--len];
142959243Sobrien
143059243Sobrien    return (ptr);
143159243Sobrien} /* end strnrcpy */
1432145479Smp#endif /* !HAVE_GETCWD */
143359243Sobrien
143459243Sobrien#ifdef apollo
143559243Sobrien/***
143659243Sobrien *** Domain/OS
143759243Sobrien ***/
143859243Sobrien#include <apollo/base.h>
143959243Sobrien#include <apollo/loader.h>
144059243Sobrien#include <apollo/error.h>
144159243Sobrien
144259243Sobrien
144359243Sobrienstatic char *
1444167465Smpapperr(status_$t *st)
144559243Sobrien{
1446167465Smp    static char *buf; /* = NULL */
144759243Sobrien    short e_subl, e_modl, e_codel;
144859243Sobrien    error_$string_t e_sub, e_mod, e_code;
144959243Sobrien
145059243Sobrien    error_$get_text(*st, e_sub, &e_subl, e_mod, &e_modl, e_code, &e_codel);
145159243Sobrien    e_sub[e_subl] = '\0';
145259243Sobrien    e_code[e_codel] = '\0';
145359243Sobrien    e_mod[e_modl] = '\0';
1454167465Smp    xfree(buf);
1455167465Smp    buf = xasprintf("%s (%s/%s)", e_code, e_sub, e_mod);
145659243Sobrien
145759243Sobrien    return(buf);
145859243Sobrien}
145959243Sobrien
146059243Sobrienstatic int
1461167465Smpllib(Char *s)
146259243Sobrien{
146359243Sobrien    short len = Strlen(s);
146459243Sobrien    status_$t st;
146559243Sobrien    char *t;
146659243Sobrien
146759243Sobrien    loader_$inlib(t = short2str(s), len, &st);
146859243Sobrien    if (st.all != status_$ok)
146959243Sobrien	stderror(ERR_SYSTEM, t, apperr(&st));
147059243Sobrien}
147159243Sobrien
147259243Sobrien/*ARGSUSED*/
147359243Sobrienvoid
1474167465Smpdoinlib(Char **v, struct command *c)
147559243Sobrien{
1476167465Smp    Char **globbed;
1477167465Smp
147859243Sobrien    setname(short2str(*v++));
1479167465Smp    v = glob_all_or_error(v);
1480167465Smp    globbed = v;
1481167465Smp    cleanup_push(globbed, blk_cleanup);
148259243Sobrien
148359243Sobrien    while (v && *v)
148459243Sobrien	llib(*v++);
1485167465Smp    cleanup_until(globbed);
148659243Sobrien}
148759243Sobrien
148859243Sobrienint
1489167465Smpgetv(Char *v)
149059243Sobrien{
149159243Sobrien    if (eq(v, STRbsd43))
149259243Sobrien	return(1);
149359243Sobrien    else if (eq(v, STRsys53))
149459243Sobrien	return(0);
149559243Sobrien    else
149659243Sobrien	stderror(ERR_NAME | ERR_SYSTEM, short2str(v),
149759243Sobrien		 CGETS(23, 28, "Invalid system type"));
149859243Sobrien    /*NOTREACHED*/
149959243Sobrien    return(0);
150059243Sobrien}
150159243Sobrien
150259243Sobrien/*ARGSUSED*/
150359243Sobrienvoid
1504167465Smpdover(Char **v, struct command *c)
150559243Sobrien{
150659243Sobrien    Char *p;
150759243Sobrien
150859243Sobrien    setname(short2str(*v++));
150959243Sobrien    if (!*v) {
151059243Sobrien	if (!(p = tgetenv(STRSYSTYPE)))
151159243Sobrien	    stderror(ERR_NAME | ERR_STRING,
151259243Sobrien		     CGETS(23, 29, "System type is not set"));
151359243Sobrien	xprintf("%S\n", p);
151459243Sobrien    }
151559243Sobrien    else {
151659243Sobrien	tsetenv(STRSYSTYPE, getv(*v) ? STRbsd43 : STRsys53);
151759243Sobrien	dohash(NULL, NULL);
151859243Sobrien    }
151959243Sobrien}
152059243Sobrien
152159243Sobrien/*
152259243Sobrien * Many thanks to rees@citi.umich.edu (Jim Rees) and
152359243Sobrien *                mathys@ssdt-tempe.sps.mot.com (Yves Mathys)
152459243Sobrien * For figuring out how to do this... I could have never done
152559243Sobrien * it without their help.
152659243Sobrien */
152759243Sobrientypedef short enum {
152859243Sobrien	name_$wdir_type,
152959243Sobrien	name_$ndir_type,
153059243Sobrien	name_$node_dir_type,
153159243Sobrien} name_$dir_type_t;
153259243Sobrien
153359243Sobrien/*ARGSUSED*/
153459243Sobrienvoid
1535167465Smpdorootnode(Char **v, struct command *c)
153659243Sobrien{
153759243Sobrien    name_$dir_type_t dirtype = name_$node_dir_type;
153859243Sobrien    uid_$t uid;
153959243Sobrien    status_$t st;
154059243Sobrien    char *name;
154159243Sobrien    short namelen;
154259243Sobrien
154359243Sobrien    setname(short2str(*v++));
154459243Sobrien
154559243Sobrien    name = short2str(*v);
154659243Sobrien    namelen = strlen(name);
154759243Sobrien
154859243Sobrien    name_$resolve(name, &namelen, &uid, &st);
154959243Sobrien    if (st.all != status_$ok)
155059243Sobrien	stderror(ERR_SYSTEM, name, apperr(&st));
155159243Sobrien    namelen = 0;
155259243Sobrien    name_$set_diru(&uid, "", &namelen, &dirtype, &st);
155359243Sobrien    if (st.all != status_$ok)
155459243Sobrien	stderror(ERR_SYSTEM, name, apperr(&st));
155559243Sobrien    dohash(NULL, NULL);
155659243Sobrien}
155759243Sobrien
155859243Sobrienint
1559167465Smpisapad(void)
156059243Sobrien{
156159243Sobrien    static int res = -1;
156259243Sobrien    static status_$t st;
156359243Sobrien
156459243Sobrien    if (res == -1) {
156559243Sobrien	int strm;
156659243Sobrien	if (isatty(0))
156759243Sobrien	    strm = 0;
156859243Sobrien	if (isatty(1))
156959243Sobrien	    strm = 1;
157059243Sobrien	if (isatty(2))
157159243Sobrien	    strm = 2;
157259243Sobrien	else {
157359243Sobrien	    res = 0;
157459243Sobrien	    st.all = status_$ok;
157559243Sobrien	    return(res);
157659243Sobrien	}
157759243Sobrien	res = stream_$isavt(&strm, &st);
157859243Sobrien	res = res ? 1 : 0;
157959243Sobrien    }
158059243Sobrien    else {
158159243Sobrien	if (st.all != status_$ok)
158259243Sobrien	    stderror(ERR_SYSTEM, "stream_$isavt", apperr(&st));
158359243Sobrien    }
158459243Sobrien    return(res);
158559243Sobrien}
158659243Sobrien#endif
1587232633Smp
1588232633Smp#ifdef __ANDROID__
1589232633Smp#include <stdio.h>
1590232633Smp/* Android (<= 2.1?) has an incomplete ttyname implementation. */
1591232633Smpchar *
1592232633Smpttyname(int fd)
1593232633Smp{
1594232633Smp    char path[64];
1595232633Smp    ssize_t siz;
1596232633Smp    static char ttyname[32];
1597232633Smp
1598232633Smp    if (!isatty(fd))
1599232633Smp	return NULL;
1600232633Smp
1601232633Smp    (void)snprintf(path, sizeof(path), "/proc/self/fd/%d", fd);
1602232633Smp    siz = readlink(path, ttyname, sizeof(ttyname));
1603232633Smp    if (siz < 0 || siz == sizeof(ttyname))
1604232633Smp	return NULL;
1605232633Smp    ttyname[siz] = '\0';
1606232633Smp    return ttyname;
1607232633Smp}
1608232633Smp#endif /* __ANDROID__ */
1609232633Smp
1610232633Smp#if defined(__CYGWIN__) && !defined(NO_CRYPT)
1611232633Smp#undef CHAR		/* Collides with Win32 API */
1612232633Smp#define WIN32_LEAN_AND_MEAN
1613232633Smp#include <windows.h>
1614232633Smp#include <sys/cygwin.h>
1615232633Smpchar *
1616232633Smpcygwin_xcrypt(struct passwd *pw, const char *password, const char *expected_pwd)
1617232633Smp{
1618232633Smp    static char invalid_password[] = "\377";
1619232633Smp    HANDLE token = cygwin_logon_user(pw, password);
1620232633Smp    if (token == INVALID_HANDLE_VALUE)
1621232633Smp	return invalid_password;
1622232633Smp    CloseHandle(token);
1623232633Smp    return (char *) expected_pwd;
1624232633Smp}
1625232633Smp#endif /* __CYGWIN__ && !NO_CRYPT */
1626