1 | /* $Header: /afs/dev.mit.edu/source/repository/third/tcsh/tc.os.c,v 1.1.1.2 1998-10-03 21:10:13 danw Exp $ */ |
---|
2 | /* |
---|
3 | * tc.os.c: OS Dependent builtin functions |
---|
4 | */ |
---|
5 | /*- |
---|
6 | * Copyright (c) 1980, 1991 The Regents of the University of California. |
---|
7 | * All rights reserved. |
---|
8 | * |
---|
9 | * Redistribution and use in source and binary forms, with or without |
---|
10 | * modification, are permitted provided that the following conditions |
---|
11 | * are met: |
---|
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. |
---|
24 | * |
---|
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 |
---|
35 | * SUCH DAMAGE. |
---|
36 | */ |
---|
37 | #include "sh.h" |
---|
38 | |
---|
39 | RCSID("$Id: tc.os.c,v 1.1.1.2 1998-10-03 21:10:13 danw Exp $") |
---|
40 | |
---|
41 | #include "tw.h" |
---|
42 | #include "ed.h" |
---|
43 | #include "ed.defns.h" /* for the function names */ |
---|
44 | #include "sh.decls.h" |
---|
45 | |
---|
46 | /*** |
---|
47 | *** MACH |
---|
48 | ***/ |
---|
49 | |
---|
50 | #ifdef MACH |
---|
51 | /* dosetpath -- setpath built-in command |
---|
52 | * |
---|
53 | ********************************************************************** |
---|
54 | * HISTORY |
---|
55 | * 08-May-88 Richard Draves (rpd) at Carnegie-Mellon University |
---|
56 | * Major changes to remove artificial limits on sizes and numbers |
---|
57 | * of paths. |
---|
58 | * |
---|
59 | ********************************************************************** |
---|
60 | */ |
---|
61 | |
---|
62 | #ifdef MACH |
---|
63 | static Char STRCPATH[] = {'C', 'P', 'A', 'T', 'H', '\0'}; |
---|
64 | static Char STRLPATH[] = {'L', 'P', 'A', 'T', 'H', '\0'}; |
---|
65 | static Char STRMPATH[] = {'M', 'P', 'A', 'T', 'H', '\0'}; |
---|
66 | # if EPATH |
---|
67 | static Char STREPATH[] = {'E', 'P', 'A', 'T', 'H', '\0'}; |
---|
68 | # endif |
---|
69 | #endif /* MACH */ |
---|
70 | static Char *syspaths[] = {STRKPATH, STRCPATH, STRLPATH, STRMPATH, |
---|
71 | |
---|
72 | #if EPATH |
---|
73 | STREPATH, |
---|
74 | #endif |
---|
75 | 0}; |
---|
76 | #define LOCALSYSPATH "/usr/local" |
---|
77 | |
---|
78 | /*ARGSUSED*/ |
---|
79 | void |
---|
80 | dosetpath(arglist, c) |
---|
81 | Char **arglist; |
---|
82 | struct command *c; |
---|
83 | { |
---|
84 | extern char *getenv(); |
---|
85 | sigmask_t omask; |
---|
86 | Char **pathvars, **cmdargs; |
---|
87 | char **spaths, **cpaths, **cmds; |
---|
88 | char *tcp; |
---|
89 | unsigned int npaths, ncmds; |
---|
90 | int i, sysflag; |
---|
91 | |
---|
92 | omask = sigsetmask(sigmask(SIGINT)); |
---|
93 | |
---|
94 | /* |
---|
95 | * setpath(3) uses stdio and we want 0, 1, 2 to work... |
---|
96 | */ |
---|
97 | if (!didfds) { |
---|
98 | (void) dcopy(SHIN, 0); |
---|
99 | (void) dcopy(SHOUT, 1); |
---|
100 | (void) dcopy(SHDIAG, 2); |
---|
101 | didfds = 1; |
---|
102 | } |
---|
103 | |
---|
104 | for (i = 1; arglist[i] && (arglist[i][0] != '-'); i++); |
---|
105 | npaths = i - 1; |
---|
106 | |
---|
107 | cmdargs = &arglist[i]; |
---|
108 | for (; arglist[i]; i++); |
---|
109 | ncmds = i - npaths - 1; |
---|
110 | |
---|
111 | if (npaths) { |
---|
112 | sysflag = 0; |
---|
113 | pathvars = &arglist[1]; |
---|
114 | } |
---|
115 | else { |
---|
116 | sysflag = 1; |
---|
117 | npaths = (sizeof syspaths / sizeof *syspaths) - 1; |
---|
118 | pathvars = syspaths; |
---|
119 | } |
---|
120 | |
---|
121 | /* note that npaths != 0 */ |
---|
122 | |
---|
123 | spaths = (char **) xmalloc((size_t) npaths * sizeof *spaths); |
---|
124 | setzero((char *) spaths, npaths * sizeof *spaths); |
---|
125 | cpaths = (char **) xmalloc((size_t) (npaths + 1) * sizeof *cpaths); |
---|
126 | setzero((char *) cpaths, (npaths + 1) * sizeof *cpaths); |
---|
127 | cmds = (char **) xmalloc((size_t) (ncmds + 1) * sizeof *cmds); |
---|
128 | setzero((char *) cmds, (ncmds + 1) * sizeof *cmds); |
---|
129 | for (i = 0; i < npaths; i++) { |
---|
130 | char *val = getenv(short2str(pathvars[i])); |
---|
131 | |
---|
132 | if (val == NULL) |
---|
133 | val = ""; |
---|
134 | |
---|
135 | spaths[i] = (char *) xmalloc((size_t) (Strlen(pathvars[i]) + |
---|
136 | strlen(val) + 2) * sizeof **spaths); |
---|
137 | (void) strcpy(spaths[i], short2str(pathvars[i])); |
---|
138 | (void) strcat(spaths[i], "="); |
---|
139 | (void) strcat(spaths[i], val); |
---|
140 | cpaths[i] = spaths[i]; |
---|
141 | } |
---|
142 | |
---|
143 | for (i = 0; i < ncmds; i++) { |
---|
144 | Char *val = globone(cmdargs[i], G_ERROR); |
---|
145 | |
---|
146 | if (val == NULL) |
---|
147 | goto abortpath; |
---|
148 | cmds[i] = (char *) xmalloc((size_t) Strlen(val) + 1); |
---|
149 | (void) strcpy(cmds[i], short2str(val)); |
---|
150 | } |
---|
151 | |
---|
152 | |
---|
153 | if (setpath(cpaths, cmds, LOCALSYSPATH, sysflag, 1) < 0) { |
---|
154 | abortpath: |
---|
155 | if (spaths) { |
---|
156 | for (i = 0; i < npaths; i++) |
---|
157 | if (spaths[i]) |
---|
158 | xfree((ptr_t) spaths[i]); |
---|
159 | xfree((ptr_t) spaths); |
---|
160 | } |
---|
161 | if (cpaths) |
---|
162 | xfree((ptr_t) cpaths); |
---|
163 | if (cmds) { |
---|
164 | for (i = 0; i < ncmds; i++) |
---|
165 | if (cmds[i]) |
---|
166 | xfree((ptr_t) cmds[i]); |
---|
167 | xfree((ptr_t) cmds); |
---|
168 | } |
---|
169 | |
---|
170 | (void) sigsetmask(omask); |
---|
171 | donefds(); |
---|
172 | return; |
---|
173 | } |
---|
174 | |
---|
175 | for (i = 0; i < npaths; i++) { |
---|
176 | Char *val, *name; |
---|
177 | |
---|
178 | name = str2short(cpaths[i]); |
---|
179 | for (val = str2short(cpaths[i]); val && *val && *val != '='; val++); |
---|
180 | if (val && *val == '=') { |
---|
181 | *val++ = '\0'; |
---|
182 | |
---|
183 | tsetenv(name, val); |
---|
184 | if (Strcmp(name, STRKPATH) == 0) { |
---|
185 | importpath(val); |
---|
186 | if (havhash) |
---|
187 | dohash(NULL, NULL); |
---|
188 | } |
---|
189 | *--val = '='; |
---|
190 | } |
---|
191 | } |
---|
192 | (void) sigsetmask(omask); |
---|
193 | donefds(); |
---|
194 | } |
---|
195 | #endif /* MACH */ |
---|
196 | |
---|
197 | /*** |
---|
198 | *** AIX |
---|
199 | ***/ |
---|
200 | #ifdef TCF |
---|
201 | /* ARGSUSED */ |
---|
202 | void |
---|
203 | dogetxvers(v, c) |
---|
204 | Char **v; |
---|
205 | struct command *c; |
---|
206 | { |
---|
207 | char xvers[MAXPATHLEN]; |
---|
208 | |
---|
209 | if (getxvers(xvers, MAXPATHLEN) == -1) |
---|
210 | stderror(ERR_SYSTEM, "getxvers", strerror(errno)); |
---|
211 | xprintf("%s\n", xvers); |
---|
212 | flush(); |
---|
213 | } |
---|
214 | |
---|
215 | /*ARGSUSED*/ |
---|
216 | void |
---|
217 | dosetxvers(v, c) |
---|
218 | Char **v; |
---|
219 | struct command *c; |
---|
220 | { |
---|
221 | char *xvers; |
---|
222 | |
---|
223 | ++v; |
---|
224 | if (!*v || *v[0] == '\0') |
---|
225 | xvers = ""; |
---|
226 | else |
---|
227 | xvers = short2str(*v); |
---|
228 | if (setxvers(xvers) == -1) |
---|
229 | stderror(ERR_SYSTEM, "setxvers", strerror(errno)); |
---|
230 | } |
---|
231 | |
---|
232 | #include <sf.h> |
---|
233 | #ifdef _AIXPS2 |
---|
234 | # define XC_PDP11 0x01 |
---|
235 | # define XC_23 0x02 |
---|
236 | # define XC_Z8K 0x03 |
---|
237 | # define XC_8086 0x04 |
---|
238 | # define XC_68K 0x05 |
---|
239 | # define XC_Z80 0x06 |
---|
240 | # define XC_VAX 0x07 |
---|
241 | # define XC_16032 0x08 |
---|
242 | # define XC_286 0x09 |
---|
243 | # define XC_386 0x0a |
---|
244 | # define XC_S370 0x0b |
---|
245 | #else |
---|
246 | # include <sys/x.out.h> |
---|
247 | #endif /* _AIXPS2 */ |
---|
248 | |
---|
249 | static struct xc_cpu_t { |
---|
250 | short xc_id; |
---|
251 | char *xc_name; |
---|
252 | } xcpu[] = |
---|
253 | { |
---|
254 | { XC_PDP11, "pdp11" }, |
---|
255 | { XC_23, "i370" }, |
---|
256 | { XC_Z8K, "z8000" }, |
---|
257 | { XC_8086, "i86" }, |
---|
258 | { XC_68K, "mc68000" }, |
---|
259 | { XC_Z80, "x80" }, |
---|
260 | { XC_VAX, "vax" }, |
---|
261 | { XC_16032, "ns16032" }, |
---|
262 | { XC_286, "i286" }, |
---|
263 | { XC_386, "i386" }, |
---|
264 | { XC_S370, "xa370" }, |
---|
265 | { 0, NULL } |
---|
266 | }; |
---|
267 | |
---|
268 | /* |
---|
269 | * our local hack table, stolen from x.out.h |
---|
270 | */ |
---|
271 | static char * |
---|
272 | getxcode(xcid) |
---|
273 | short xcid; |
---|
274 | { |
---|
275 | int i; |
---|
276 | |
---|
277 | for (i = 0; xcpu[i].xc_name != NULL; i++) |
---|
278 | if (xcpu[i].xc_id == xcid) |
---|
279 | return (xcpu[i].xc_name); |
---|
280 | return (NULL); |
---|
281 | } |
---|
282 | |
---|
283 | static short |
---|
284 | getxid(xcname) |
---|
285 | char *xcname; |
---|
286 | { |
---|
287 | int i; |
---|
288 | |
---|
289 | for (i = 0; xcpu[i].xc_name != NULL; i++) |
---|
290 | if (strcmp(xcpu[i].xc_name, xcname) == 0) |
---|
291 | return (xcpu[i].xc_id); |
---|
292 | return ((short) -1); |
---|
293 | } |
---|
294 | |
---|
295 | |
---|
296 | /*ARGSUSED*/ |
---|
297 | void |
---|
298 | dogetspath(v, c) |
---|
299 | Char **v; |
---|
300 | struct command *c; |
---|
301 | { |
---|
302 | int i, j; |
---|
303 | sitepath_t p[MAXSITE]; |
---|
304 | struct sf *st; |
---|
305 | static char *local = "LOCAL "; |
---|
306 | |
---|
307 | if ((j = getspath(p, MAXSITE)) == -1) |
---|
308 | stderror(ERR_SYSTEM, "getspath", strerror(errno)); |
---|
309 | for (i = 0; i < j && (p[i] & SPATH_CPU) != NOSITE; i++) { |
---|
310 | if (p[i] & SPATH_CPU) { |
---|
311 | if ((p[i] & SPATH_MASK) == NULLSITE) |
---|
312 | xprintf(local); |
---|
313 | else if ((st = sfxcode((short) (p[i] & SPATH_MASK))) != NULL) |
---|
314 | xprintf("%s ", st->sf_ctype); |
---|
315 | else { |
---|
316 | char *xc = getxcode(p[i] & SPATH_MASK); |
---|
317 | |
---|
318 | if (xc != NULL) |
---|
319 | xprintf("%s ", xc); |
---|
320 | else |
---|
321 | xprintf("*cpu %d* ", (int) (p[i] & SPATH_MASK)); |
---|
322 | /* |
---|
323 | * BUG in the aix code... needs that cause if |
---|
324 | * sfxcode fails once it fails for ever |
---|
325 | */ |
---|
326 | endsf(); |
---|
327 | } |
---|
328 | } |
---|
329 | else { |
---|
330 | if (p[i] == NULLSITE) |
---|
331 | xprintf(local); |
---|
332 | else if ((st = sfnum(p[i])) != NULL) |
---|
333 | xprintf("%s ", st->sf_sname); |
---|
334 | else |
---|
335 | xprintf("*site %d* ", (int) (p[i] & SPATH_MASK)); |
---|
336 | } |
---|
337 | } |
---|
338 | xputchar('\n'); |
---|
339 | flush(); |
---|
340 | } |
---|
341 | |
---|
342 | /*ARGSUSED*/ |
---|
343 | void |
---|
344 | dosetspath(v, c) |
---|
345 | Char **v; |
---|
346 | struct command *c; |
---|
347 | { |
---|
348 | int i; |
---|
349 | short j; |
---|
350 | char *s; |
---|
351 | sitepath_t p[MAXSITE]; |
---|
352 | struct sf *st; |
---|
353 | |
---|
354 | /* |
---|
355 | * sfname() on AIX G9.9 at least, mallocs too pointers p, q |
---|
356 | * then does the equivalent of while (*p++ == *q++) continue; |
---|
357 | * and then tries to free(p,q) them! Congrats to the wizard who |
---|
358 | * wrote that one. I bet he tested it really well too. |
---|
359 | * Sooo, we set dont_free :-) |
---|
360 | */ |
---|
361 | dont_free = 1; |
---|
362 | for (i = 0, v++; *v && *v[0] != '\0'; v++, i++) { |
---|
363 | s = short2str(*v); |
---|
364 | if (Isdigit(*s)) |
---|
365 | p[i] = atoi(s); |
---|
366 | else if (strcmp(s, "LOCAL") == 0) |
---|
367 | p[i] = NULLSITE; |
---|
368 | else if ((st = sfctype(s)) != NULL) |
---|
369 | p[i] = SPATH_CPU | st->sf_ccode; |
---|
370 | else if ((j = getxid(s)) != -1) |
---|
371 | p[i] = SPATH_CPU | j; |
---|
372 | else if ((st = sfname(s)) != NULL) |
---|
373 | p[i] = st->sf_id; |
---|
374 | else { |
---|
375 | setname(s); |
---|
376 | stderror(ERR_NAME | ERR_STRING, CGETS(23, 1, "Bad cpu/site name")); |
---|
377 | } |
---|
378 | if (i == MAXSITE - 1) |
---|
379 | stderror(ERR_NAME | ERR_STRING, CGETS(23, 2, "Site path too long")); |
---|
380 | } |
---|
381 | if (setspath(p, i) == -1) |
---|
382 | stderror(ERR_SYSTEM, "setspath", strerror(errno)); |
---|
383 | dont_free = 0; |
---|
384 | } |
---|
385 | |
---|
386 | /* sitename(): |
---|
387 | * Return the site name where the process is running |
---|
388 | */ |
---|
389 | char * |
---|
390 | sitename(pid) |
---|
391 | pid_t pid; |
---|
392 | { |
---|
393 | siteno_t ss; |
---|
394 | struct sf *st; |
---|
395 | |
---|
396 | if ((ss = site(pid)) == -1 || (st = sfnum(ss)) == NULL) |
---|
397 | return CGETS(23, 3, "unknown"); |
---|
398 | else |
---|
399 | return st->sf_sname; |
---|
400 | } |
---|
401 | |
---|
402 | static int |
---|
403 | migratepid(pid, new_site) |
---|
404 | pid_t pid; |
---|
405 | siteno_t new_site; |
---|
406 | { |
---|
407 | struct sf *st; |
---|
408 | int need_local; |
---|
409 | |
---|
410 | need_local = (pid == 0) || (pid == getpid()); |
---|
411 | |
---|
412 | if (kill3((pid_t) pid, SIGMIGRATE, new_site) < 0) { |
---|
413 | xprintf("%d: %s\n", pid, strerror(errno)); |
---|
414 | return (-1); |
---|
415 | } |
---|
416 | |
---|
417 | if (need_local) { |
---|
418 | if ((new_site = site(0)) == -1) { |
---|
419 | xprintf(CGETS(23, 4, "site: %s\n"), strerror(errno)); |
---|
420 | return (-1); |
---|
421 | } |
---|
422 | if ((st = sfnum(new_site)) == NULL) { |
---|
423 | xprintf(CGETS(23, 5, "%d: Site not found\n"), new_site); |
---|
424 | return (-1); |
---|
425 | } |
---|
426 | if (setlocal(st->sf_local, strlen(st->sf_local)) == -1) { |
---|
427 | xprintf(CGETS(23, 6, "setlocal: %s: %s\n"), |
---|
428 | st->sf_local, strerror(errno)); |
---|
429 | return (-1); |
---|
430 | } |
---|
431 | } |
---|
432 | return (0); |
---|
433 | } |
---|
434 | |
---|
435 | /*ARGSUSED*/ |
---|
436 | void |
---|
437 | domigrate(v, c) |
---|
438 | Char **v; |
---|
439 | struct command *c; |
---|
440 | { |
---|
441 | struct sf *st; |
---|
442 | char *s; |
---|
443 | Char *cp; |
---|
444 | struct process *pp; |
---|
445 | int err1 = 0; |
---|
446 | int pid = 0; |
---|
447 | siteno_t new_site = 0; |
---|
448 | sigmask_t omask; |
---|
449 | |
---|
450 | #ifdef BSDSIGS |
---|
451 | omask = sigmask(SIGCHLD); |
---|
452 | if (setintr) |
---|
453 | omask |= sigmask(SIGINT); |
---|
454 | omask = sigblock(omask) & ~omask; |
---|
455 | #else |
---|
456 | if (setintr) |
---|
457 | (void) sighold(SIGINT); |
---|
458 | (void) sighold(SIGCHLD); |
---|
459 | #endif /* BSDSIGS */ |
---|
460 | |
---|
461 | ++v; |
---|
462 | if (*v[0] == '-') { |
---|
463 | /* |
---|
464 | * Do the -site. |
---|
465 | */ |
---|
466 | s = short2str(&v[0][1]); |
---|
467 | /* |
---|
468 | * see comment in setspath() |
---|
469 | */ |
---|
470 | dont_free = 1; |
---|
471 | if ((st = sfname(s)) == NULL) { |
---|
472 | setname(s); |
---|
473 | stderror(ERR_NAME | ERR_STRING, CGETS(23, 7, "Site not found")); |
---|
474 | } |
---|
475 | dont_free = 0; |
---|
476 | new_site = st->sf_id; |
---|
477 | ++v; |
---|
478 | } |
---|
479 | |
---|
480 | if (!*v || *v[0] == '\0') { |
---|
481 | if (migratepid(0, new_site) == -1) |
---|
482 | err1++; |
---|
483 | } |
---|
484 | else { |
---|
485 | gflag = 0, tglob(v); |
---|
486 | if (gflag) { |
---|
487 | v = globall(v); |
---|
488 | if (v == 0) |
---|
489 | stderror(ERR_NAME | ERR_NOMATCH); |
---|
490 | } |
---|
491 | else { |
---|
492 | v = gargv = saveblk(v); |
---|
493 | trim(v); |
---|
494 | } |
---|
495 | |
---|
496 | while (v && (cp = *v)) { |
---|
497 | if (*cp == '%') { |
---|
498 | pp = pfind(cp); |
---|
499 | if (kill3((pid_t) - pp->p_jobid, SIGMIGRATE, new_site) < 0) { |
---|
500 | xprintf("%S: %s\n", cp, strerror(errno)); |
---|
501 | err1++; |
---|
502 | } |
---|
503 | } |
---|
504 | else if (!(Isdigit(*cp) || *cp == '-')) |
---|
505 | stderror(ERR_NAME | ERR_JOBARGS); |
---|
506 | else { |
---|
507 | pid = atoi(short2str(cp)); |
---|
508 | if (migratepid(pid, new_site) == -1) |
---|
509 | err1++; |
---|
510 | } |
---|
511 | v++; |
---|
512 | } |
---|
513 | if (gargv) |
---|
514 | blkfree(gargv), gargv = 0; |
---|
515 | } |
---|
516 | |
---|
517 | done: |
---|
518 | #ifdef BSDSIGS |
---|
519 | (void) sigsetmask(omask); |
---|
520 | #else |
---|
521 | (void) sigrelse(SIGCHLD); |
---|
522 | if (setintr) |
---|
523 | (void) sigrelse(SIGINT); |
---|
524 | #endif /* BSDSIGS */ |
---|
525 | if (err1) |
---|
526 | stderror(ERR_SILENT); |
---|
527 | } |
---|
528 | |
---|
529 | #endif /* TCF */ |
---|
530 | |
---|
531 | /*** |
---|
532 | *** CRAY ddmode <velo@sesun3.epfl.ch> (Martin Ouwehand EPFL-SIC/SE) |
---|
533 | ***/ |
---|
534 | #if defined(_CRAY) && !defined(_CRAYMPP) |
---|
535 | void |
---|
536 | dodmmode(v, c) |
---|
537 | Char **v; |
---|
538 | struct command *c; |
---|
539 | { |
---|
540 | Char *cp = v[1]; |
---|
541 | |
---|
542 | USE(c); |
---|
543 | |
---|
544 | if ( !cp ) { |
---|
545 | int mode; |
---|
546 | |
---|
547 | mode = dmmode(0); |
---|
548 | dmmode(mode); |
---|
549 | xprintf("%d\n",mode); |
---|
550 | } |
---|
551 | else { |
---|
552 | if (cp[1] != '\0') |
---|
553 | stderror(ERR_NAME | ERR_STRING, |
---|
554 | CGETS(23, 30, "Too many arguments")); |
---|
555 | else |
---|
556 | switch(*cp) { |
---|
557 | case '0': |
---|
558 | dmmode(0); |
---|
559 | break; |
---|
560 | case '1': |
---|
561 | dmmode(1); |
---|
562 | break; |
---|
563 | default: |
---|
564 | stderror(ERR_NAME | ERR_STRING, |
---|
565 | CGETS(23, 31, "Invalid argument")); |
---|
566 | } |
---|
567 | } |
---|
568 | } |
---|
569 | #endif /* _CRAY && !_CRAYMPP */ |
---|
570 | |
---|
571 | |
---|
572 | /*** |
---|
573 | *** CONVEX Warps. |
---|
574 | ***/ |
---|
575 | |
---|
576 | #ifdef WARP |
---|
577 | /* |
---|
578 | * handle the funky warping of symlinks |
---|
579 | */ |
---|
580 | #include <warpdb.h> |
---|
581 | #include <sys/warp.h> |
---|
582 | |
---|
583 | static jmp_buf sigsys_buf; |
---|
584 | |
---|
585 | static sigret_t |
---|
586 | catch_sigsys() |
---|
587 | { |
---|
588 | longjmp(sigsys_buf, 1); |
---|
589 | } |
---|
590 | |
---|
591 | |
---|
592 | /*ARGSUSED*/ |
---|
593 | void |
---|
594 | dowarp(v, c) |
---|
595 | Char **v; |
---|
596 | struct command *c; |
---|
597 | { |
---|
598 | int warp, oldwarp; |
---|
599 | struct warpent *we; |
---|
600 | void (*old_sigsys_handler) () = 0; |
---|
601 | char *newwarp; |
---|
602 | |
---|
603 | if (setjmp(sigsys_buf)) { |
---|
604 | signal(SIGSYS, old_sigsys_handler); |
---|
605 | stderror(ERR_NAME | ERR_STRING, |
---|
606 | CGETS(23, 8, "You're trapped in a universe you never made")); |
---|
607 | return; |
---|
608 | } |
---|
609 | old_sigsys_handler = signal(SIGSYS, catch_sigsys); |
---|
610 | |
---|
611 | warp = getwarp(); |
---|
612 | |
---|
613 | v++; |
---|
614 | if (*v == 0) { /* display warp value */ |
---|
615 | if (warp < 0) |
---|
616 | stderror(ERR_NAME | ERR_STRING, CGETS(23, 9, "Getwarp failed")); |
---|
617 | we = getwarpbyvalue(warp); |
---|
618 | if (we) |
---|
619 | printf("%s\n", we->w_name); |
---|
620 | else |
---|
621 | printf("%d\n", warp); |
---|
622 | } |
---|
623 | else { /* set warp value */ |
---|
624 | oldwarp = warp; |
---|
625 | newwarp = short2str(*v); |
---|
626 | if (Isdigit(*v[0])) |
---|
627 | warp = atoi(newwarp); |
---|
628 | else { |
---|
629 | we = getwarpbyname(newwarp); |
---|
630 | if (we) |
---|
631 | warp = we->w_value; |
---|
632 | else |
---|
633 | warp = -1; |
---|
634 | } |
---|
635 | if ((warp < 0) || (warp >= WARP_MAXLINK)) |
---|
636 | stderror(ERR_NAME | ERR_STRING, CGETS(23, 10, "Invalid warp")); |
---|
637 | if ((setwarp(warp) < 0) || (getwarp() != warp)) { |
---|
638 | (void) setwarp(oldwarp); |
---|
639 | stderror(ERR_NAME | ERR_STRING, CGETS(23, 11, "Setwarp failed")); |
---|
640 | } |
---|
641 | } |
---|
642 | signal(SIGSYS, old_sigsys_handler); |
---|
643 | return; |
---|
644 | } |
---|
645 | #endif /* WARP */ |
---|
646 | |
---|
647 | /*** |
---|
648 | *** Masscomp or HCX |
---|
649 | ***/ |
---|
650 | /* Added, DAS DEC-90. */ |
---|
651 | #if defined(masscomp) || defined(_CX_UX) |
---|
652 | /*ARGSUSED*/ |
---|
653 | void |
---|
654 | douniverse(v, c) |
---|
655 | register Char **v; |
---|
656 | struct command *c; |
---|
657 | { |
---|
658 | register Char *cp = v[1]; |
---|
659 | register Char *cp2; /* dunno how many elements v comes in with */ |
---|
660 | char ubuf[100]; |
---|
661 | #ifdef BSDSIGS |
---|
662 | register sigmask_t omask = 0; |
---|
663 | #endif /* BSDSIGS */ |
---|
664 | |
---|
665 | if (cp == 0) { |
---|
666 | (void) getuniverse(ubuf); |
---|
667 | xprintf("%s\n", ubuf); |
---|
668 | } |
---|
669 | else { |
---|
670 | cp2 = v[2]; |
---|
671 | if (cp2 == 0) { |
---|
672 | if (*cp == '\0' || setuniverse(short2str(cp)) != 0) |
---|
673 | stderror(ERR_NAME | ERR_STRING, CGETS(23, 12, "Illegal universe")); |
---|
674 | } |
---|
675 | else { |
---|
676 | (void) getuniverse(ubuf); |
---|
677 | if (*cp == '\0' || setuniverse(short2str(cp)) != 0) |
---|
678 | stderror(ERR_NAME | ERR_STRING, CGETS(23, 12, "Illegal universe")); |
---|
679 | if (setintr) |
---|
680 | #ifdef BSDSIGS |
---|
681 | omask = sigblock(sigmask(SIGINT)) & ~sigmask(SIGINT); |
---|
682 | #else /* !BSDSIGS */ |
---|
683 | (void) sighold(SIGINT); |
---|
684 | #endif /* BSDSIGS */ |
---|
685 | lshift(v, 2); |
---|
686 | if (setintr) |
---|
687 | #ifdef BSDSIGS |
---|
688 | (void) sigsetmask(omask); |
---|
689 | #else /* !BSDSIGS */ |
---|
690 | (void) sigrelse (SIGINT); |
---|
691 | #endif /* BSDSIGS */ |
---|
692 | reexecute(c); |
---|
693 | (void) setuniverse(ubuf); |
---|
694 | } |
---|
695 | } |
---|
696 | } |
---|
697 | #endif /* masscomp || _CX_UX */ |
---|
698 | |
---|
699 | #if defined(_CX_UX) |
---|
700 | /*ARGSUSED*/ |
---|
701 | void |
---|
702 | doatt(v, c) |
---|
703 | register Char **v; |
---|
704 | struct command *c; |
---|
705 | { |
---|
706 | register Char *cp = v[1]; |
---|
707 | char ubuf[100]; |
---|
708 | #ifdef BSDSIGS |
---|
709 | register sigmask_t omask = 0; |
---|
710 | #endif /* BSDSIGS */ |
---|
711 | |
---|
712 | if (cp == 0) |
---|
713 | (void) setuniverse("att"); |
---|
714 | else { |
---|
715 | (void) getuniverse(ubuf); |
---|
716 | (void) setuniverse("att"); |
---|
717 | if (setintr) |
---|
718 | #ifdef BSDSIGS |
---|
719 | omask = sigblock(sigmask(SIGINT)) & ~sigmask(SIGINT); |
---|
720 | #else /* !BSDSIGS */ |
---|
721 | (void) sighold(SIGINT); |
---|
722 | #endif /* BSDSIGS */ |
---|
723 | lshift(v, 1); |
---|
724 | if (setintr) |
---|
725 | #ifdef BSDSIGS |
---|
726 | (void) sigsetmask(omask); |
---|
727 | #else /* !BSDSIGS */ |
---|
728 | (void) sigrelse (SIGINT); |
---|
729 | #endif /* BSDSIGS */ |
---|
730 | reexecute(c); |
---|
731 | (void) setuniverse(ubuf); |
---|
732 | } |
---|
733 | } |
---|
734 | |
---|
735 | /*ARGSUSED*/ |
---|
736 | void |
---|
737 | doucb(v, c) |
---|
738 | register Char **v; |
---|
739 | struct command *c; |
---|
740 | { |
---|
741 | register Char *cp = v[1]; |
---|
742 | char ubuf[100]; |
---|
743 | #ifdef BSDSIGS |
---|
744 | register sigmask_t omask = 0; |
---|
745 | #endif /* BSDSIGS */ |
---|
746 | |
---|
747 | if (cp == 0) |
---|
748 | (void) setuniverse("ucb"); |
---|
749 | else { |
---|
750 | (void) getuniverse(ubuf); |
---|
751 | (void) setuniverse("ucb"); |
---|
752 | if (setintr) |
---|
753 | #ifdef BSDSIGS |
---|
754 | omask = sigblock(sigmask(SIGINT)) & ~sigmask(SIGINT); |
---|
755 | #else /* !BSDSIGS */ |
---|
756 | (void) sighold(SIGINT); |
---|
757 | #endif /* BSDSIGS */ |
---|
758 | lshift(v, 1); |
---|
759 | if (setintr) |
---|
760 | #ifdef BSDSIGS |
---|
761 | (void) sigsetmask(omask); |
---|
762 | #else /* !BSDSIGS */ |
---|
763 | (void) sigrelse (SIGINT); |
---|
764 | #endif /* BSDSIGS */ |
---|
765 | reexecute(c); |
---|
766 | (void) setuniverse(ubuf); |
---|
767 | } |
---|
768 | } |
---|
769 | #endif /* _CX_UX */ |
---|
770 | |
---|
771 | #ifdef _SEQUENT_ |
---|
772 | /* |
---|
773 | * Compute the difference in process stats. |
---|
774 | */ |
---|
775 | void |
---|
776 | pr_stat_sub(p2, p1, pr) |
---|
777 | struct process_stats *p2, *p1, *pr; |
---|
778 | { |
---|
779 | pr->ps_utime.tv_sec = p2->ps_utime.tv_sec - p1->ps_utime.tv_sec; |
---|
780 | pr->ps_utime.tv_usec = p2->ps_utime.tv_usec - p1->ps_utime.tv_usec; |
---|
781 | if (pr->ps_utime.tv_usec < 0) { |
---|
782 | pr->ps_utime.tv_sec -= 1; |
---|
783 | pr->ps_utime.tv_usec += 1000000; |
---|
784 | } |
---|
785 | pr->ps_stime.tv_sec = p2->ps_stime.tv_sec - p1->ps_stime.tv_sec; |
---|
786 | pr->ps_stime.tv_usec = p2->ps_stime.tv_usec - p1->ps_stime.tv_usec; |
---|
787 | if (pr->ps_stime.tv_usec < 0) { |
---|
788 | pr->ps_stime.tv_sec -= 1; |
---|
789 | pr->ps_stime.tv_usec += 1000000; |
---|
790 | } |
---|
791 | |
---|
792 | pr->ps_maxrss = p2->ps_maxrss - p1->ps_maxrss; |
---|
793 | pr->ps_pagein = p2->ps_pagein - p1->ps_pagein; |
---|
794 | pr->ps_reclaim = p2->ps_reclaim - p1->ps_reclaim; |
---|
795 | pr->ps_zerofill = p2->ps_zerofill - p1->ps_zerofill; |
---|
796 | pr->ps_pffincr = p2->ps_pffincr - p1->ps_pffincr; |
---|
797 | pr->ps_pffdecr = p2->ps_pffdecr - p1->ps_pffdecr; |
---|
798 | pr->ps_swap = p2->ps_swap - p1->ps_swap; |
---|
799 | pr->ps_syscall = p2->ps_syscall - p1->ps_syscall; |
---|
800 | pr->ps_volcsw = p2->ps_volcsw - p1->ps_volcsw; |
---|
801 | pr->ps_involcsw = p2->ps_involcsw - p1->ps_involcsw; |
---|
802 | pr->ps_signal = p2->ps_signal - p1->ps_signal; |
---|
803 | pr->ps_lread = p2->ps_lread - p1->ps_lread; |
---|
804 | pr->ps_lwrite = p2->ps_lwrite - p1->ps_lwrite; |
---|
805 | pr->ps_bread = p2->ps_bread - p1->ps_bread; |
---|
806 | pr->ps_bwrite = p2->ps_bwrite - p1->ps_bwrite; |
---|
807 | pr->ps_phread = p2->ps_phread - p1->ps_phread; |
---|
808 | pr->ps_phwrite = p2->ps_phwrite - p1->ps_phwrite; |
---|
809 | } |
---|
810 | |
---|
811 | #endif /* _SEQUENT_ */ |
---|
812 | |
---|
813 | |
---|
814 | #ifdef NEEDmemset |
---|
815 | /* This is a replacement for a missing memset function */ |
---|
816 | ptr_t xmemset(loc, value, len) |
---|
817 | ptr_t loc; |
---|
818 | int len; |
---|
819 | size_t value; |
---|
820 | { |
---|
821 | char *ptr = (char *) loc; |
---|
822 | |
---|
823 | while (len--) |
---|
824 | *ptr++ = value; |
---|
825 | return loc; |
---|
826 | } |
---|
827 | #endif /* NEEDmemset */ |
---|
828 | |
---|
829 | |
---|
830 | #ifdef NEEDmemmove |
---|
831 | /* memmove(): |
---|
832 | * This is the ANSI form of bcopy() with the arguments backwards... |
---|
833 | * Unlike memcpy(), it handles overlaps between source and |
---|
834 | * destination memory |
---|
835 | */ |
---|
836 | ptr_t |
---|
837 | xmemmove(vdst, vsrc, len) |
---|
838 | ptr_t vdst; |
---|
839 | const ptr_t vsrc; |
---|
840 | size_t len; |
---|
841 | { |
---|
842 | const char *src = (const char *) vsrc; |
---|
843 | char *dst = (char *) vdst; |
---|
844 | |
---|
845 | if (src == dst) |
---|
846 | return vdst; |
---|
847 | |
---|
848 | if (src > dst) { |
---|
849 | while (len--) |
---|
850 | *dst++ = *src++; |
---|
851 | } |
---|
852 | else { |
---|
853 | src += len; |
---|
854 | dst += len; |
---|
855 | while (len--) |
---|
856 | *--dst = *--src; |
---|
857 | } |
---|
858 | return vdst; |
---|
859 | } |
---|
860 | #endif /* NEEDmemmove */ |
---|
861 | |
---|
862 | |
---|
863 | #ifndef WINNT |
---|
864 | #ifdef tcgetpgrp |
---|
865 | int |
---|
866 | xtcgetpgrp(fd) |
---|
867 | int fd; |
---|
868 | { |
---|
869 | int pgrp; |
---|
870 | |
---|
871 | /* ioctl will handle setting errno correctly. */ |
---|
872 | if (ioctl(fd, TIOCGPGRP, (ioctl_t) & pgrp) < 0) |
---|
873 | return (-1); |
---|
874 | return (pgrp); |
---|
875 | } |
---|
876 | |
---|
877 | /* |
---|
878 | * XXX: tcsetpgrp is not a macro any more cause on some systems, |
---|
879 | * pid_t is a short, but the ioctl() takes a pointer to int (pyr) |
---|
880 | * Thanks to Simon Day (simon@pharaoh.cyborg.bt.co.uk) for pointing |
---|
881 | * this out. |
---|
882 | */ |
---|
883 | int |
---|
884 | xtcsetpgrp(fd, pgrp) |
---|
885 | int fd, pgrp; |
---|
886 | { |
---|
887 | return ioctl(fd, TIOCSPGRP, (ioctl_t) &pgrp); |
---|
888 | } |
---|
889 | |
---|
890 | #endif /* tcgetpgrp */ |
---|
891 | #endif /* WINNT */ |
---|
892 | |
---|
893 | |
---|
894 | #ifdef YPBUGS |
---|
895 | void |
---|
896 | fix_yp_bugs() |
---|
897 | { |
---|
898 | char *mydomain; |
---|
899 | |
---|
900 | extern int yp_get_default_domain __P((char **)); |
---|
901 | /* |
---|
902 | * PWP: The previous version assumed that yp domain was the same as the |
---|
903 | * internet name domain. This isn't allways true. (Thanks to Mat Landau |
---|
904 | * <mlandau@bbn.com> for the original version of this.) |
---|
905 | */ |
---|
906 | if (yp_get_default_domain(&mydomain) == 0) { /* if we got a name */ |
---|
907 | extern void yp_unbind __P((const char *)); |
---|
908 | |
---|
909 | yp_unbind(mydomain); |
---|
910 | } |
---|
911 | } |
---|
912 | |
---|
913 | #endif /* YPBUGS */ |
---|
914 | |
---|
915 | #ifdef STRCOLLBUG |
---|
916 | void |
---|
917 | fix_strcoll_bug() |
---|
918 | { |
---|
919 | #if defined(NLS) && !defined(NOSTRCOLL) |
---|
920 | /* |
---|
921 | * SunOS4 checks the file descriptor from openlocale() for <= 0 |
---|
922 | * instead of == -1. Someone should tell sun that file descriptor 0 |
---|
923 | * is valid! Our portable hack: open one so we call it with 0 used... |
---|
924 | * We have to call this routine every time the locale changes... |
---|
925 | * |
---|
926 | * Of course it also tries to free the constant locale "C" it initially |
---|
927 | * had allocated, with the sequence |
---|
928 | * > setenv LANG "fr" |
---|
929 | * > ls^D |
---|
930 | * > unsetenv LANG |
---|
931 | * But we are smarter than that and just print a warning message. |
---|
932 | */ |
---|
933 | int fd = -1; |
---|
934 | static char *root = "/"; |
---|
935 | |
---|
936 | if (!didfds) |
---|
937 | fd = open(root, O_RDONLY); |
---|
938 | |
---|
939 | (void) strcoll(root, root); |
---|
940 | |
---|
941 | if (fd != -1) |
---|
942 | (void) close(fd); |
---|
943 | #endif |
---|
944 | } |
---|
945 | #endif /* STRCOLLBUG */ |
---|
946 | |
---|
947 | |
---|
948 | #ifdef OREO |
---|
949 | #include <compat.h> |
---|
950 | #endif /* OREO */ |
---|
951 | |
---|
952 | void |
---|
953 | osinit() |
---|
954 | { |
---|
955 | #ifdef OREO |
---|
956 | set42sig(); |
---|
957 | setcompat(getcompat() & ~COMPAT_EXEC); |
---|
958 | sigignore(SIGIO); /* ignore SIGIO */ |
---|
959 | #endif /* OREO */ |
---|
960 | |
---|
961 | #ifdef aiws |
---|
962 | { |
---|
963 | struct sigstack inst; |
---|
964 | inst.ss_sp = (char *) xmalloc((size_t) 4192) + 4192; |
---|
965 | inst.ss_onstack = 0; |
---|
966 | sigstack(&inst, NULL); |
---|
967 | } |
---|
968 | #endif /* aiws */ |
---|
969 | |
---|
970 | #ifdef apollo |
---|
971 | (void) isapad(); |
---|
972 | #endif |
---|
973 | } |
---|
974 | |
---|
975 | #ifdef strerror |
---|
976 | char * |
---|
977 | xstrerror(i) |
---|
978 | int i; |
---|
979 | { |
---|
980 | static char errbuf[128]; |
---|
981 | |
---|
982 | if (i >= 0 && i < sys_nerr) { |
---|
983 | return sys_errlist[i]; |
---|
984 | } else { |
---|
985 | (void) xsnprintf(errbuf, sizeof(errbuf), |
---|
986 | CGETS(23, 13, "Unknown Error: %d"), i); |
---|
987 | return errbuf; |
---|
988 | } |
---|
989 | } |
---|
990 | #endif /* strerror */ |
---|
991 | |
---|
992 | #ifdef gethostname |
---|
993 | # if !defined(_MINIX) && !defined(__EMX__) && !defined(WINNT) |
---|
994 | # include <sys/utsname.h> |
---|
995 | # endif /* !_MINIX && !__EMX__ && !WINNT */ |
---|
996 | |
---|
997 | int |
---|
998 | xgethostname(name, namlen) |
---|
999 | char *name; |
---|
1000 | int namlen; |
---|
1001 | { |
---|
1002 | # if !defined(_MINIX) && !defined(__EMX__) && !defined(WINNT) |
---|
1003 | int i, retval; |
---|
1004 | struct utsname uts; |
---|
1005 | |
---|
1006 | retval = uname(&uts); |
---|
1007 | |
---|
1008 | # ifdef DEBUG |
---|
1009 | xprintf(CGETS(23, 14, "sysname: %s\n"), uts.sysname); |
---|
1010 | xprintf(CGETS(23, 15, "nodename: %s\n"), uts.nodename); |
---|
1011 | xprintf(CGETS(23, 16, "release: %s\n"), uts.release); |
---|
1012 | xprintf(CGETS(23, 17, "version: %s\n"), uts.version); |
---|
1013 | xprintf(CGETS(23, 18, "machine: %s\n"), uts.machine); |
---|
1014 | # endif /* DEBUG */ |
---|
1015 | i = strlen(uts.nodename) + 1; |
---|
1016 | (void) strncpy(name, uts.nodename, i < namlen ? i : namlen); |
---|
1017 | |
---|
1018 | return retval; |
---|
1019 | # else /* !_MINIX && !__EMX__ */ |
---|
1020 | if (namlen > 0) { |
---|
1021 | # ifdef __EMX__ |
---|
1022 | (void) strncpy(name, "OS/2", namlen); |
---|
1023 | # else /* _MINIX */ |
---|
1024 | (void) strncpy(name, "minix", namlen); |
---|
1025 | # endif /* __EMX__ */ |
---|
1026 | name[namlen-1] = '\0'; |
---|
1027 | } |
---|
1028 | return(0); |
---|
1029 | #endif /* _MINIX && !__EMX__ */ |
---|
1030 | } /* end xgethostname */ |
---|
1031 | #endif /* gethostname */ |
---|
1032 | |
---|
1033 | #ifdef nice |
---|
1034 | # if defined(_MINIX) && defined(NICE) |
---|
1035 | # undef _POSIX_SOURCE /* redefined in <lib.h> */ |
---|
1036 | # undef _MINIX /* redefined in <lib.h> */ |
---|
1037 | # undef HZ /* redefined in <minix/const.h> */ |
---|
1038 | # include <lib.h> |
---|
1039 | # endif /* _MINIX && NICE */ |
---|
1040 | int |
---|
1041 | xnice(incr) |
---|
1042 | int incr; |
---|
1043 | { |
---|
1044 | #if defined(_MINIX) && defined(NICE) |
---|
1045 | return callm1(MM, NICE, incr, 0, 0, NIL_PTR, NIL_PTR, NIL_PTR); |
---|
1046 | #else |
---|
1047 | return /* incr ? 0 : */ 0; |
---|
1048 | #endif /* _MINIX && NICE */ |
---|
1049 | } /* end xnice */ |
---|
1050 | #endif /* nice */ |
---|
1051 | |
---|
1052 | #ifdef NEEDgetcwd |
---|
1053 | static char *strnrcpy __P((char *, char *, size_t)); |
---|
1054 | |
---|
1055 | /* xgetcwd(): |
---|
1056 | * Return the pathname of the current directory, or return |
---|
1057 | * an error message in pathname. |
---|
1058 | */ |
---|
1059 | |
---|
1060 | # ifdef hp9000s500 |
---|
1061 | /* |
---|
1062 | * From: Bernd Mohr <mohr@faui77.informatik.uni-erlangen.de> |
---|
1063 | * I also ported the tcsh to the HP9000 Series 500. This computer |
---|
1064 | * is a little bit different than the other HP 9000 computer. It has |
---|
1065 | * a HP Chip instead of a Motorola CPU and it is no "real" UNIX. It runs |
---|
1066 | * HP-UX which is emulated in top of a HP operating system. So, the last |
---|
1067 | * supported version of HP-UX is 5.2 on the HP9000s500. This has two |
---|
1068 | * consequences: it supports no job control and it has a filesystem |
---|
1069 | * without "." and ".." !!! |
---|
1070 | */ |
---|
1071 | char * |
---|
1072 | xgetcwd(pathname, pathlen) |
---|
1073 | char *pathname; |
---|
1074 | size_t pathlen; |
---|
1075 | { |
---|
1076 | char pathbuf[MAXNAMLEN]; /* temporary pathname buffer */ |
---|
1077 | char *pnptr = &pathbuf[(sizeof pathbuf)-1]; /* pathname pointer */ |
---|
1078 | dev_t rdev; /* root device number */ |
---|
1079 | DIR *dirp = NULL; /* directory stream */ |
---|
1080 | ino_t rino; /* root inode number */ |
---|
1081 | off_t rsize; /* root size */ |
---|
1082 | struct direct *dir; /* directory entry struct */ |
---|
1083 | struct stat d, dd; /* file status struct */ |
---|
1084 | int serrno; |
---|
1085 | |
---|
1086 | *pnptr = '\0'; |
---|
1087 | (void) stat("/.", &d); |
---|
1088 | rdev = d.st_dev; |
---|
1089 | rino = d.st_ino; |
---|
1090 | rsize = d.st_size; |
---|
1091 | for (;;) { |
---|
1092 | if (stat(".", &d) == -1) { |
---|
1093 | (void) xsnprintf(pathname, pathlen, CGETS(23, 24, |
---|
1094 | "getcwd: Cannot stat \".\" (%s)"), strerror(errno)); |
---|
1095 | goto fail; |
---|
1096 | } |
---|
1097 | if (d.st_ino == rino && d.st_dev == rdev && d.st_size == rsize) |
---|
1098 | break; /* reached root directory */ |
---|
1099 | if ((dirp = opendir("..")) == NULL) { |
---|
1100 | (void) xsnprintf(pathname, pathlen, CGETS(23, 19, |
---|
1101 | "getcwd: Cannot open \"..\" (%s)"), strerror(errno)); |
---|
1102 | goto fail; |
---|
1103 | } |
---|
1104 | if (chdir("..") == -1) { |
---|
1105 | (void) xsnprintf(pathname, pathlen, CGETS(23, 20, |
---|
1106 | "getcwd: Cannot chdir to \"..\" (%s)"), strerror(errno)); |
---|
1107 | goto fail; |
---|
1108 | } |
---|
1109 | do { |
---|
1110 | if ((dir = readdir(dirp)) == NULL) { |
---|
1111 | (void) xsnprintf(pathname, pathlen, |
---|
1112 | CGETS(23, 21, "getcwd: Read error in \"..\" (%s)"), |
---|
1113 | strerror(errno)); |
---|
1114 | goto fail; |
---|
1115 | } |
---|
1116 | if (stat(dir->d_name, &dd) == -1) { |
---|
1117 | (void) xsnprintf(pathname, pathlen, |
---|
1118 | CGETS(23, 25, "getcwd: Cannot stat directory \"%s\" (%s)"), |
---|
1119 | dir->d_name, strerror(errno)); |
---|
1120 | goto fail; |
---|
1121 | } |
---|
1122 | } while (dd.st_ino != d.st_ino || |
---|
1123 | dd.st_dev != d.st_dev || |
---|
1124 | dd.st_size != d.st_size); |
---|
1125 | (void) closedir(dirp); |
---|
1126 | dirp = NULL; |
---|
1127 | pnptr = strnrcpy(dirp->d_name, pnptr, pnptr - pathbuf); |
---|
1128 | pnptr = strnrcpy("/", pnptr, pnptr - pathbuf); |
---|
1129 | } |
---|
1130 | |
---|
1131 | if (*pnptr == '\0') /* current dir == root dir */ |
---|
1132 | (void) strncpy(pathname, "/", pathlen); |
---|
1133 | else { |
---|
1134 | (void) strncpy(pathname, pnptr, pathlen); |
---|
1135 | pathname[pathlen - 1] = '\0'; |
---|
1136 | if (chdir(pnptr) == -1) { |
---|
1137 | (void) xsnprintf(pathname, MAXPATHLEN, CGETS(23, 22, |
---|
1138 | "getcwd: Cannot change back to \".\" (%s)"), |
---|
1139 | strerror(errno)); |
---|
1140 | return NULL; |
---|
1141 | } |
---|
1142 | } |
---|
1143 | return pathname; |
---|
1144 | |
---|
1145 | fail: |
---|
1146 | serrno = errno; |
---|
1147 | (void) chdir(strnrcpy(".", pnptr, pnptr - pathbuf)); |
---|
1148 | errno = serrno; |
---|
1149 | return NULL; |
---|
1150 | } |
---|
1151 | |
---|
1152 | # else /* ! hp9000s500 */ |
---|
1153 | |
---|
1154 | # if (SYSVREL != 0 && !defined(d_fileno)) || defined(_VMS_POSIX) || defined(WINNT) |
---|
1155 | # define d_fileno d_ino |
---|
1156 | # endif |
---|
1157 | |
---|
1158 | char * |
---|
1159 | xgetcwd(pathname, pathlen) |
---|
1160 | char *pathname; |
---|
1161 | size_t pathlen; |
---|
1162 | { |
---|
1163 | DIR *dp; |
---|
1164 | struct dirent *d; |
---|
1165 | |
---|
1166 | struct stat st_root, st_cur, st_next, st_dotdot; |
---|
1167 | char pathbuf[MAXPATHLEN], nextpathbuf[MAXPATHLEN * 2]; |
---|
1168 | char *pathptr, *nextpathptr, *cur_name_add; |
---|
1169 | int save_errno = 0; |
---|
1170 | |
---|
1171 | /* find the inode of root */ |
---|
1172 | if (stat("/", &st_root) == -1) { |
---|
1173 | (void) xsnprintf(pathname, pathlen, CGETS(23, 23, |
---|
1174 | "getcwd: Cannot stat \"/\" (%s)"), |
---|
1175 | strerror(errno)); |
---|
1176 | return NULL; |
---|
1177 | } |
---|
1178 | pathbuf[MAXPATHLEN - 1] = '\0'; |
---|
1179 | pathptr = &pathbuf[MAXPATHLEN - 1]; |
---|
1180 | nextpathbuf[MAXPATHLEN - 1] = '\0'; |
---|
1181 | cur_name_add = nextpathptr = &nextpathbuf[MAXPATHLEN - 1]; |
---|
1182 | |
---|
1183 | /* find the inode of the current directory */ |
---|
1184 | if (lstat(".", &st_cur) == -1) { |
---|
1185 | (void) xsnprintf(pathname, pathlen, CGETS(23, 24, |
---|
1186 | "getcwd: Cannot stat \".\" (%s)"), |
---|
1187 | strerror(errno)); |
---|
1188 | return NULL; |
---|
1189 | } |
---|
1190 | nextpathptr = strnrcpy(nextpathptr, "../", nextpathptr - nextpathbuf); |
---|
1191 | |
---|
1192 | /* Descend to root */ |
---|
1193 | for (;;) { |
---|
1194 | |
---|
1195 | /* look if we found root yet */ |
---|
1196 | if (st_cur.st_ino == st_root.st_ino && |
---|
1197 | DEV_DEV_COMPARE(st_cur.st_dev, st_root.st_dev)) { |
---|
1198 | (void) strncpy(pathname, *pathptr != '/' ? "/" : pathptr, pathlen); |
---|
1199 | pathname[pathlen - 1] = '\0'; |
---|
1200 | return pathname; |
---|
1201 | } |
---|
1202 | |
---|
1203 | /* open the parent directory */ |
---|
1204 | if (stat(nextpathptr, &st_dotdot) == -1) { |
---|
1205 | (void) xsnprintf(pathname, pathlen, CGETS(23, 25, |
---|
1206 | "getcwd: Cannot stat directory \"%s\" (%s)"), |
---|
1207 | nextpathptr, strerror(errno)); |
---|
1208 | return NULL; |
---|
1209 | } |
---|
1210 | if ((dp = opendir(nextpathptr)) == NULL) { |
---|
1211 | (void) xsnprintf(pathname, pathlen, CGETS(23, 26, |
---|
1212 | "getcwd: Cannot open directory \"%s\" (%s)"), |
---|
1213 | nextpathptr, strerror(errno)); |
---|
1214 | return NULL; |
---|
1215 | } |
---|
1216 | |
---|
1217 | /* look in the parent for the entry with the same inode */ |
---|
1218 | if (DEV_DEV_COMPARE(st_dotdot.st_dev, st_cur.st_dev)) { |
---|
1219 | /* Parent has same device. No need to stat every member */ |
---|
1220 | for (d = readdir(dp); d != NULL; d = readdir(dp)) { |
---|
1221 | #ifdef __clipper__ |
---|
1222 | if (((unsigned long)d->d_fileno & 0xffff) == st_cur.st_ino) |
---|
1223 | break; |
---|
1224 | #else |
---|
1225 | if (d->d_fileno == st_cur.st_ino) |
---|
1226 | break; |
---|
1227 | #endif |
---|
1228 | } |
---|
1229 | } |
---|
1230 | else { |
---|
1231 | /* |
---|
1232 | * Parent has a different device. This is a mount point so we |
---|
1233 | * need to stat every member |
---|
1234 | */ |
---|
1235 | for (d = readdir(dp); d != NULL; d = readdir(dp)) { |
---|
1236 | if (ISDOT(d->d_name) || ISDOTDOT(d->d_name)) |
---|
1237 | continue; |
---|
1238 | (void)strncpy(cur_name_add, d->d_name, |
---|
1239 | &nextpathbuf[sizeof(nextpathbuf) - 1] - cur_name_add); |
---|
1240 | if (lstat(nextpathptr, &st_next) == -1) { |
---|
1241 | /* |
---|
1242 | * We might not be able to stat() some path components |
---|
1243 | * if we are using afs, but this is not an error as |
---|
1244 | * long as we find the one we need; we also save the |
---|
1245 | * first error to report it if we don't finally succeed. |
---|
1246 | */ |
---|
1247 | if (save_errno == 0) |
---|
1248 | save_errno = errno; |
---|
1249 | continue; |
---|
1250 | } |
---|
1251 | /* check if we found it yet */ |
---|
1252 | if (st_next.st_ino == st_cur.st_ino && |
---|
1253 | DEV_DEV_COMPARE(st_next.st_dev, st_cur.st_dev)) |
---|
1254 | break; |
---|
1255 | } |
---|
1256 | } |
---|
1257 | if (d == NULL) { |
---|
1258 | (void) xsnprintf(pathname, pathlen, CGETS(23, 27, |
---|
1259 | "getcwd: Cannot find \".\" in \"..\" (%s)"), |
---|
1260 | strerror(save_errno ? save_errno : ENOENT)); |
---|
1261 | (void) closedir(dp); |
---|
1262 | return NULL; |
---|
1263 | } |
---|
1264 | else |
---|
1265 | save_errno = 0; |
---|
1266 | st_cur = st_dotdot; |
---|
1267 | pathptr = strnrcpy(pathptr, d->d_name, pathptr - pathbuf); |
---|
1268 | pathptr = strnrcpy(pathptr, "/", pathptr - pathbuf); |
---|
1269 | nextpathptr = strnrcpy(nextpathptr, "../", nextpathptr - nextpathbuf); |
---|
1270 | *cur_name_add = '\0'; |
---|
1271 | (void) closedir(dp); |
---|
1272 | } |
---|
1273 | } /* end getcwd */ |
---|
1274 | # endif /* hp9000s500 */ |
---|
1275 | |
---|
1276 | /* strnrcpy(): |
---|
1277 | * Like strncpy, going backwards and returning the new pointer |
---|
1278 | */ |
---|
1279 | static char * |
---|
1280 | strnrcpy(ptr, str, siz) |
---|
1281 | register char *ptr, *str; |
---|
1282 | size_t siz; |
---|
1283 | { |
---|
1284 | register int len = strlen(str); |
---|
1285 | if (siz == 0) |
---|
1286 | return ptr; |
---|
1287 | |
---|
1288 | while (len && siz--) |
---|
1289 | *--ptr = str[--len]; |
---|
1290 | |
---|
1291 | return (ptr); |
---|
1292 | } /* end strnrcpy */ |
---|
1293 | #endif /* getcwd */ |
---|
1294 | |
---|
1295 | #ifdef apollo |
---|
1296 | /*** |
---|
1297 | *** Domain/OS |
---|
1298 | ***/ |
---|
1299 | #include <apollo/base.h> |
---|
1300 | #include <apollo/loader.h> |
---|
1301 | #include <apollo/error.h> |
---|
1302 | |
---|
1303 | |
---|
1304 | static char * |
---|
1305 | apperr(st) |
---|
1306 | status_$t *st; |
---|
1307 | { |
---|
1308 | static char buf[BUFSIZE]; |
---|
1309 | short e_subl, e_modl, e_codel; |
---|
1310 | error_$string_t e_sub, e_mod, e_code; |
---|
1311 | |
---|
1312 | error_$get_text(*st, e_sub, &e_subl, e_mod, &e_modl, e_code, &e_codel); |
---|
1313 | e_sub[e_subl] = '\0'; |
---|
1314 | e_code[e_codel] = '\0'; |
---|
1315 | e_mod[e_modl] = '\0'; |
---|
1316 | (void) xsnprintf(buf, sizeof(buf), "%s (%s/%s)", e_code, e_sub, e_mod); |
---|
1317 | |
---|
1318 | return(buf); |
---|
1319 | } |
---|
1320 | |
---|
1321 | static int |
---|
1322 | llib(s) |
---|
1323 | Char *s; |
---|
1324 | { |
---|
1325 | short len = Strlen(s); |
---|
1326 | status_$t st; |
---|
1327 | char *t; |
---|
1328 | |
---|
1329 | loader_$inlib(t = short2str(s), len, &st); |
---|
1330 | if (st.all != status_$ok) |
---|
1331 | stderror(ERR_SYSTEM, t, apperr(&st)); |
---|
1332 | } |
---|
1333 | |
---|
1334 | /*ARGSUSED*/ |
---|
1335 | void |
---|
1336 | doinlib(v, c) |
---|
1337 | Char **v; |
---|
1338 | struct command *c; |
---|
1339 | { |
---|
1340 | setname(short2str(*v++)); |
---|
1341 | gflag = 0, tglob(v); |
---|
1342 | if (gflag) { |
---|
1343 | v = globall(v); |
---|
1344 | if (v == 0) |
---|
1345 | stderror(ERR_NAME | ERR_NOMATCH); |
---|
1346 | } |
---|
1347 | else { |
---|
1348 | v = gargv = saveblk(v); |
---|
1349 | trim(v); |
---|
1350 | } |
---|
1351 | |
---|
1352 | while (v && *v) |
---|
1353 | llib(*v++); |
---|
1354 | if (gargv) |
---|
1355 | blkfree(gargv), gargv = 0; |
---|
1356 | } |
---|
1357 | |
---|
1358 | int |
---|
1359 | getv(v) |
---|
1360 | Char *v; |
---|
1361 | { |
---|
1362 | if (eq(v, STRbsd43)) |
---|
1363 | return(1); |
---|
1364 | else if (eq(v, STRsys53)) |
---|
1365 | return(0); |
---|
1366 | else |
---|
1367 | stderror(ERR_NAME | ERR_SYSTEM, short2str(v), |
---|
1368 | CGETS(23, 28, "Invalid system type")); |
---|
1369 | /*NOTREACHED*/ |
---|
1370 | return(0); |
---|
1371 | } |
---|
1372 | |
---|
1373 | /*ARGSUSED*/ |
---|
1374 | void |
---|
1375 | dover(v, c) |
---|
1376 | Char **v; |
---|
1377 | struct command *c; |
---|
1378 | { |
---|
1379 | Char *p; |
---|
1380 | |
---|
1381 | setname(short2str(*v++)); |
---|
1382 | if (!*v) { |
---|
1383 | if (!(p = tgetenv(STRSYSTYPE))) |
---|
1384 | stderror(ERR_NAME | ERR_STRING, |
---|
1385 | CGETS(23, 29, "System type is not set")); |
---|
1386 | xprintf("%S\n", p); |
---|
1387 | } |
---|
1388 | else { |
---|
1389 | tsetenv(STRSYSTYPE, getv(*v) ? STRbsd43 : STRsys53); |
---|
1390 | dohash(NULL, NULL); |
---|
1391 | } |
---|
1392 | } |
---|
1393 | |
---|
1394 | /* |
---|
1395 | * Many thanks to rees@citi.umich.edu (Jim Rees) and |
---|
1396 | * mathys@ssdt-tempe.sps.mot.com (Yves Mathys) |
---|
1397 | * For figuring out how to do this... I could have never done |
---|
1398 | * it without their help. |
---|
1399 | */ |
---|
1400 | typedef short enum { |
---|
1401 | name_$wdir_type, |
---|
1402 | name_$ndir_type, |
---|
1403 | name_$node_dir_type, |
---|
1404 | } name_$dir_type_t; |
---|
1405 | |
---|
1406 | /*ARGSUSED*/ |
---|
1407 | void |
---|
1408 | dorootnode(v, c) |
---|
1409 | Char **v; |
---|
1410 | struct command *c; |
---|
1411 | { |
---|
1412 | name_$dir_type_t dirtype = name_$node_dir_type; |
---|
1413 | uid_$t uid; |
---|
1414 | status_$t st; |
---|
1415 | char *name; |
---|
1416 | short namelen; |
---|
1417 | |
---|
1418 | setname(short2str(*v++)); |
---|
1419 | |
---|
1420 | name = short2str(*v); |
---|
1421 | namelen = strlen(name); |
---|
1422 | |
---|
1423 | name_$resolve(name, &namelen, &uid, &st); |
---|
1424 | if (st.all != status_$ok) |
---|
1425 | stderror(ERR_SYSTEM, name, apperr(&st)); |
---|
1426 | namelen = 0; |
---|
1427 | name_$set_diru(&uid, "", &namelen, &dirtype, &st); |
---|
1428 | if (st.all != status_$ok) |
---|
1429 | stderror(ERR_SYSTEM, name, apperr(&st)); |
---|
1430 | dohash(NULL, NULL); |
---|
1431 | } |
---|
1432 | |
---|
1433 | int |
---|
1434 | isapad() |
---|
1435 | { |
---|
1436 | static int res = -1; |
---|
1437 | static status_$t st; |
---|
1438 | |
---|
1439 | if (res == -1) { |
---|
1440 | int strm; |
---|
1441 | if (isatty(0)) |
---|
1442 | strm = 0; |
---|
1443 | if (isatty(1)) |
---|
1444 | strm = 1; |
---|
1445 | if (isatty(2)) |
---|
1446 | strm = 2; |
---|
1447 | else { |
---|
1448 | res = 0; |
---|
1449 | st.all = status_$ok; |
---|
1450 | return(res); |
---|
1451 | } |
---|
1452 | res = stream_$isavt(&strm, &st); |
---|
1453 | res = res ? 1 : 0; |
---|
1454 | } |
---|
1455 | else { |
---|
1456 | if (st.all != status_$ok) |
---|
1457 | stderror(ERR_SYSTEM, "stream_$isavt", apperr(&st)); |
---|
1458 | } |
---|
1459 | return(res); |
---|
1460 | } |
---|
1461 | #endif |
---|