diff options
author | obrien <obrien@FreeBSD.org> | 2000-04-15 04:41:27 +0000 |
---|---|---|
committer | obrien <obrien@FreeBSD.org> | 2000-04-15 04:41:27 +0000 |
commit | 4ad28cefef28ce6bdb44a0532cfe20a2076bc694 (patch) | |
tree | 7679c440a91912ee9586cee3ebab24596c0fe1c4 /contrib/tcsh/tc.os.c | |
download | FreeBSD-src-4ad28cefef28ce6bdb44a0532cfe20a2076bc694.zip FreeBSD-src-4ad28cefef28ce6bdb44a0532cfe20a2076bc694.tar.gz |
Import the latest version of the 44BSD C-shell -- tcsh-6.09.
Diffstat (limited to 'contrib/tcsh/tc.os.c')
-rw-r--r-- | contrib/tcsh/tc.os.c | 1474 |
1 files changed, 1474 insertions, 0 deletions
diff --git a/contrib/tcsh/tc.os.c b/contrib/tcsh/tc.os.c new file mode 100644 index 0000000..b2af5f6 --- /dev/null +++ b/contrib/tcsh/tc.os.c @@ -0,0 +1,1474 @@ +/* $Header: /src/pub/tcsh/tc.os.c,v 3.50 1998/10/25 15:10:35 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. 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("$Id: tc.os.c,v 3.50 1998/10/25 15:10:35 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(arglist, c) + Char **arglist; + struct command *c; +{ + extern char *getenv(); + sigmask_t omask; + Char **pathvars, **cmdargs; + char **spaths, **cpaths, **cmds; + char *tcp; + unsigned int npaths, ncmds; + int i, sysflag; + + omask = sigsetmask(sigmask(SIGINT)); + + /* + * 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 = (char **) xmalloc((size_t) npaths * sizeof *spaths); + setzero((char *) spaths, npaths * sizeof *spaths); + cpaths = (char **) xmalloc((size_t) (npaths + 1) * sizeof *cpaths); + setzero((char *) cpaths, (npaths + 1) * sizeof *cpaths); + cmds = (char **) xmalloc((size_t) (ncmds + 1) * sizeof *cmds); + setzero((char *) cmds, (ncmds + 1) * sizeof *cmds); + for (i = 0; i < npaths; i++) { + char *val = getenv(short2str(pathvars[i])); + + if (val == NULL) + val = ""; + + spaths[i] = (char *) xmalloc((size_t) (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); + + if (val == NULL) + goto abortpath; + cmds[i] = (char *) xmalloc((size_t) Strlen(val) + 1); + (void) strcpy(cmds[i], short2str(val)); + } + + + if (setpath(cpaths, cmds, LOCALSYSPATH, sysflag, 1) < 0) { +abortpath: + if (spaths) { + for (i = 0; i < npaths; i++) + if (spaths[i]) + xfree((ptr_t) spaths[i]); + xfree((ptr_t) spaths); + } + if (cpaths) + xfree((ptr_t) cpaths); + if (cmds) { + for (i = 0; i < ncmds; i++) + if (cmds[i]) + xfree((ptr_t) cmds[i]); + xfree((ptr_t) cmds); + } + + (void) sigsetmask(omask); + 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); + if (Strcmp(name, STRKPATH) == 0) { + importpath(val); + if (havhash) + dohash(NULL, NULL); + } + *--val = '='; + } + } + (void) sigsetmask(omask); + donefds(); +} +#endif /* MACH */ + +/*** + *** AIX + ***/ +#ifdef TCF +/* ARGSUSED */ +void +dogetxvers(v, c) + 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(v, c) + 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(xcid) + 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(xcname) + 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(v, c) + 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(v, c) + 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) + 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(pid, new_site) + pid_t pid; + siteno_t new_site; +{ + struct sf *st; + int need_local; + + need_local = (pid == 0) || (pid == getpid()); + + if (kill3((pid_t) 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(v, c) + 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; + sigmask_t omask; + +#ifdef BSDSIGS + omask = sigmask(SIGCHLD); + if (setintr) + omask |= sigmask(SIGINT); + omask = sigblock(omask) & ~omask; +#else + if (setintr) + (void) sighold(SIGINT); + (void) sighold(SIGCHLD); +#endif /* BSDSIGS */ + + ++v; + if (*v[0] == '-') { + /* + * Do the -site. + */ + s = short2str(&v[0][1]); + /* + * see comment in setspath() + */ + dont_free = 1; + if ((st = sfname(s)) == NULL) { + 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 { + gflag = 0, tglob(v); + if (gflag) { + v = globall(v); + if (v == 0) + stderror(ERR_NAME | ERR_NOMATCH); + } + else { + v = gargv = saveblk(v); + trim(v); + } + + while (v && (cp = *v)) { + if (*cp == '%') { + pp = pfind(cp); + if (kill3((pid_t) - 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++; + } + if (gargv) + blkfree(gargv), gargv = 0; + } + +done: +#ifdef BSDSIGS + (void) sigsetmask(omask); +#else + (void) sigrelse(SIGCHLD); + if (setintr) + (void) sigrelse(SIGINT); +#endif /* BSDSIGS */ + 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(v, c) + 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 sigret_t +catch_sigsys() +{ + longjmp(sigsys_buf, 1); +} + + +/*ARGSUSED*/ +void +dowarp(v, c) + Char **v; + struct command *c; +{ + int warp, oldwarp; + struct warpent *we; + void (*old_sigsys_handler) () = 0; + char *newwarp; + + if (setjmp(sigsys_buf)) { + signal(SIGSYS, old_sigsys_handler); + stderror(ERR_NAME | ERR_STRING, + CGETS(23, 8, "You're trapped in a universe you never made")); + return; + } + 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")); + } + } + signal(SIGSYS, old_sigsys_handler); + return; +} +#endif /* WARP */ + +/*** + *** Masscomp or HCX + ***/ +/* Added, DAS DEC-90. */ +#if defined(masscomp) || defined(_CX_UX) +/*ARGSUSED*/ +void +douniverse(v, c) + register Char **v; + struct command *c; +{ + register Char *cp = v[1]; + register Char *cp2; /* dunno how many elements v comes in with */ + char ubuf[100]; +#ifdef BSDSIGS + register sigmask_t omask = 0; +#endif /* BSDSIGS */ + + 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")); + if (setintr) +#ifdef BSDSIGS + omask = sigblock(sigmask(SIGINT)) & ~sigmask(SIGINT); +#else /* !BSDSIGS */ + (void) sighold(SIGINT); +#endif /* BSDSIGS */ + lshift(v, 2); + if (setintr) +#ifdef BSDSIGS + (void) sigsetmask(omask); +#else /* !BSDSIGS */ + (void) sigrelse (SIGINT); +#endif /* BSDSIGS */ + reexecute(c); + (void) setuniverse(ubuf); + } + } +} +#endif /* masscomp || _CX_UX */ + +#if defined(_CX_UX) +/*ARGSUSED*/ +void +doatt(v, c) + register Char **v; + struct command *c; +{ + register Char *cp = v[1]; + char ubuf[100]; +#ifdef BSDSIGS + register sigmask_t omask = 0; +#endif /* BSDSIGS */ + + if (cp == 0) + (void) setuniverse("att"); + else { + (void) getuniverse(ubuf); + (void) setuniverse("att"); + if (setintr) +#ifdef BSDSIGS + omask = sigblock(sigmask(SIGINT)) & ~sigmask(SIGINT); +#else /* !BSDSIGS */ + (void) sighold(SIGINT); +#endif /* BSDSIGS */ + lshift(v, 1); + if (setintr) +#ifdef BSDSIGS + (void) sigsetmask(omask); +#else /* !BSDSIGS */ + (void) sigrelse (SIGINT); +#endif /* BSDSIGS */ + reexecute(c); + (void) setuniverse(ubuf); + } +} + +/*ARGSUSED*/ +void +doucb(v, c) + register Char **v; + struct command *c; +{ + register Char *cp = v[1]; + char ubuf[100]; +#ifdef BSDSIGS + register sigmask_t omask = 0; +#endif /* BSDSIGS */ + + if (cp == 0) + (void) setuniverse("ucb"); + else { + (void) getuniverse(ubuf); + (void) setuniverse("ucb"); + if (setintr) +#ifdef BSDSIGS + omask = sigblock(sigmask(SIGINT)) & ~sigmask(SIGINT); +#else /* !BSDSIGS */ + (void) sighold(SIGINT); +#endif /* BSDSIGS */ + lshift(v, 1); + if (setintr) +#ifdef BSDSIGS + (void) sigsetmask(omask); +#else /* !BSDSIGS */ + (void) sigrelse (SIGINT); +#endif /* BSDSIGS */ + reexecute(c); + (void) setuniverse(ubuf); + } +} +#endif /* _CX_UX */ + +#ifdef _SEQUENT_ +/* + * Compute the difference in process stats. + */ +void +pr_stat_sub(p2, p1, pr) + struct process_stats *p2, *p1, *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_ */ + + +#ifdef NEEDmemset +/* This is a replacement for a missing memset function */ +ptr_t xmemset(loc, value, len) + ptr_t loc; + int len; + size_t value; +{ + char *ptr = (char *) loc; + + while (len--) + *ptr++ = value; + return loc; +} +#endif /* NEEDmemset */ + + +#ifdef NEEDmemmove +/* memmove(): + * This is the ANSI form of bcopy() with the arguments backwards... + * Unlike memcpy(), it handles overlaps between source and + * destination memory + */ +ptr_t +xmemmove(vdst, vsrc, len) + ptr_t vdst; + const ptr_t vsrc; + size_t len; +{ + const char *src = (const char *) vsrc; + char *dst = (char *) 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 /* NEEDmemmove */ + + +#ifndef WINNT +#ifdef tcgetpgrp +int +xtcgetpgrp(fd) + 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(fd, pgrp) + int fd, pgrp; +{ + return ioctl(fd, TIOCSPGRP, (ioctl_t) &pgrp); +} + +#endif /* tcgetpgrp */ +#endif /* WINNT */ + + +#ifdef YPBUGS +void +fix_yp_bugs() +{ + char *mydomain; + + extern int yp_get_default_domain __P((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 __P((const char *)); + + yp_unbind(mydomain); + } +} + +#endif /* YPBUGS */ + +#ifdef STRCOLLBUG +void +fix_strcoll_bug() +{ +#if defined(NLS) && !defined(NOSTRCOLL) + /* + * 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 = open(root, O_RDONLY); + + (void) strcoll(root, root); + + if (fd != -1) + (void) close(fd); +#endif +} +#endif /* STRCOLLBUG */ + + +#ifdef OREO +#include <compat.h> +#endif /* OREO */ + +void +osinit() +{ +#ifdef OREO + set42sig(); + setcompat(getcompat() & ~COMPAT_EXEC); + sigignore(SIGIO); /* ignore SIGIO */ +#endif /* OREO */ + +#ifdef aiws + { + struct sigstack inst; + inst.ss_sp = (char *) xmalloc((size_t) 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 */ +} + +#ifdef strerror +char * +xstrerror(i) + int i; +{ + static char errbuf[128]; + + if (i >= 0 && i < sys_nerr) { + return sys_errlist[i]; + } else { + (void) xsnprintf(errbuf, sizeof(errbuf), + CGETS(23, 13, "Unknown Error: %d"), i); + return errbuf; + } +} +#endif /* strerror */ + +#ifdef gethostname +# if !defined(_MINIX) && !defined(__EMX__) && !defined(WINNT) +# include <sys/utsname.h> +# endif /* !_MINIX && !__EMX__ && !WINNT */ + +int +xgethostname(name, namlen) + char *name; + int namlen; +{ +# if !defined(_MINIX) && !defined(__EMX__) && !defined(WINNT) + 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 /* gethostname */ + +#ifdef 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(incr) + 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 /* nice */ + +#ifdef NEEDgetcwd +static char *strnrcpy __P((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(pathname, pathlen) + char *pathname; + size_t pathlen; +{ + char pathbuf[MAXNAMLEN]; /* 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); + (void) 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 */ + +# if (SYSVREL != 0 && !defined(d_fileno)) || defined(_VMS_POSIX) || defined(WINNT) +# define d_fileno d_ino +# endif + +char * +xgetcwd(pathname, pathlen) + 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_fileno & 0xffff) == st_cur.st_ino) + break; +#else + if (d->d_fileno == 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)); + (void) 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'; + (void) closedir(dp); + } +} /* end getcwd */ +# endif /* hp9000s500 */ + +/* strnrcpy(): + * Like strncpy, going backwards and returning the new pointer + */ +static char * +strnrcpy(ptr, str, siz) + register char *ptr, *str; + size_t siz; +{ + register int len = strlen(str); + if (siz == 0) + return ptr; + + while (len && siz--) + *--ptr = str[--len]; + + return (ptr); +} /* end strnrcpy */ +#endif /* getcwd */ + +#ifdef apollo +/*** + *** Domain/OS + ***/ +#include <apollo/base.h> +#include <apollo/loader.h> +#include <apollo/error.h> + + +static char * +apperr(st) + status_$t *st; +{ + static char buf[BUFSIZE]; + 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'; + (void) xsnprintf(buf, sizeof(buf), "%s (%s/%s)", e_code, e_sub, e_mod); + + return(buf); +} + +static int +llib(s) + 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(v, c) + Char **v; + struct command *c; +{ + setname(short2str(*v++)); + gflag = 0, tglob(v); + if (gflag) { + v = globall(v); + if (v == 0) + stderror(ERR_NAME | ERR_NOMATCH); + } + else { + v = gargv = saveblk(v); + trim(v); + } + + while (v && *v) + llib(*v++); + if (gargv) + blkfree(gargv), gargv = 0; +} + +int +getv(v) + 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(v, c) + 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(v, c) + 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() +{ + 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 |