/* * 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 1.1.1.1 2001/07/18 11:06:05 root 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 #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 #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 (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 #include 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 * 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 #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 # 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 */ # undef _MINIX /* redefined in */ # undef HZ /* redefined in */ # include # 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 * 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 #include #include 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