1 /* $Header: /src/pub/tcsh/tc.os.c,v 3.52 2000/11/11 23:03:39 christos Exp $ */
3 * tc.os.c: OS Dependent builtin functions
6 * Copyright (c) 1980, 1991 The Regents of the University of California.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by the University of
20 * California, Berkeley and its contributors.
21 * 4. Neither the name of the University nor the names of its contributors
22 * may be used to endorse or promote products derived from this software
23 * without specific prior written permission.
25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 RCSID("$Id: tc.os.c,v 3.52 2000/11/11 23:03:39 christos Exp $")
43 #include "ed.defns.h" /* for the function names */
47 #define TIOCGPGRP TIOCGETPGRP
48 #define TIOCSPGRP TIOCSETPGRP
56 /* dosetpath -- setpath built-in command
58 **********************************************************************
60 * 08-May-88 Richard Draves (rpd) at Carnegie-Mellon University
61 * Major changes to remove artificial limits on sizes and numbers
64 **********************************************************************
68 static Char STRCPATH[] = {'C', 'P', 'A', 'T', 'H', '\0'};
69 static Char STRLPATH[] = {'L', 'P', 'A', 'T', 'H', '\0'};
70 static Char STRMPATH[] = {'M', 'P', 'A', 'T', 'H', '\0'};
72 static Char STREPATH[] = {'E', 'P', 'A', 'T', 'H', '\0'};
75 static Char *syspaths[] = {STRKPATH, STRCPATH, STRLPATH, STRMPATH,
81 #define LOCALSYSPATH "/usr/local"
89 extern char *getenv();
91 Char **pathvars, **cmdargs;
92 char **spaths, **cpaths, **cmds;
94 unsigned int npaths, ncmds;
97 omask = sigsetmask(sigmask(SIGINT));
100 * setpath(3) uses stdio and we want 0, 1, 2 to work...
103 (void) dcopy(SHIN, 0);
104 (void) dcopy(SHOUT, 1);
105 (void) dcopy(SHDIAG, 2);
109 for (i = 1; arglist[i] && (arglist[i][0] != '-'); i++);
112 cmdargs = &arglist[i];
113 for (; arglist[i]; i++);
114 ncmds = i - npaths - 1;
118 pathvars = &arglist[1];
122 npaths = (sizeof syspaths / sizeof *syspaths) - 1;
126 /* note that npaths != 0 */
128 spaths = (char **) xmalloc((size_t) npaths * sizeof *spaths);
129 setzero((char *) spaths, npaths * sizeof *spaths);
130 cpaths = (char **) xmalloc((size_t) (npaths + 1) * sizeof *cpaths);
131 setzero((char *) cpaths, (npaths + 1) * sizeof *cpaths);
132 cmds = (char **) xmalloc((size_t) (ncmds + 1) * sizeof *cmds);
133 setzero((char *) cmds, (ncmds + 1) * sizeof *cmds);
134 for (i = 0; i < npaths; i++) {
135 char *val = getenv(short2str(pathvars[i]));
140 spaths[i] = (char *) xmalloc((size_t) (Strlen(pathvars[i]) +
141 strlen(val) + 2) * sizeof **spaths);
142 (void) strcpy(spaths[i], short2str(pathvars[i]));
143 (void) strcat(spaths[i], "=");
144 (void) strcat(spaths[i], val);
145 cpaths[i] = spaths[i];
148 for (i = 0; i < ncmds; i++) {
149 Char *val = globone(cmdargs[i], G_ERROR);
153 cmds[i] = (char *) xmalloc((size_t) Strlen(val) + 1);
154 (void) strcpy(cmds[i], short2str(val));
158 if (setpath(cpaths, cmds, LOCALSYSPATH, sysflag, 1) < 0) {
161 for (i = 0; i < npaths; i++)
163 xfree((ptr_t) spaths[i]);
164 xfree((ptr_t) spaths);
167 xfree((ptr_t) cpaths);
169 for (i = 0; i < ncmds; i++)
171 xfree((ptr_t) cmds[i]);
175 (void) sigsetmask(omask);
180 for (i = 0; i < npaths; i++) {
183 name = str2short(cpaths[i]);
184 for (val = str2short(cpaths[i]); val && *val && *val != '='; val++);
185 if (val && *val == '=') {
189 if (Strcmp(name, STRKPATH) == 0) {
197 (void) sigsetmask(omask);
212 char xvers[MAXPATHLEN];
214 if (getxvers(xvers, MAXPATHLEN) == -1)
215 stderror(ERR_SYSTEM, "getxvers", strerror(errno));
216 xprintf("%s\n", xvers);
229 if (!*v || *v[0] == '\0')
232 xvers = short2str(*v);
233 if (setxvers(xvers) == -1)
234 stderror(ERR_SYSTEM, "setxvers", strerror(errno));
239 # define XC_PDP11 0x01
242 # define XC_8086 0x04
246 # define XC_16032 0x08
249 # define XC_S370 0x0b
251 # include <sys/x.out.h>
254 static struct xc_cpu_t {
259 { XC_PDP11, "pdp11" },
263 { XC_68K, "mc68000" },
266 { XC_16032, "ns16032" },
269 { XC_S370, "xa370" },
274 * our local hack table, stolen from x.out.h
282 for (i = 0; xcpu[i].xc_name != NULL; i++)
283 if (xcpu[i].xc_id == xcid)
284 return (xcpu[i].xc_name);
294 for (i = 0; xcpu[i].xc_name != NULL; i++)
295 if (strcmp(xcpu[i].xc_name, xcname) == 0)
296 return (xcpu[i].xc_id);
308 sitepath_t p[MAXSITE];
310 static char *local = "LOCAL ";
312 if ((j = getspath(p, MAXSITE)) == -1)
313 stderror(ERR_SYSTEM, "getspath", strerror(errno));
314 for (i = 0; i < j && (p[i] & SPATH_CPU) != NOSITE; i++) {
315 if (p[i] & SPATH_CPU) {
316 if ((p[i] & SPATH_MASK) == NULLSITE)
318 else if ((st = sfxcode((short) (p[i] & SPATH_MASK))) != NULL)
319 xprintf("%s ", st->sf_ctype);
321 char *xc = getxcode(p[i] & SPATH_MASK);
326 xprintf("*cpu %d* ", (int) (p[i] & SPATH_MASK));
328 * BUG in the aix code... needs that cause if
329 * sfxcode fails once it fails for ever
335 if (p[i] == NULLSITE)
337 else if ((st = sfnum(p[i])) != NULL)
338 xprintf("%s ", st->sf_sname);
340 xprintf("*site %d* ", (int) (p[i] & SPATH_MASK));
356 sitepath_t p[MAXSITE];
360 * sfname() on AIX G9.9 at least, mallocs too pointers p, q
361 * then does the equivalent of while (*p++ == *q++) continue;
362 * and then tries to free(p,q) them! Congrats to the wizard who
363 * wrote that one. I bet he tested it really well too.
364 * Sooo, we set dont_free :-)
367 for (i = 0, v++; *v && *v[0] != '\0'; v++, i++) {
371 else if (strcmp(s, "LOCAL") == 0)
373 else if ((st = sfctype(s)) != NULL)
374 p[i] = SPATH_CPU | st->sf_ccode;
375 else if ((j = getxid(s)) != -1)
376 p[i] = SPATH_CPU | j;
377 else if ((st = sfname(s)) != NULL)
381 stderror(ERR_NAME | ERR_STRING, CGETS(23, 1, "Bad cpu/site name"));
383 if (i == MAXSITE - 1)
384 stderror(ERR_NAME | ERR_STRING, CGETS(23, 2, "Site path too long"));
386 if (setspath(p, i) == -1)
387 stderror(ERR_SYSTEM, "setspath", strerror(errno));
392 * Return the site name where the process is running
401 if ((ss = site(pid)) == -1 || (st = sfnum(ss)) == NULL)
402 return CGETS(23, 3, "unknown");
408 migratepid(pid, new_site)
415 need_local = (pid == 0) || (pid == getpid());
417 if (kill3((pid_t) pid, SIGMIGRATE, new_site) < 0) {
418 xprintf("%d: %s\n", pid, strerror(errno));
423 if ((new_site = site(0)) == -1) {
424 xprintf(CGETS(23, 4, "site: %s\n"), strerror(errno));
427 if ((st = sfnum(new_site)) == NULL) {
428 xprintf(CGETS(23, 5, "%d: Site not found\n"), new_site);
431 if (setlocal(st->sf_local, strlen(st->sf_local)) == -1) {
432 xprintf(CGETS(23, 6, "setlocal: %s: %s\n"),
433 st->sf_local, strerror(errno));
452 siteno_t new_site = 0;
456 omask = sigmask(SIGCHLD);
458 omask |= sigmask(SIGINT);
459 omask = sigblock(omask) & ~omask;
462 (void) sighold(SIGINT);
463 (void) sighold(SIGCHLD);
471 s = short2str(&v[0][1]);
473 * see comment in setspath()
476 if ((st = sfname(s)) == NULL) {
478 stderror(ERR_NAME | ERR_STRING, CGETS(23, 7, "Site not found"));
481 new_site = st->sf_id;
485 if (!*v || *v[0] == '\0') {
486 if (migratepid(0, new_site) == -1)
494 stderror(ERR_NAME | ERR_NOMATCH);
497 v = gargv = saveblk(v);
501 while (v && (cp = *v)) {
504 if (kill3((pid_t) - pp->p_jobid, SIGMIGRATE, new_site) < 0) {
505 xprintf("%S: %s\n", cp, strerror(errno));
509 else if (!(Isdigit(*cp) || *cp == '-'))
510 stderror(ERR_NAME | ERR_JOBARGS);
512 pid = atoi(short2str(cp));
513 if (migratepid(pid, new_site) == -1)
519 blkfree(gargv), gargv = 0;
524 (void) sigsetmask(omask);
526 (void) sigrelse(SIGCHLD);
528 (void) sigrelse(SIGINT);
531 stderror(ERR_SILENT);
537 *** CRAY ddmode <velo@sesun3.epfl.ch> (Martin Ouwehand EPFL-SIC/SE)
539 #if defined(_CRAY) && !defined(_CRAYMPP)
554 xprintf("%d\n",mode);
558 stderror(ERR_NAME | ERR_STRING,
559 CGETS(23, 30, "Too many arguments"));
569 stderror(ERR_NAME | ERR_STRING,
570 CGETS(23, 31, "Invalid argument"));
574 #endif /* _CRAY && !_CRAYMPP */
583 * handle the funky warping of symlinks
586 #include <sys/warp.h>
588 static jmp_buf sigsys_buf;
593 longjmp(sigsys_buf, 1);
605 void (*old_sigsys_handler) () = 0;
608 if (setjmp(sigsys_buf)) {
609 signal(SIGSYS, old_sigsys_handler);
610 stderror(ERR_NAME | ERR_STRING,
611 CGETS(23, 8, "You're trapped in a universe you never made"));
614 old_sigsys_handler = signal(SIGSYS, catch_sigsys);
619 if (*v == 0) { /* display warp value */
621 stderror(ERR_NAME | ERR_STRING, CGETS(23, 9, "Getwarp failed"));
622 we = getwarpbyvalue(warp);
624 printf("%s\n", we->w_name);
626 printf("%d\n", warp);
628 else { /* set warp value */
630 newwarp = short2str(*v);
632 warp = atoi(newwarp);
634 we = getwarpbyname(newwarp);
640 if ((warp < 0) || (warp >= WARP_MAXLINK))
641 stderror(ERR_NAME | ERR_STRING, CGETS(23, 10, "Invalid warp"));
642 if ((setwarp(warp) < 0) || (getwarp() != warp)) {
643 (void) setwarp(oldwarp);
644 stderror(ERR_NAME | ERR_STRING, CGETS(23, 11, "Setwarp failed"));
647 signal(SIGSYS, old_sigsys_handler);
655 /* Added, DAS DEC-90. */
656 #if defined(masscomp) || defined(_CX_UX)
663 register Char *cp = v[1];
664 register Char *cp2; /* dunno how many elements v comes in with */
667 register sigmask_t omask = 0;
671 (void) getuniverse(ubuf);
672 xprintf("%s\n", ubuf);
677 if (*cp == '\0' || setuniverse(short2str(cp)) != 0)
678 stderror(ERR_NAME | ERR_STRING, CGETS(23, 12, "Illegal universe"));
681 (void) getuniverse(ubuf);
682 if (*cp == '\0' || setuniverse(short2str(cp)) != 0)
683 stderror(ERR_NAME | ERR_STRING, CGETS(23, 12, "Illegal universe"));
686 omask = sigblock(sigmask(SIGINT)) & ~sigmask(SIGINT);
688 (void) sighold(SIGINT);
693 (void) sigsetmask(omask);
695 (void) sigrelse (SIGINT);
698 (void) setuniverse(ubuf);
702 #endif /* masscomp || _CX_UX */
711 register Char *cp = v[1];
714 register sigmask_t omask = 0;
718 (void) setuniverse("att");
720 (void) getuniverse(ubuf);
721 (void) setuniverse("att");
724 omask = sigblock(sigmask(SIGINT)) & ~sigmask(SIGINT);
726 (void) sighold(SIGINT);
731 (void) sigsetmask(omask);
733 (void) sigrelse (SIGINT);
736 (void) setuniverse(ubuf);
746 register Char *cp = v[1];
749 register sigmask_t omask = 0;
753 (void) setuniverse("ucb");
755 (void) getuniverse(ubuf);
756 (void) setuniverse("ucb");
759 omask = sigblock(sigmask(SIGINT)) & ~sigmask(SIGINT);
761 (void) sighold(SIGINT);
766 (void) sigsetmask(omask);
768 (void) sigrelse (SIGINT);
771 (void) setuniverse(ubuf);
778 * Compute the difference in process stats.
781 pr_stat_sub(p2, p1, pr)
782 struct process_stats *p2, *p1, *pr;
784 pr->ps_utime.tv_sec = p2->ps_utime.tv_sec - p1->ps_utime.tv_sec;
785 pr->ps_utime.tv_usec = p2->ps_utime.tv_usec - p1->ps_utime.tv_usec;
786 if (pr->ps_utime.tv_usec < 0) {
787 pr->ps_utime.tv_sec -= 1;
788 pr->ps_utime.tv_usec += 1000000;
790 pr->ps_stime.tv_sec = p2->ps_stime.tv_sec - p1->ps_stime.tv_sec;
791 pr->ps_stime.tv_usec = p2->ps_stime.tv_usec - p1->ps_stime.tv_usec;
792 if (pr->ps_stime.tv_usec < 0) {
793 pr->ps_stime.tv_sec -= 1;
794 pr->ps_stime.tv_usec += 1000000;
797 pr->ps_maxrss = p2->ps_maxrss - p1->ps_maxrss;
798 pr->ps_pagein = p2->ps_pagein - p1->ps_pagein;
799 pr->ps_reclaim = p2->ps_reclaim - p1->ps_reclaim;
800 pr->ps_zerofill = p2->ps_zerofill - p1->ps_zerofill;
801 pr->ps_pffincr = p2->ps_pffincr - p1->ps_pffincr;
802 pr->ps_pffdecr = p2->ps_pffdecr - p1->ps_pffdecr;
803 pr->ps_swap = p2->ps_swap - p1->ps_swap;
804 pr->ps_syscall = p2->ps_syscall - p1->ps_syscall;
805 pr->ps_volcsw = p2->ps_volcsw - p1->ps_volcsw;
806 pr->ps_involcsw = p2->ps_involcsw - p1->ps_involcsw;
807 pr->ps_signal = p2->ps_signal - p1->ps_signal;
808 pr->ps_lread = p2->ps_lread - p1->ps_lread;
809 pr->ps_lwrite = p2->ps_lwrite - p1->ps_lwrite;
810 pr->ps_bread = p2->ps_bread - p1->ps_bread;
811 pr->ps_bwrite = p2->ps_bwrite - p1->ps_bwrite;
812 pr->ps_phread = p2->ps_phread - p1->ps_phread;
813 pr->ps_phwrite = p2->ps_phwrite - p1->ps_phwrite;
816 #endif /* _SEQUENT_ */
820 /* This is a replacement for a missing memset function */
821 ptr_t xmemset(loc, value, len)
826 char *ptr = (char *) loc;
832 #endif /* NEEDmemset */
837 * This is the ANSI form of bcopy() with the arguments backwards...
838 * Unlike memcpy(), it handles overlaps between source and
842 xmemmove(vdst, vsrc, len)
847 const char *src = (const char *) vsrc;
848 char *dst = (char *) vdst;
865 #endif /* NEEDmemmove */
876 /* ioctl will handle setting errno correctly. */
877 if (ioctl(fd, TIOCGPGRP, (ioctl_t) & pgrp) < 0)
883 * XXX: tcsetpgrp is not a macro any more cause on some systems,
884 * pid_t is a short, but the ioctl() takes a pointer to int (pyr)
885 * Thanks to Simon Day (simon@pharaoh.cyborg.bt.co.uk) for pointing
892 return ioctl(fd, TIOCSPGRP, (ioctl_t) &pgrp);
895 #endif /* tcgetpgrp */
896 #endif /* WINNT_NATIVE */
905 extern int yp_get_default_domain __P((char **));
907 * PWP: The previous version assumed that yp domain was the same as the
908 * internet name domain. This isn't allways true. (Thanks to Mat Landau
909 * <mlandau@bbn.com> for the original version of this.)
911 if (yp_get_default_domain(&mydomain) == 0) { /* if we got a name */
912 extern void yp_unbind __P((const char *));
924 #if defined(NLS) && !defined(NOSTRCOLL)
926 * SunOS4 checks the file descriptor from openlocale() for <= 0
927 * instead of == -1. Someone should tell sun that file descriptor 0
928 * is valid! Our portable hack: open one so we call it with 0 used...
929 * We have to call this routine every time the locale changes...
931 * Of course it also tries to free the constant locale "C" it initially
932 * had allocated, with the sequence
936 * But we are smarter than that and just print a warning message.
939 static char *root = "/";
942 fd = open(root, O_RDONLY);
944 (void) strcoll(root, root);
950 #endif /* STRCOLLBUG */
962 setcompat(getcompat() & ~COMPAT_EXEC);
963 sigignore(SIGIO); /* ignore SIGIO */
968 struct sigstack inst;
969 inst.ss_sp = (char *) xmalloc((size_t) 4192) + 4192;
971 sigstack(&inst, NULL);
981 * kill(SIGCONT) problems, don't know what this syscall does
982 * [schott@rzg.mpg.de]
984 syscall(151, getpid(), getpid());
993 static char errbuf[128];
995 if (i >= 0 && i < sys_nerr) {
996 return sys_errlist[i];
998 (void) xsnprintf(errbuf, sizeof(errbuf),
999 CGETS(23, 13, "Unknown Error: %d"), i);
1003 #endif /* strerror */
1006 # if !defined(_MINIX) && !defined(__EMX__) && !defined(WINNT_NATIVE)
1007 # include <sys/utsname.h>
1008 # endif /* !_MINIX && !__EMX__ && !WINNT_NATIVE */
1011 xgethostname(name, namlen)
1015 # if !defined(_MINIX) && !defined(__EMX__) && !defined(WINNT_NATIVE)
1019 retval = uname(&uts);
1022 xprintf(CGETS(23, 14, "sysname: %s\n"), uts.sysname);
1023 xprintf(CGETS(23, 15, "nodename: %s\n"), uts.nodename);
1024 xprintf(CGETS(23, 16, "release: %s\n"), uts.release);
1025 xprintf(CGETS(23, 17, "version: %s\n"), uts.version);
1026 xprintf(CGETS(23, 18, "machine: %s\n"), uts.machine);
1028 i = strlen(uts.nodename) + 1;
1029 (void) strncpy(name, uts.nodename, i < namlen ? i : namlen);
1032 # else /* !_MINIX && !__EMX__ */
1035 (void) strncpy(name, "OS/2", namlen);
1037 (void) strncpy(name, "minix", namlen);
1038 # endif /* __EMX__ */
1039 name[namlen-1] = '\0';
1042 #endif /* _MINIX && !__EMX__ */
1043 } /* end xgethostname */
1044 #endif /* gethostname */
1047 # if defined(_MINIX) && defined(NICE)
1048 # undef _POSIX_SOURCE /* redefined in <lib.h> */
1049 # undef _MINIX /* redefined in <lib.h> */
1050 # undef HZ /* redefined in <minix/const.h> */
1052 # endif /* _MINIX && NICE */
1057 #if defined(_MINIX) && defined(NICE)
1058 return callm1(MM, NICE, incr, 0, 0, NIL_PTR, NIL_PTR, NIL_PTR);
1060 return /* incr ? 0 : */ 0;
1061 #endif /* _MINIX && NICE */
1066 static char *strnrcpy __P((char *, char *, size_t));
1069 * Return the pathname of the current directory, or return
1070 * an error message in pathname.
1075 * From: Bernd Mohr <mohr@faui77.informatik.uni-erlangen.de>
1076 * I also ported the tcsh to the HP9000 Series 500. This computer
1077 * is a little bit different than the other HP 9000 computer. It has
1078 * a HP Chip instead of a Motorola CPU and it is no "real" UNIX. It runs
1079 * HP-UX which is emulated in top of a HP operating system. So, the last
1080 * supported version of HP-UX is 5.2 on the HP9000s500. This has two
1081 * consequences: it supports no job control and it has a filesystem
1082 * without "." and ".." !!!
1085 xgetcwd(pathname, pathlen)
1089 char pathbuf[MAXNAMLEN]; /* temporary pathname buffer */
1090 char *pnptr = &pathbuf[(sizeof pathbuf)-1]; /* pathname pointer */
1091 dev_t rdev; /* root device number */
1092 DIR *dirp = NULL; /* directory stream */
1093 ino_t rino; /* root inode number */
1094 off_t rsize; /* root size */
1095 struct direct *dir; /* directory entry struct */
1096 struct stat d, dd; /* file status struct */
1100 (void) stat("/.", &d);
1105 if (stat(".", &d) == -1) {
1106 (void) xsnprintf(pathname, pathlen, CGETS(23, 24,
1107 "getcwd: Cannot stat \".\" (%s)"), strerror(errno));
1110 if (d.st_ino == rino && d.st_dev == rdev && d.st_size == rsize)
1111 break; /* reached root directory */
1112 if ((dirp = opendir("..")) == NULL) {
1113 (void) xsnprintf(pathname, pathlen, CGETS(23, 19,
1114 "getcwd: Cannot open \"..\" (%s)"), strerror(errno));
1117 if (chdir("..") == -1) {
1118 (void) xsnprintf(pathname, pathlen, CGETS(23, 20,
1119 "getcwd: Cannot chdir to \"..\" (%s)"), strerror(errno));
1123 if ((dir = readdir(dirp)) == NULL) {
1124 (void) xsnprintf(pathname, pathlen,
1125 CGETS(23, 21, "getcwd: Read error in \"..\" (%s)"),
1129 if (stat(dir->d_name, &dd) == -1) {
1130 (void) xsnprintf(pathname, pathlen,
1131 CGETS(23, 25, "getcwd: Cannot stat directory \"%s\" (%s)"),
1132 dir->d_name, strerror(errno));
1135 } while (dd.st_ino != d.st_ino ||
1136 dd.st_dev != d.st_dev ||
1137 dd.st_size != d.st_size);
1138 (void) closedir(dirp);
1140 pnptr = strnrcpy(dirp->d_name, pnptr, pnptr - pathbuf);
1141 pnptr = strnrcpy("/", pnptr, pnptr - pathbuf);
1144 if (*pnptr == '\0') /* current dir == root dir */
1145 (void) strncpy(pathname, "/", pathlen);
1147 (void) strncpy(pathname, pnptr, pathlen);
1148 pathname[pathlen - 1] = '\0';
1149 if (chdir(pnptr) == -1) {
1150 (void) xsnprintf(pathname, MAXPATHLEN, CGETS(23, 22,
1151 "getcwd: Cannot change back to \".\" (%s)"),
1160 (void) chdir(strnrcpy(".", pnptr, pnptr - pathbuf));
1165 # else /* ! hp9000s500 */
1167 # if (SYSVREL != 0 && !defined(d_fileno)) || defined(_VMS_POSIX) || defined(WINNT) || defined(_MINIX_VMD)
1168 # define d_fileno d_ino
1172 xgetcwd(pathname, pathlen)
1179 struct stat st_root, st_cur, st_next, st_dotdot;
1180 char pathbuf[MAXPATHLEN], nextpathbuf[MAXPATHLEN * 2];
1181 char *pathptr, *nextpathptr, *cur_name_add;
1184 /* find the inode of root */
1185 if (stat("/", &st_root) == -1) {
1186 (void) xsnprintf(pathname, pathlen, CGETS(23, 23,
1187 "getcwd: Cannot stat \"/\" (%s)"),
1191 pathbuf[MAXPATHLEN - 1] = '\0';
1192 pathptr = &pathbuf[MAXPATHLEN - 1];
1193 nextpathbuf[MAXPATHLEN - 1] = '\0';
1194 cur_name_add = nextpathptr = &nextpathbuf[MAXPATHLEN - 1];
1196 /* find the inode of the current directory */
1197 if (lstat(".", &st_cur) == -1) {
1198 (void) xsnprintf(pathname, pathlen, CGETS(23, 24,
1199 "getcwd: Cannot stat \".\" (%s)"),
1203 nextpathptr = strnrcpy(nextpathptr, "../", nextpathptr - nextpathbuf);
1205 /* Descend to root */
1208 /* look if we found root yet */
1209 if (st_cur.st_ino == st_root.st_ino &&
1210 DEV_DEV_COMPARE(st_cur.st_dev, st_root.st_dev)) {
1211 (void) strncpy(pathname, *pathptr != '/' ? "/" : pathptr, pathlen);
1212 pathname[pathlen - 1] = '\0';
1216 /* open the parent directory */
1217 if (stat(nextpathptr, &st_dotdot) == -1) {
1218 (void) xsnprintf(pathname, pathlen, CGETS(23, 25,
1219 "getcwd: Cannot stat directory \"%s\" (%s)"),
1220 nextpathptr, strerror(errno));
1223 if ((dp = opendir(nextpathptr)) == NULL) {
1224 (void) xsnprintf(pathname, pathlen, CGETS(23, 26,
1225 "getcwd: Cannot open directory \"%s\" (%s)"),
1226 nextpathptr, strerror(errno));
1230 /* look in the parent for the entry with the same inode */
1231 if (DEV_DEV_COMPARE(st_dotdot.st_dev, st_cur.st_dev)) {
1232 /* Parent has same device. No need to stat every member */
1233 for (d = readdir(dp); d != NULL; d = readdir(dp)) {
1235 if (((unsigned long)d->d_fileno & 0xffff) == st_cur.st_ino)
1238 if (d->d_fileno == st_cur.st_ino)
1245 * Parent has a different device. This is a mount point so we
1246 * need to stat every member
1248 for (d = readdir(dp); d != NULL; d = readdir(dp)) {
1249 if (ISDOT(d->d_name) || ISDOTDOT(d->d_name))
1251 (void)strncpy(cur_name_add, d->d_name,
1252 (size_t) (&nextpathbuf[sizeof(nextpathbuf) - 1] - cur_name_add));
1253 if (lstat(nextpathptr, &st_next) == -1) {
1255 * We might not be able to stat() some path components
1256 * if we are using afs, but this is not an error as
1257 * long as we find the one we need; we also save the
1258 * first error to report it if we don't finally succeed.
1260 if (save_errno == 0)
1264 /* check if we found it yet */
1265 if (st_next.st_ino == st_cur.st_ino &&
1266 DEV_DEV_COMPARE(st_next.st_dev, st_cur.st_dev))
1271 (void) xsnprintf(pathname, pathlen, CGETS(23, 27,
1272 "getcwd: Cannot find \".\" in \"..\" (%s)"),
1273 strerror(save_errno ? save_errno : ENOENT));
1274 (void) closedir(dp);
1280 pathptr = strnrcpy(pathptr, d->d_name, pathptr - pathbuf);
1281 pathptr = strnrcpy(pathptr, "/", pathptr - pathbuf);
1282 nextpathptr = strnrcpy(nextpathptr, "../", nextpathptr - nextpathbuf);
1283 *cur_name_add = '\0';
1284 (void) closedir(dp);
1287 # endif /* hp9000s500 */
1290 * Like strncpy, going backwards and returning the new pointer
1293 strnrcpy(ptr, str, siz)
1294 register char *ptr, *str;
1297 register int len = strlen(str);
1301 while (len && siz--)
1302 *--ptr = str[--len];
1305 } /* end strnrcpy */
1312 #include <apollo/base.h>
1313 #include <apollo/loader.h>
1314 #include <apollo/error.h>
1321 static char buf[BUFSIZE];
1322 short e_subl, e_modl, e_codel;
1323 error_$string_t e_sub, e_mod, e_code;
1325 error_$get_text(*st, e_sub, &e_subl, e_mod, &e_modl, e_code, &e_codel);
1326 e_sub[e_subl] = '\0';
1327 e_code[e_codel] = '\0';
1328 e_mod[e_modl] = '\0';
1329 (void) xsnprintf(buf, sizeof(buf), "%s (%s/%s)", e_code, e_sub, e_mod);
1338 short len = Strlen(s);
1342 loader_$inlib(t = short2str(s), len, &st);
1343 if (st.all != status_$ok)
1344 stderror(ERR_SYSTEM, t, apperr(&st));
1353 setname(short2str(*v++));
1354 gflag = 0, tglob(v);
1358 stderror(ERR_NAME | ERR_NOMATCH);
1361 v = gargv = saveblk(v);
1368 blkfree(gargv), gargv = 0;
1375 if (eq(v, STRbsd43))
1377 else if (eq(v, STRsys53))
1380 stderror(ERR_NAME | ERR_SYSTEM, short2str(v),
1381 CGETS(23, 28, "Invalid system type"));
1394 setname(short2str(*v++));
1396 if (!(p = tgetenv(STRSYSTYPE)))
1397 stderror(ERR_NAME | ERR_STRING,
1398 CGETS(23, 29, "System type is not set"));
1402 tsetenv(STRSYSTYPE, getv(*v) ? STRbsd43 : STRsys53);
1408 * Many thanks to rees@citi.umich.edu (Jim Rees) and
1409 * mathys@ssdt-tempe.sps.mot.com (Yves Mathys)
1410 * For figuring out how to do this... I could have never done
1411 * it without their help.
1413 typedef short enum {
1416 name_$node_dir_type,
1425 name_$dir_type_t dirtype = name_$node_dir_type;
1431 setname(short2str(*v++));
1433 name = short2str(*v);
1434 namelen = strlen(name);
1436 name_$resolve(name, &namelen, &uid, &st);
1437 if (st.all != status_$ok)
1438 stderror(ERR_SYSTEM, name, apperr(&st));
1440 name_$set_diru(&uid, "", &namelen, &dirtype, &st);
1441 if (st.all != status_$ok)
1442 stderror(ERR_SYSTEM, name, apperr(&st));
1449 static int res = -1;
1450 static status_$t st;
1462 st.all = status_$ok;
1465 res = stream_$isavt(&strm, &st);
1469 if (st.all != status_$ok)
1470 stderror(ERR_SYSTEM, "stream_$isavt", apperr(&st));