diff options
Diffstat (limited to 'contrib/tcsh/tc.os.c')
-rw-r--r-- | contrib/tcsh/tc.os.c | 1625 |
1 files changed, 1625 insertions, 0 deletions
diff --git a/contrib/tcsh/tc.os.c b/contrib/tcsh/tc.os.c new file mode 100644 index 0000000..3377549 --- /dev/null +++ b/contrib/tcsh/tc.os.c @@ -0,0 +1,1625 @@ +/* $Header: /p/tcsh/cvsroot/tcsh/tc.os.c,v 3.72 2011/01/25 13:58:19 christos Exp $ */ +/* + * tc.os.c: OS Dependent builtin functions + */ +/*- + * Copyright (c) 1980, 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#include "sh.h" + +RCSID("$tcsh: tc.os.c,v 3.72 2011/01/25 13:58:19 christos Exp $") + +#include "tw.h" +#include "ed.h" +#include "ed.defns.h" /* for the function names */ +#include "sh.decls.h" + +#ifdef _UWIN +#define TIOCGPGRP TIOCGETPGRP +#define TIOCSPGRP TIOCSETPGRP +#endif + +/*** + *** MACH + ***/ + +#ifdef MACH +/* dosetpath -- setpath built-in command + * + ********************************************************************** + * HISTORY + * 08-May-88 Richard Draves (rpd) at Carnegie-Mellon University + * Major changes to remove artificial limits on sizes and numbers + * of paths. + * + ********************************************************************** + */ + +#ifdef MACH +static Char STRCPATH[] = {'C', 'P', 'A', 'T', 'H', '\0'}; +static Char STRLPATH[] = {'L', 'P', 'A', 'T', 'H', '\0'}; +static Char STRMPATH[] = {'M', 'P', 'A', 'T', 'H', '\0'}; +# if EPATH +static Char STREPATH[] = {'E', 'P', 'A', 'T', 'H', '\0'}; +# endif +#endif /* MACH */ +static Char *syspaths[] = {STRKPATH, STRCPATH, STRLPATH, STRMPATH, + +#if EPATH + STREPATH, +#endif + 0}; +#define LOCALSYSPATH "/usr/local" + +/*ARGSUSED*/ +void +dosetpath(Char **arglist, struct command *c) +{ + extern char *getenv(); + Char **pathvars, **cmdargs; + char **spaths, **cpaths, **cmds; + char *tcp; + unsigned int npaths, ncmds; + int i, sysflag; + + pintr_disabled++; + cleanup_push(&pintr_disabled, disabled_cleanup); + + /* + * setpath(3) uses stdio and we want 0, 1, 2 to work... + */ + if (!didfds) { + (void) dcopy(SHIN, 0); + (void) dcopy(SHOUT, 1); + (void) dcopy(SHDIAG, 2); + didfds = 1; + } + + for (i = 1; arglist[i] && (arglist[i][0] != '-'); i++); + npaths = i - 1; + + cmdargs = &arglist[i]; + for (; arglist[i]; i++); + ncmds = i - npaths - 1; + + if (npaths) { + sysflag = 0; + pathvars = &arglist[1]; + } + else { + sysflag = 1; + npaths = (sizeof syspaths / sizeof *syspaths) - 1; + pathvars = syspaths; + } + + /* note that npaths != 0 */ + + spaths = xmalloc(npaths * sizeof *spaths); + setzero(spaths, npaths * sizeof *spaths); + cpaths = xmalloc((npaths + 1) * sizeof *cpaths); + setzero(cpaths, (npaths + 1) * sizeof *cpaths); + cmds = xmalloc((ncmds + 1) * sizeof *cmds); + setzero(cmds, (ncmds + 1) * sizeof *cmds); + for (i = 0; i < npaths; i++) { + char *val = getenv(short2str(pathvars[i])); + + if (val == NULL) + val = ""; + + spaths[i] = xmalloc((Strlen(pathvars[i]) + strlen(val) + 2) * + sizeof **spaths); + (void) strcpy(spaths[i], short2str(pathvars[i])); + (void) strcat(spaths[i], "="); + (void) strcat(spaths[i], val); + cpaths[i] = spaths[i]; + } + + for (i = 0; i < ncmds; i++) { + Char *val = globone(cmdargs[i], G_ERROR);/*FIXRESET*/ + + if (val == NULL) + goto abortpath; + cmds[i] = strsave(short2str(val)); + } + + + if (setpath(cpaths, cmds, LOCALSYSPATH, sysflag, 1) < 0) { +abortpath: + if (spaths) { + for (i = 0; i < npaths; i++) + xfree(spaths[i]); + xfree(spaths); + } + xfree(cpaths); + if (cmds) { + for (i = 0; i < ncmds; i++) + xfree(cmds[i]); + xfree(cmds); + } + + cleanup_until(&pintr_disabled); + donefds(); + return; + } + + for (i = 0; i < npaths; i++) { + Char *val, *name; + + name = str2short(cpaths[i]); + for (val = str2short(cpaths[i]); val && *val && *val != '='; val++); + if (val && *val == '=') { + *val++ = '\0'; + + tsetenv(name, val);/*FIXRESET*/ + if (Strcmp(name, STRKPATH) == 0) { + importpath(val);/*FIXRESET*/ + if (havhash) + dohash(NULL, NULL);/*FIXRESET*/ + } + *--val = '='; + } + } + cleanup_until(&pintr_disabled); + donefds(); +} +#endif /* MACH */ + +/*** + *** AIX + ***/ +#ifdef TCF +/* ARGSUSED */ +void +dogetxvers(Char **v, struct command *c) +{ + char xvers[MAXPATHLEN]; + + if (getxvers(xvers, MAXPATHLEN) == -1) + stderror(ERR_SYSTEM, "getxvers", strerror(errno)); + xprintf("%s\n", xvers); + flush(); +} + +/*ARGSUSED*/ +void +dosetxvers(Char **v, struct command *c) +{ + char *xvers; + + ++v; + if (!*v || *v[0] == '\0') + xvers = ""; + else + xvers = short2str(*v); + if (setxvers(xvers) == -1) + stderror(ERR_SYSTEM, "setxvers", strerror(errno)); +} + +#include <sf.h> +#ifdef _AIXPS2 +# define XC_PDP11 0x01 +# define XC_23 0x02 +# define XC_Z8K 0x03 +# define XC_8086 0x04 +# define XC_68K 0x05 +# define XC_Z80 0x06 +# define XC_VAX 0x07 +# define XC_16032 0x08 +# define XC_286 0x09 +# define XC_386 0x0a +# define XC_S370 0x0b +#else +# include <sys/x.out.h> +#endif /* _AIXPS2 */ + +static struct xc_cpu_t { + short xc_id; + char *xc_name; +} xcpu[] = +{ + { XC_PDP11, "pdp11" }, + { XC_23, "i370" }, + { XC_Z8K, "z8000" }, + { XC_8086, "i86" }, + { XC_68K, "mc68000" }, + { XC_Z80, "x80" }, + { XC_VAX, "vax" }, + { XC_16032, "ns16032" }, + { XC_286, "i286" }, + { XC_386, "i386" }, + { XC_S370, "xa370" }, + { 0, NULL } +}; + +/* + * our local hack table, stolen from x.out.h + */ +static char * +getxcode(short xcid) +{ + int i; + + for (i = 0; xcpu[i].xc_name != NULL; i++) + if (xcpu[i].xc_id == xcid) + return (xcpu[i].xc_name); + return (NULL); +} + +static short +getxid(char *xcname) +{ + int i; + + for (i = 0; xcpu[i].xc_name != NULL; i++) + if (strcmp(xcpu[i].xc_name, xcname) == 0) + return (xcpu[i].xc_id); + return ((short) -1); +} + + +/*ARGSUSED*/ +void +dogetspath(Char **v, struct command *c) +{ + int i, j; + sitepath_t p[MAXSITE]; + struct sf *st; + static char *local = "LOCAL "; + + if ((j = getspath(p, MAXSITE)) == -1) + stderror(ERR_SYSTEM, "getspath", strerror(errno)); + for (i = 0; i < j && (p[i] & SPATH_CPU) != NOSITE; i++) { + if (p[i] & SPATH_CPU) { + if ((p[i] & SPATH_MASK) == NULLSITE) + xprintf(local); + else if ((st = sfxcode((short) (p[i] & SPATH_MASK))) != NULL) + xprintf("%s ", st->sf_ctype); + else { + char *xc = getxcode(p[i] & SPATH_MASK); + + if (xc != NULL) + xprintf("%s ", xc); + else + xprintf("*cpu %d* ", (int) (p[i] & SPATH_MASK)); + /* + * BUG in the aix code... needs that cause if + * sfxcode fails once it fails for ever + */ + endsf(); + } + } + else { + if (p[i] == NULLSITE) + xprintf(local); + else if ((st = sfnum(p[i])) != NULL) + xprintf("%s ", st->sf_sname); + else + xprintf("*site %d* ", (int) (p[i] & SPATH_MASK)); + } + } + xputchar('\n'); + flush(); +} + +/*ARGSUSED*/ +void +dosetspath(Char **v, struct command *c) +{ + int i; + short j; + char *s; + sitepath_t p[MAXSITE]; + struct sf *st; + + /* + * sfname() on AIX G9.9 at least, mallocs too pointers p, q + * then does the equivalent of while (*p++ == *q++) continue; + * and then tries to free(p,q) them! Congrats to the wizard who + * wrote that one. I bet he tested it really well too. + * Sooo, we set dont_free :-) + */ + dont_free = 1; + for (i = 0, v++; *v && *v[0] != '\0'; v++, i++) { + s = short2str(*v); + if (isdigit(*s)) + p[i] = atoi(s); + else if (strcmp(s, "LOCAL") == 0) + p[i] = NULLSITE; + else if ((st = sfctype(s)) != NULL) + p[i] = SPATH_CPU | st->sf_ccode; + else if ((j = getxid(s)) != -1) + p[i] = SPATH_CPU | j; + else if ((st = sfname(s)) != NULL) + p[i] = st->sf_id; + else { + setname(s); + stderror(ERR_NAME | ERR_STRING, CGETS(23, 1, "Bad cpu/site name")); + } + if (i == MAXSITE - 1) + stderror(ERR_NAME | ERR_STRING, CGETS(23, 2, "Site path too long")); + } + if (setspath(p, i) == -1) + stderror(ERR_SYSTEM, "setspath", strerror(errno)); + dont_free = 0; +} + +/* sitename(): + * Return the site name where the process is running + */ +char * +sitename(pid_t pid) +{ + siteno_t ss; + struct sf *st; + + if ((ss = site(pid)) == -1 || (st = sfnum(ss)) == NULL) + return CGETS(23, 3, "unknown"); + else + return st->sf_sname; +} + +static int +migratepid(pit_t pid, siteno_t new_site) +{ + struct sf *st; + int need_local; + + need_local = (pid == 0) || (pid == getpid()); + + if (kill3(pid, SIGMIGRATE, new_site) < 0) { + xprintf("%d: %s\n", pid, strerror(errno)); + return (-1); + } + + if (need_local) { + if ((new_site = site(0)) == -1) { + xprintf(CGETS(23, 4, "site: %s\n"), strerror(errno)); + return (-1); + } + if ((st = sfnum(new_site)) == NULL) { + xprintf(CGETS(23, 5, "%d: Site not found\n"), new_site); + return (-1); + } + if (setlocal(st->sf_local, strlen(st->sf_local)) == -1) { + xprintf(CGETS(23, 6, "setlocal: %s: %s\n"), + st->sf_local, strerror(errno)); + return (-1); + } + } + return (0); +} + +/*ARGSUSED*/ +void +domigrate(Char **v, struct command *c) +{ + struct sf *st; + char *s; + Char *cp; + struct process *pp; + int err1 = 0; + int pid = 0; + siteno_t new_site = 0; + + pchild_disabled++; + cleanup_push(&pchild_disabled, disabled_cleanup); + if (setintr) { + pintr_disabled++; + cleanup_push(&pintr_disabled, disabled_cleanup); + } + + ++v; + if (*v[0] == '-') { + /* + * Do the -site. + */ + s = short2str(&v[0][1]); + /* + * see comment in setspath() + */ + dont_free = 1; + if ((st = sfname(s)) == NULL) { + dont_free = 0; + setname(s); + stderror(ERR_NAME | ERR_STRING, CGETS(23, 7, "Site not found")); + } + dont_free = 0; + new_site = st->sf_id; + ++v; + } + + if (!*v || *v[0] == '\0') { + if (migratepid(0, new_site) == -1) + err1++; + } + else { + Char **globbed; + + v = glob_all_or_error(v); + globbed = v; + cleanup_push(globbed, blk_cleanup); + + while (v && (cp = *v)) { + if (*cp == '%') { + pp = pfind(cp); + if (kill3(- pp->p_jobid, SIGMIGRATE, new_site) < 0) { + xprintf("%S: %s\n", cp, strerror(errno)); + err1++; + } + } + else if (!(Isdigit(*cp) || *cp == '-')) + stderror(ERR_NAME | ERR_JOBARGS); + else { + pid = atoi(short2str(cp)); + if (migratepid(pid, new_site) == -1) + err1++; + } + v++; + } + cleanup_until(globbed); + } + +done: + cleanup_until(&pchild_disabled); + if (err1) + stderror(ERR_SILENT); +} + +#endif /* TCF */ + +/*** + *** CRAY ddmode <velo@sesun3.epfl.ch> (Martin Ouwehand EPFL-SIC/SE) + ***/ +#if defined(_CRAY) && !defined(_CRAYMPP) +void +dodmmode(Char **v, struct command *c) +{ + Char *cp = v[1]; + + USE(c); + + if ( !cp ) { + int mode; + + mode = dmmode(0); + dmmode(mode); + xprintf("%d\n",mode); + } + else { + if (cp[1] != '\0') + stderror(ERR_NAME | ERR_STRING, + CGETS(23, 30, "Too many arguments")); + else + switch(*cp) { + case '0': + dmmode(0); + break; + case '1': + dmmode(1); + break; + default: + stderror(ERR_NAME | ERR_STRING, + CGETS(23, 31, "Invalid argument")); + } + } +} +#endif /* _CRAY && !_CRAYMPP */ + + +/*** + *** CONVEX Warps. + ***/ + +#ifdef WARP +/* + * handle the funky warping of symlinks + */ +#include <warpdb.h> +#include <sys/warp.h> + +static jmp_buf sigsys_buf; + +static void +catch_sigsys(void) +{ + sigset_t set; + sigemptyset(&set, SIGSYS); + (void)sigprocmask(SIG_UNBLOCK, &set, NULL); + longjmp(sigsys_buf, 1); +} + + +/*ARGSUSED*/ +void +dowarp(Char **v, struct command *c) +{ + int warp, oldwarp; + struct warpent *we; + volatile struct sigaction old_sigsys_handler; + char *newwarp; + + if (setjmp(sigsys_buf)) { + sigaction(SIGSYS, &old_sigsys_handler, NULL); + stderror(ERR_NAME | ERR_STRING, + CGETS(23, 8, "You're trapped in a universe you never made")); + return; + } + sigaction(SIGSYS, NULL, &old_sigsys_handler); + signal(SIGSYS, catch_sigsys); + + warp = getwarp(); + + v++; + if (*v == 0) { /* display warp value */ + if (warp < 0) + stderror(ERR_NAME | ERR_STRING, CGETS(23, 9, "Getwarp failed")); + we = getwarpbyvalue(warp); + if (we) + printf("%s\n", we->w_name); + else + printf("%d\n", warp); + } + else { /* set warp value */ + oldwarp = warp; + newwarp = short2str(*v); + if (Isdigit(*v[0])) + warp = atoi(newwarp); + else { + we = getwarpbyname(newwarp); + if (we) + warp = we->w_value; + else + warp = -1; + } + if ((warp < 0) || (warp >= WARP_MAXLINK)) + stderror(ERR_NAME | ERR_STRING, CGETS(23, 10, "Invalid warp")); + if ((setwarp(warp) < 0) || (getwarp() != warp)) { + (void) setwarp(oldwarp); + stderror(ERR_NAME | ERR_STRING, CGETS(23, 11, "Setwarp failed")); + } + } + sigaction(SIGSYS, &old_sigsys_handler, NULL); +} +#endif /* WARP */ + +/*** + *** Masscomp or HCX + ***/ +/* Added, DAS DEC-90. */ +#if defined(masscomp) || defined(_CX_UX) +static void +setuniverse_cleanup(void *xbuf) +{ + char *buf; + + buf = xbuf; + setuniverse(buf); +} + +/*ARGSUSED*/ +void +douniverse(Char **v, struct command *c) +{ + Char *cp = v[1]; + Char *cp2; /* dunno how many elements v comes in with */ + char ubuf[100]; + + if (cp == 0) { + (void) getuniverse(ubuf); + xprintf("%s\n", ubuf); + } + else { + cp2 = v[2]; + if (cp2 == 0) { + if (*cp == '\0' || setuniverse(short2str(cp)) != 0) + stderror(ERR_NAME | ERR_STRING, CGETS(23, 12, "Illegal universe")); + } + else { + (void) getuniverse(ubuf); + if (*cp == '\0' || setuniverse(short2str(cp)) != 0) + stderror(ERR_NAME | ERR_STRING, CGETS(23, 12, "Illegal universe")); + cleanup_push(ubuf, setuniverse_cleanup); + if (setintr) { + pintr_disabled++; + cleanup_push(&pintr_disabled, disabled_cleanup); + } + lshift(v, 2); + if (setintr) + cleanup_until(&pintr_disabled); + reexecute(c); + cleanup_until(ubuf); + } + } +} +#endif /* masscomp || _CX_UX */ + +/*** + *** BS2000/OSD POSIX (Fujitsu Siemens Computers) + ***/ +#if defined(_OSD_POSIX) +static int +bs2upcase(char *str) +{ + enum { outside = ' ', singlequote='\'', doublequote='"'} string = outside; + + char *white; + + for (white = str + strlen(str) - 1; isspace(*white) && white > str; --white) + *white = '\0'; + + for (; *str != '\0'; ++str) + { + if (string == outside) + { + *str = toupper (*str); + } + if (*str == '\'') + { + if (string == outside) + string = singlequote; + else if (string != doublequote) + string = outside; + } + else if (*str == '"') + { + if (string == outside) + string = doublequote; + else if (string != singlequote) + string = outside; + } + } + if (string != outside) + { + stderror(ERR_NAME | ERR_UNMATCHED, (Char) string); + return 1; + } + return 0; +} +static int +bs2cmdlist(char *str) +{ + char *str_beg = NULL; + int ret = 0; + + enum { outside = ' ', singlequote='\'', doublequote='"'} string = outside; + + while (*str != '\0') + { + while (isspace(*str)) + ++str; + + if (*str == '\0') + break; + + str_beg = str; + + for (; *str != '\0'; ++str) + { + if (string == outside && *str == ';') /* End of command */ + { + *str++ = '\0'; + break; /* continue with next command */ + } + if (*str == '\'') + { + if (string == outside) + string = singlequote; + else if (string != doublequote) + string = outside; + } + else if (*str == '"') + { + if (string == outside) + string = doublequote; + else if (string != singlequote) + string = outside; + } + } + if (strlen(str_beg) != 0) + { + ret = bs2system(str_beg); + flush(); + if (ret != 0 /*&& !option.err_ignore*/) + break; /* do not continue after errors */ + } + } + + if (string != outside) + { + stderror(ERR_NAME | ERR_UNMATCHED, (Char) string); + return -1; + } + + return ret; +} +/*ARGSUSED*/ +void +dobs2cmd(Char **v, struct command *c) +{ + Char *cp, **globbed; + int i = 0, len = 0; + char *cmd = NULL; + int pvec[2]; + struct command faket; + Char *fakecom[2]; + char tibuf[BUFSIZE]; + int icnt, old_pintr_disabled; + static const Char STRbs2cmd[] = { 'b','s','2','c','m','d','\0' }; + + v++; + if (setintr) + pintr_push_enable(&old_pintr_disabled); + v = glob_all_or_error(v); + if (setintr) + cleanup_until(&old_pintr_disabled); + globbed = v; + cleanup_push(globbed, blk_cleanup); + + /* First round: count the string lengths */ + for (i=0; v[i]; ++i) { + len += Strlen(v[i]) + (v[i+1] != NULL); + } + + cmd = xmalloc(len+1); /* 1 for the final '\0' *//* FIXME: memory leak? */ + + /* 2nd round: fill cmd buffer */ + i = 0; + while ((cp = *v++) != 0) { + int c; + while (c = *cp++) + cmd[i++] = (char)c; + if (*v) + cmd[i++] = ' '; + } + cmd[i] = '\0'; + + /* Make upper case */ + bs2upcase(cmd); + + faket.t_dtyp = NODE_COMMAND; + faket.t_dflg = F_BACKQ|F_STDERR; + faket.t_dlef = 0; + faket.t_drit = 0; + faket.t_dspr = 0; + faket.t_dcom = fakecom; + fakecom[0] = (Char *)STRbs2cmd; + fakecom[1] = 0; + + mypipe(pvec); + cleanup_push(&pvec[0], open_cleanup); + cleanup_push(&pvec[1], open_cleanup); + if (pfork(&faket, -1) == 0) { + sigset_t set; + /* child */ + xclose(pvec[0]); + (void) dmove(pvec[1], 1); + (void) dmove(SHDIAG, 2); + initdesc(); + sigemptyset(&set); + sigaddset(&set, SIGINT); + (void)sigprocmask(SIG_UNBLOCK, &set, NULL); +#ifdef SIGTSTP + signal(SIGTSTP, SIG_IGN); +#endif +#ifdef SIGTTIN + signal(SIGTTIN, SIG_IGN); +#endif +#ifdef SIGTTOU + signal(SIGTTOU, SIG_IGN); +#endif + xexit(bs2cmdlist(cmd)); + } + cleanup_until(&pvec[1]); + for(;;) { + int old_pintr_disabled; + + if (setintr) + pintr_push_enable(&old_pintr_disabled); + icnt = xread(pvec[0], tibuf, sizeof(tibuf)); + if (setintr) + cleanup_until(&old_pintr_disabled); + if (icnt <= 0) + break; + for (i = 0; i < icnt; i++) + xputchar((unsigned char) tibuf[i]); + } + cleanup_until(&pvec[0]); + pwait(); + + flush(); + + cleanup_until(globbed); +} +#endif /* _OSD_POSIX */ + +#if defined(_CX_UX) +static void +setuniverse_cleanup(void *xbuf) +{ + char *buf; + + buf = xbuf; + setuniverse(buf); +} + +/*ARGSUSED*/ +void +doatt(Char **v, struct command *c) +{ + Char *cp = v[1]; + char ubuf[100]; + + if (cp == 0) + (void) setuniverse("att"); + else { + (void) getuniverse(ubuf); + (void) setuniverse("att"); + cleanup_push(ubuf, setuniverse_cleanup); + if (setintr) { + pintr_disabled++; + cleanup_push(&pintr_disabled, disabled_cleanup); + } + lshift(v, 1); + if (setintr) + cleanup_until(&pintr_disabled); + reexecute(c); + cleanup_until(ubuf); + } +} + +/*ARGSUSED*/ +void +doucb(Char **v, struct command *c) +{ + Char *cp = v[1]; + char ubuf[100]; + + if (cp == 0) + (void) setuniverse("ucb"); + else { + (void) getuniverse(ubuf); + (void) setuniverse("ucb"); + cleanup_push(ubuf, setuniverse_cleanup); + if (setintr) { + pintr_disabled++; + cleanup_push(&pintr_disabled, disabled_cleanup); + } + lshift(v, 1); + if (setintr) + cleanup_until(&pintr_disabled); + reexecute(c); + cleanup_until(ubuf); + } +} +#endif /* _CX_UX */ + +#ifdef _SEQUENT_ +/* + * Compute the difference in process stats. + */ +void +pr_stat_sub(struct process_stats *p2, struct process_stats *p1, + struct process_stats *pr) +{ + pr->ps_utime.tv_sec = p2->ps_utime.tv_sec - p1->ps_utime.tv_sec; + pr->ps_utime.tv_usec = p2->ps_utime.tv_usec - p1->ps_utime.tv_usec; + if (pr->ps_utime.tv_usec < 0) { + pr->ps_utime.tv_sec -= 1; + pr->ps_utime.tv_usec += 1000000; + } + pr->ps_stime.tv_sec = p2->ps_stime.tv_sec - p1->ps_stime.tv_sec; + pr->ps_stime.tv_usec = p2->ps_stime.tv_usec - p1->ps_stime.tv_usec; + if (pr->ps_stime.tv_usec < 0) { + pr->ps_stime.tv_sec -= 1; + pr->ps_stime.tv_usec += 1000000; + } + + pr->ps_maxrss = p2->ps_maxrss - p1->ps_maxrss; + pr->ps_pagein = p2->ps_pagein - p1->ps_pagein; + pr->ps_reclaim = p2->ps_reclaim - p1->ps_reclaim; + pr->ps_zerofill = p2->ps_zerofill - p1->ps_zerofill; + pr->ps_pffincr = p2->ps_pffincr - p1->ps_pffincr; + pr->ps_pffdecr = p2->ps_pffdecr - p1->ps_pffdecr; + pr->ps_swap = p2->ps_swap - p1->ps_swap; + pr->ps_syscall = p2->ps_syscall - p1->ps_syscall; + pr->ps_volcsw = p2->ps_volcsw - p1->ps_volcsw; + pr->ps_involcsw = p2->ps_involcsw - p1->ps_involcsw; + pr->ps_signal = p2->ps_signal - p1->ps_signal; + pr->ps_lread = p2->ps_lread - p1->ps_lread; + pr->ps_lwrite = p2->ps_lwrite - p1->ps_lwrite; + pr->ps_bread = p2->ps_bread - p1->ps_bread; + pr->ps_bwrite = p2->ps_bwrite - p1->ps_bwrite; + pr->ps_phread = p2->ps_phread - p1->ps_phread; + pr->ps_phwrite = p2->ps_phwrite - p1->ps_phwrite; +} + +#endif /* _SEQUENT_ */ + + +#ifndef HAVE_MEMSET +/* This is a replacement for a missing memset function */ +void *xmemset(void *loc, int value, size_t len) +{ + char *ptr = loc; + + while (len--) + *ptr++ = value; + return loc; +} +#endif /* !HAVE_MEMSET */ + + +#ifndef HAVE_MEMMOVE +/* memmove(): + * This is the ANSI form of bcopy() with the arguments backwards... + * Unlike memcpy(), it handles overlaps between source and + * destination memory + */ +void * +xmemmove(void *vdst, const void *vsrc, size_t len) +{ + const char *src = vsrc; + char *dst = vdst; + + if (src == dst) + return vdst; + + if (src > dst) { + while (len--) + *dst++ = *src++; + } + else { + src += len; + dst += len; + while (len--) + *--dst = *--src; + } + return vdst; +} +#endif /* HAVE_MEMMOVE */ + + +#ifndef WINNT_NATIVE +#ifdef NEEDtcgetpgrp +pid_t +xtcgetpgrp(int fd) +{ + int pgrp; + + /* ioctl will handle setting errno correctly. */ + if (ioctl(fd, TIOCGPGRP, (ioctl_t) & pgrp) < 0) + return (-1); + return (pgrp); +} + +/* + * XXX: tcsetpgrp is not a macro any more cause on some systems, + * pid_t is a short, but the ioctl() takes a pointer to int (pyr) + * Thanks to Simon Day (simon@pharaoh.cyborg.bt.co.uk) for pointing + * this out. + */ +int +xtcsetpgrp(int fd, int pgrp) +{ + return ioctl(fd, TIOCSPGRP, (ioctl_t) &pgrp); +} + +#endif /* NEEDtcgetpgrp */ +#endif /* WINNT_NATIVE */ + + +#ifdef YPBUGS +void +fix_yp_bugs(void) +{ + char *mydomain; + + extern int yp_get_default_domain (char **); + /* + * PWP: The previous version assumed that yp domain was the same as the + * internet name domain. This isn't allways true. (Thanks to Mat Landau + * <mlandau@bbn.com> for the original version of this.) + */ + if (yp_get_default_domain(&mydomain) == 0) { /* if we got a name */ + extern void yp_unbind (const char *); + + yp_unbind(mydomain); + } +} + +#endif /* YPBUGS */ + +#ifdef STRCOLLBUG +void +fix_strcoll_bug(void) +{ +#if defined(NLS) && defined(HAVE_STRCOLL) + /* + * SunOS4 checks the file descriptor from openlocale() for <= 0 + * instead of == -1. Someone should tell sun that file descriptor 0 + * is valid! Our portable hack: open one so we call it with 0 used... + * We have to call this routine every time the locale changes... + * + * Of course it also tries to free the constant locale "C" it initially + * had allocated, with the sequence + * > setenv LANG "fr" + * > ls^D + * > unsetenv LANG + * But we are smarter than that and just print a warning message. + */ + int fd = -1; + static char *root = "/"; + + if (!didfds) + fd = xopen(root, O_RDONLY|O_LARGEFILE); + + (void) strcoll(root, root); + + if (fd != -1) + xclose(fd); +#endif +} +#endif /* STRCOLLBUG */ + + +#ifdef OREO +#include <compat.h> +#endif /* OREO */ + +void +osinit(void) +{ +#ifdef OREO + set42sig(); + setcompat(getcompat() & ~COMPAT_EXEC); + signal(SIGIO, SIG_IGN); /* ignore SIGIO */ +#endif /* OREO */ + +#ifdef aiws + { + struct sigstack inst; + inst.ss_sp = xmalloc(4192) + 4192; + inst.ss_onstack = 0; + sigstack(&inst, NULL); + } +#endif /* aiws */ + +#ifdef apollo + (void) isapad(); +#endif + +#ifdef _SX + /* + * kill(SIGCONT) problems, don't know what this syscall does + * [schott@rzg.mpg.de] + */ + syscall(151, getpid(), getpid()); +#endif /* _SX */ +} + +#ifndef HAVE_STRERROR +extern int sys_nerr; +extern char *sys_errlist[]; +char * +xstrerror(int i) +{ + if (i >= 0 && i < sys_nerr) { + return sys_errlist[i]; + } else { + static char *errbuf; /* = NULL; */ + + xfree(errbuf); + errbuf = xasprintf(CGETS(23, 13, "Unknown Error: %d"), i); + return errbuf; + } +} +#endif /* !HAVE_STRERROR */ + +#ifndef HAVE_GETHOSTNAME +# if !defined(_MINIX) && !defined(__EMX__) && !defined(WINNT_NATIVE) +# include <sys/utsname.h> +# endif /* !_MINIX && !__EMX__ && !WINNT_NATIVE */ + +int +xgethostname(char *name, int namlen) +{ +# if !defined(_MINIX) && !defined(__EMX__) && !defined(WINNT_NATIVE) + int i, retval; + struct utsname uts; + + retval = uname(&uts); + +# ifdef DEBUG + xprintf(CGETS(23, 14, "sysname: %s\n"), uts.sysname); + xprintf(CGETS(23, 15, "nodename: %s\n"), uts.nodename); + xprintf(CGETS(23, 16, "release: %s\n"), uts.release); + xprintf(CGETS(23, 17, "version: %s\n"), uts.version); + xprintf(CGETS(23, 18, "machine: %s\n"), uts.machine); +# endif /* DEBUG */ + i = strlen(uts.nodename) + 1; + (void) strncpy(name, uts.nodename, i < namlen ? i : namlen); + + return retval; +# else /* !_MINIX && !__EMX__ */ + if (namlen > 0) { +# ifdef __EMX__ + (void) strncpy(name, "OS/2", namlen); +# else /* _MINIX */ + (void) strncpy(name, "minix", namlen); +# endif /* __EMX__ */ + name[namlen-1] = '\0'; + } + return(0); +#endif /* _MINIX && !__EMX__ */ +} /* end xgethostname */ +#endif /* !HAVE_GETHOSTNAME */ + +#ifndef HAVE_NICE +# if defined(_MINIX) && defined(NICE) +# undef _POSIX_SOURCE /* redefined in <lib.h> */ +# undef _MINIX /* redefined in <lib.h> */ +# undef HZ /* redefined in <minix/const.h> */ +# include <lib.h> +# endif /* _MINIX && NICE */ +int +xnice(int incr) +{ +#if defined(_MINIX) && defined(NICE) + return callm1(MM, NICE, incr, 0, 0, NIL_PTR, NIL_PTR, NIL_PTR); +#else + return /* incr ? 0 : */ 0; +#endif /* _MINIX && NICE */ +} /* end xnice */ +#endif /* !HAVE_NICE */ + +#ifndef HAVE_GETCWD +static char *strnrcpy (char *, char *, size_t); + +/* xgetcwd(): + * Return the pathname of the current directory, or return + * an error message in pathname. + */ + +# ifdef hp9000s500 +/* + * From: Bernd Mohr <mohr@faui77.informatik.uni-erlangen.de> + * I also ported the tcsh to the HP9000 Series 500. This computer + * is a little bit different than the other HP 9000 computer. It has + * a HP Chip instead of a Motorola CPU and it is no "real" UNIX. It runs + * HP-UX which is emulated in top of a HP operating system. So, the last + * supported version of HP-UX is 5.2 on the HP9000s500. This has two + * consequences: it supports no job control and it has a filesystem + * without "." and ".." !!! + */ +char * +xgetcwd(char *pathname, size_t pathlen) +{ + char pathbuf[MAXPATHLEN]; /* temporary pathname buffer */ + char *pnptr = &pathbuf[(sizeof pathbuf)-1]; /* pathname pointer */ + dev_t rdev; /* root device number */ + DIR *dirp = NULL; /* directory stream */ + ino_t rino; /* root inode number */ + off_t rsize; /* root size */ + struct direct *dir; /* directory entry struct */ + struct stat d, dd; /* file status struct */ + int serrno; + + *pnptr = '\0'; + (void) stat("/.", &d); + rdev = d.st_dev; + rino = d.st_ino; + rsize = d.st_size; + for (;;) { + if (stat(".", &d) == -1) { + (void) xsnprintf(pathname, pathlen, CGETS(23, 24, + "getcwd: Cannot stat \".\" (%s)"), strerror(errno)); + goto fail; + } + if (d.st_ino == rino && d.st_dev == rdev && d.st_size == rsize) + break; /* reached root directory */ + if ((dirp = opendir("..")) == NULL) { + (void) xsnprintf(pathname, pathlen, CGETS(23, 19, + "getcwd: Cannot open \"..\" (%s)"), strerror(errno)); + goto fail; + } + if (chdir("..") == -1) { + (void) xsnprintf(pathname, pathlen, CGETS(23, 20, + "getcwd: Cannot chdir to \"..\" (%s)"), strerror(errno)); + goto fail; + } + do { + if ((dir = readdir(dirp)) == NULL) { + (void) xsnprintf(pathname, pathlen, + CGETS(23, 21, "getcwd: Read error in \"..\" (%s)"), + strerror(errno)); + goto fail; + } + if (stat(dir->d_name, &dd) == -1) { + (void) xsnprintf(pathname, pathlen, + CGETS(23, 25, "getcwd: Cannot stat directory \"%s\" (%s)"), + dir->d_name, strerror(errno)); + goto fail; + } + } while (dd.st_ino != d.st_ino || + dd.st_dev != d.st_dev || + dd.st_size != d.st_size); + closedir(dirp); + dirp = NULL; + pnptr = strnrcpy(dirp->d_name, pnptr, pnptr - pathbuf); + pnptr = strnrcpy("/", pnptr, pnptr - pathbuf); + } + + if (*pnptr == '\0') /* current dir == root dir */ + (void) strncpy(pathname, "/", pathlen); + else { + (void) strncpy(pathname, pnptr, pathlen); + pathname[pathlen - 1] = '\0'; + if (chdir(pnptr) == -1) { + (void) xsnprintf(pathname, MAXPATHLEN, CGETS(23, 22, + "getcwd: Cannot change back to \".\" (%s)"), + strerror(errno)); + return NULL; + } + } + return pathname; + +fail: + serrno = errno; + (void) chdir(strnrcpy(".", pnptr, pnptr - pathbuf)); + errno = serrno; + return NULL; +} + +# else /* ! hp9000s500 */ + + +char * +xgetcwd(char *pathname, size_t pathlen) +{ + DIR *dp; + struct dirent *d; + + struct stat st_root, st_cur, st_next, st_dotdot; + char pathbuf[MAXPATHLEN], nextpathbuf[MAXPATHLEN * 2]; + char *pathptr, *nextpathptr, *cur_name_add; + int save_errno = 0; + + /* find the inode of root */ + if (stat("/", &st_root) == -1) { + (void) xsnprintf(pathname, pathlen, CGETS(23, 23, + "getcwd: Cannot stat \"/\" (%s)"), + strerror(errno)); + return NULL; + } + pathbuf[MAXPATHLEN - 1] = '\0'; + pathptr = &pathbuf[MAXPATHLEN - 1]; + nextpathbuf[MAXPATHLEN - 1] = '\0'; + cur_name_add = nextpathptr = &nextpathbuf[MAXPATHLEN - 1]; + + /* find the inode of the current directory */ + if (lstat(".", &st_cur) == -1) { + (void) xsnprintf(pathname, pathlen, CGETS(23, 24, + "getcwd: Cannot stat \".\" (%s)"), + strerror(errno)); + return NULL; + } + nextpathptr = strnrcpy(nextpathptr, "../", nextpathptr - nextpathbuf); + + /* Descend to root */ + for (;;) { + + /* look if we found root yet */ + if (st_cur.st_ino == st_root.st_ino && + DEV_DEV_COMPARE(st_cur.st_dev, st_root.st_dev)) { + (void) strncpy(pathname, *pathptr != '/' ? "/" : pathptr, pathlen); + pathname[pathlen - 1] = '\0'; + return pathname; + } + + /* open the parent directory */ + if (stat(nextpathptr, &st_dotdot) == -1) { + (void) xsnprintf(pathname, pathlen, CGETS(23, 25, + "getcwd: Cannot stat directory \"%s\" (%s)"), + nextpathptr, strerror(errno)); + return NULL; + } + if ((dp = opendir(nextpathptr)) == NULL) { + (void) xsnprintf(pathname, pathlen, CGETS(23, 26, + "getcwd: Cannot open directory \"%s\" (%s)"), + nextpathptr, strerror(errno)); + return NULL; + } + + /* look in the parent for the entry with the same inode */ + if (DEV_DEV_COMPARE(st_dotdot.st_dev, st_cur.st_dev)) { + /* Parent has same device. No need to stat every member */ + for (d = readdir(dp); d != NULL; d = readdir(dp)) { +#ifdef __clipper__ + if (((unsigned long)d->d_ino & 0xffff) == st_cur.st_ino) + break; +#else + if (d->d_ino == st_cur.st_ino) + break; +#endif + } + } + else { + /* + * Parent has a different device. This is a mount point so we + * need to stat every member + */ + for (d = readdir(dp); d != NULL; d = readdir(dp)) { + if (ISDOT(d->d_name) || ISDOTDOT(d->d_name)) + continue; + (void)strncpy(cur_name_add, d->d_name, + (size_t) (&nextpathbuf[sizeof(nextpathbuf) - 1] - cur_name_add)); + if (lstat(nextpathptr, &st_next) == -1) { + /* + * We might not be able to stat() some path components + * if we are using afs, but this is not an error as + * long as we find the one we need; we also save the + * first error to report it if we don't finally succeed. + */ + if (save_errno == 0) + save_errno = errno; + continue; + } + /* check if we found it yet */ + if (st_next.st_ino == st_cur.st_ino && + DEV_DEV_COMPARE(st_next.st_dev, st_cur.st_dev)) + break; + } + } + if (d == NULL) { + (void) xsnprintf(pathname, pathlen, CGETS(23, 27, + "getcwd: Cannot find \".\" in \"..\" (%s)"), + strerror(save_errno ? save_errno : ENOENT)); + closedir(dp); + return NULL; + } + else + save_errno = 0; + st_cur = st_dotdot; + pathptr = strnrcpy(pathptr, d->d_name, pathptr - pathbuf); + pathptr = strnrcpy(pathptr, "/", pathptr - pathbuf); + nextpathptr = strnrcpy(nextpathptr, "../", nextpathptr - nextpathbuf); + *cur_name_add = '\0'; + closedir(dp); + } +} /* end getcwd */ +# endif /* hp9000s500 */ + +/* strnrcpy(): + * Like strncpy, going backwards and returning the new pointer + */ +static char * +strnrcpy(char *ptr, char *str, size_t siz) +{ + int len = strlen(str); + if (siz == 0) + return ptr; + + while (len && siz--) + *--ptr = str[--len]; + + return (ptr); +} /* end strnrcpy */ +#endif /* !HAVE_GETCWD */ + +#ifdef apollo +/*** + *** Domain/OS + ***/ +#include <apollo/base.h> +#include <apollo/loader.h> +#include <apollo/error.h> + + +static char * +apperr(status_$t *st) +{ + static char *buf; /* = NULL */ + short e_subl, e_modl, e_codel; + error_$string_t e_sub, e_mod, e_code; + + error_$get_text(*st, e_sub, &e_subl, e_mod, &e_modl, e_code, &e_codel); + e_sub[e_subl] = '\0'; + e_code[e_codel] = '\0'; + e_mod[e_modl] = '\0'; + xfree(buf); + buf = xasprintf("%s (%s/%s)", e_code, e_sub, e_mod); + + return(buf); +} + +static int +llib(Char *s) +{ + short len = Strlen(s); + status_$t st; + char *t; + + loader_$inlib(t = short2str(s), len, &st); + if (st.all != status_$ok) + stderror(ERR_SYSTEM, t, apperr(&st)); +} + +/*ARGSUSED*/ +void +doinlib(Char **v, struct command *c) +{ + Char **globbed; + + setname(short2str(*v++)); + v = glob_all_or_error(v); + globbed = v; + cleanup_push(globbed, blk_cleanup); + + while (v && *v) + llib(*v++); + cleanup_until(globbed); +} + +int +getv(Char *v) +{ + if (eq(v, STRbsd43)) + return(1); + else if (eq(v, STRsys53)) + return(0); + else + stderror(ERR_NAME | ERR_SYSTEM, short2str(v), + CGETS(23, 28, "Invalid system type")); + /*NOTREACHED*/ + return(0); +} + +/*ARGSUSED*/ +void +dover(Char **v, struct command *c) +{ + Char *p; + + setname(short2str(*v++)); + if (!*v) { + if (!(p = tgetenv(STRSYSTYPE))) + stderror(ERR_NAME | ERR_STRING, + CGETS(23, 29, "System type is not set")); + xprintf("%S\n", p); + } + else { + tsetenv(STRSYSTYPE, getv(*v) ? STRbsd43 : STRsys53); + dohash(NULL, NULL); + } +} + +/* + * Many thanks to rees@citi.umich.edu (Jim Rees) and + * mathys@ssdt-tempe.sps.mot.com (Yves Mathys) + * For figuring out how to do this... I could have never done + * it without their help. + */ +typedef short enum { + name_$wdir_type, + name_$ndir_type, + name_$node_dir_type, +} name_$dir_type_t; + +/*ARGSUSED*/ +void +dorootnode(Char **v, struct command *c) +{ + name_$dir_type_t dirtype = name_$node_dir_type; + uid_$t uid; + status_$t st; + char *name; + short namelen; + + setname(short2str(*v++)); + + name = short2str(*v); + namelen = strlen(name); + + name_$resolve(name, &namelen, &uid, &st); + if (st.all != status_$ok) + stderror(ERR_SYSTEM, name, apperr(&st)); + namelen = 0; + name_$set_diru(&uid, "", &namelen, &dirtype, &st); + if (st.all != status_$ok) + stderror(ERR_SYSTEM, name, apperr(&st)); + dohash(NULL, NULL); +} + +int +isapad(void) +{ + static int res = -1; + static status_$t st; + + if (res == -1) { + int strm; + if (isatty(0)) + strm = 0; + if (isatty(1)) + strm = 1; + if (isatty(2)) + strm = 2; + else { + res = 0; + st.all = status_$ok; + return(res); + } + res = stream_$isavt(&strm, &st); + res = res ? 1 : 0; + } + else { + if (st.all != status_$ok) + stderror(ERR_SYSTEM, "stream_$isavt", apperr(&st)); + } + return(res); +} +#endif + +#ifdef __ANDROID__ +#include <stdio.h> +/* Android (<= 2.1?) has an incomplete ttyname implementation. */ +char * +ttyname(int fd) +{ + char path[64]; + ssize_t siz; + static char ttyname[32]; + + if (!isatty(fd)) + return NULL; + + (void)snprintf(path, sizeof(path), "/proc/self/fd/%d", fd); + siz = readlink(path, ttyname, sizeof(ttyname)); + if (siz < 0 || siz == sizeof(ttyname)) + return NULL; + ttyname[siz] = '\0'; + return ttyname; +} +#endif /* __ANDROID__ */ + +#if defined(__CYGWIN__) && !defined(NO_CRYPT) +#undef CHAR /* Collides with Win32 API */ +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#include <sys/cygwin.h> +char * +cygwin_xcrypt(struct passwd *pw, const char *password, const char *expected_pwd) +{ + static char invalid_password[] = "\377"; + HANDLE token = cygwin_logon_user(pw, password); + if (token == INVALID_HANDLE_VALUE) + return invalid_password; + CloseHandle(token); + return (char *) expected_pwd; +} +#endif /* __CYGWIN__ && !NO_CRYPT */ |