1 | /* $Header: /afs/dev.mit.edu/source/repository/third/tcsh/tc.func.c,v 1.1.1.2 1998-10-03 21:10:12 danw Exp $ */ |
---|
2 | /* |
---|
3 | * tc.func.c: New tcsh builtins. |
---|
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.func.c,v 1.1.1.2 1998-10-03 21:10:12 danw Exp $") |
---|
40 | |
---|
41 | #include "ed.h" |
---|
42 | #include "ed.defns.h" /* for the function names */ |
---|
43 | #include "tw.h" |
---|
44 | #include "tc.h" |
---|
45 | #ifdef WINNT |
---|
46 | #include "nt.const.h" |
---|
47 | #endif /* WINNT */ |
---|
48 | |
---|
49 | #ifdef AFS |
---|
50 | #define PASSMAX 16 |
---|
51 | #include <afs/stds.h> |
---|
52 | #include <afs/kautils.h> |
---|
53 | long ka_UserAuthenticateGeneral(); |
---|
54 | #else |
---|
55 | #ifndef PASSMAX |
---|
56 | #define PASSMAX 8 |
---|
57 | #endif |
---|
58 | #endif /* AFS */ |
---|
59 | |
---|
60 | #ifdef TESLA |
---|
61 | extern int do_logout; |
---|
62 | #endif /* TESLA */ |
---|
63 | extern time_t t_period; |
---|
64 | extern int just_signaled; |
---|
65 | static bool precmd_active = 0; |
---|
66 | static bool periodic_active = 0; |
---|
67 | static bool cwdcmd_active = 0; /* PWP: for cwd_cmd */ |
---|
68 | static bool beepcmd_active = 0; |
---|
69 | static signalfun_t alm_fun = NULL; |
---|
70 | |
---|
71 | static void Reverse __P((Char *)); |
---|
72 | static void auto_logout __P((int)); |
---|
73 | static char *xgetpass __P((char *)); |
---|
74 | static void auto_lock __P((int)); |
---|
75 | #ifdef BSDJOBS |
---|
76 | static void insert __P((struct wordent *, bool)); |
---|
77 | static void insert_we __P((struct wordent *, struct wordent *)); |
---|
78 | static int inlist __P((Char *, Char *)); |
---|
79 | #endif /* BSDJOBS */ |
---|
80 | struct tildecache; |
---|
81 | static int tildecompare __P((struct tildecache *, struct tildecache *)); |
---|
82 | static Char *gethomedir __P((Char *)); |
---|
83 | #ifdef REMOTEHOST |
---|
84 | static sigret_t palarm __P((int)); |
---|
85 | static void getremotehost __P((void)); |
---|
86 | #endif /* REMOTEHOST */ |
---|
87 | |
---|
88 | /* |
---|
89 | * Tops-C shell |
---|
90 | */ |
---|
91 | |
---|
92 | /* |
---|
93 | * expand_lex: Take the given lex and put an expanded version of it in the |
---|
94 | * string buf. First guy in lex list is ignored; last guy is ^J which we |
---|
95 | * ignore Only take lex'es from position from to position to inclusive Note: |
---|
96 | * csh sometimes sets bit 8 in characters which causes all kinds of problems |
---|
97 | * if we don't mask it here. Note: excl's in lexes have been un-back-slashed |
---|
98 | * and must be re-back-slashed |
---|
99 | * (PWP: NOTE: this returns a pointer to the END of the string expanded |
---|
100 | * (in other words, where the NUL is).) |
---|
101 | */ |
---|
102 | /* PWP: this is a combination of the old sprlex() and the expand_lex from |
---|
103 | the magic-space stuff */ |
---|
104 | |
---|
105 | Char * |
---|
106 | expand_lex(buf, bufsiz, sp0, from, to) |
---|
107 | Char *buf; |
---|
108 | size_t bufsiz; |
---|
109 | struct wordent *sp0; |
---|
110 | int from, to; |
---|
111 | { |
---|
112 | register struct wordent *sp; |
---|
113 | register Char *s, *d, *e; |
---|
114 | register Char prev_c; |
---|
115 | register int i; |
---|
116 | |
---|
117 | buf[0] = '\0'; |
---|
118 | prev_c = '\0'; |
---|
119 | d = buf; |
---|
120 | e = &buf[bufsiz]; /* for bounds checking */ |
---|
121 | |
---|
122 | if (!sp0) |
---|
123 | return (buf); /* null lex */ |
---|
124 | if ((sp = sp0->next) == sp0) |
---|
125 | return (buf); /* nada */ |
---|
126 | if (sp == (sp0 = sp0->prev)) |
---|
127 | return (buf); /* nada */ |
---|
128 | |
---|
129 | for (i = 0; i < NCARGS; i++) { |
---|
130 | if ((i >= from) && (i <= to)) { /* if in range */ |
---|
131 | for (s = sp->word; *s && d < e; s++) { |
---|
132 | /* |
---|
133 | * bugfix by Michael Bloom: anything but the current history |
---|
134 | * character {(PWP) and backslash} seem to be dealt with |
---|
135 | * elsewhere. |
---|
136 | */ |
---|
137 | if ((*s & QUOTE) |
---|
138 | && (((*s & TRIM) == HIST) || |
---|
139 | (((*s & TRIM) == '\'') && (prev_c != '\\')) || |
---|
140 | (((*s & TRIM) == '\"') && (prev_c != '\\')) || |
---|
141 | (((*s & TRIM) == '\\') && (prev_c != '\\')))) { |
---|
142 | *d++ = '\\'; |
---|
143 | } |
---|
144 | if (d < e) |
---|
145 | *d++ = (*s & TRIM); |
---|
146 | prev_c = *s; |
---|
147 | } |
---|
148 | if (d < e) |
---|
149 | *d++ = ' '; |
---|
150 | } |
---|
151 | sp = sp->next; |
---|
152 | if (sp == sp0) |
---|
153 | break; |
---|
154 | } |
---|
155 | if (d > buf) |
---|
156 | d--; /* get rid of trailing space */ |
---|
157 | |
---|
158 | return (d); |
---|
159 | } |
---|
160 | |
---|
161 | Char * |
---|
162 | sprlex(buf, bufsiz, sp0) |
---|
163 | Char *buf; |
---|
164 | size_t bufsiz; |
---|
165 | struct wordent *sp0; |
---|
166 | { |
---|
167 | Char *cp; |
---|
168 | |
---|
169 | cp = expand_lex(buf, bufsiz, sp0, 0, NCARGS); |
---|
170 | *cp = '\0'; |
---|
171 | return (buf); |
---|
172 | } |
---|
173 | |
---|
174 | void |
---|
175 | Itoa(n, s) /* convert n to characters in s */ |
---|
176 | int n; |
---|
177 | Char *s; |
---|
178 | { |
---|
179 | int i, sign; |
---|
180 | |
---|
181 | if ((sign = n) < 0) /* record sign */ |
---|
182 | n = -n; |
---|
183 | i = 0; |
---|
184 | do { |
---|
185 | s[i++] = n % 10 + '0'; |
---|
186 | } while ((n /= 10) > 0); |
---|
187 | if (sign < 0) |
---|
188 | s[i++] = '-'; |
---|
189 | s[i] = '\0'; |
---|
190 | Reverse(s); |
---|
191 | } |
---|
192 | |
---|
193 | static void |
---|
194 | Reverse(s) |
---|
195 | Char *s; |
---|
196 | { |
---|
197 | Char c; |
---|
198 | int i, j; |
---|
199 | |
---|
200 | for (i = 0, j = (int) Strlen(s) - 1; i < j; i++, j--) { |
---|
201 | c = s[i]; |
---|
202 | s[i] = s[j]; |
---|
203 | s[j] = c; |
---|
204 | } |
---|
205 | } |
---|
206 | |
---|
207 | |
---|
208 | /*ARGSUSED*/ |
---|
209 | void |
---|
210 | dolist(v, c) |
---|
211 | register Char **v; |
---|
212 | struct command *c; |
---|
213 | { |
---|
214 | int i, k; |
---|
215 | struct stat st; |
---|
216 | #ifdef COLOR_LS_F |
---|
217 | extern bool color_context_ls; |
---|
218 | #endif /* COLOR_LS_F */ |
---|
219 | |
---|
220 | USE(c); |
---|
221 | if (*++v == NULL) { |
---|
222 | (void) t_search(STRNULL, NULL, LIST, 0, TW_ZERO, 0, STRNULL, 0); |
---|
223 | return; |
---|
224 | } |
---|
225 | gflag = 0; |
---|
226 | tglob(v); |
---|
227 | if (gflag) { |
---|
228 | v = globall(v); |
---|
229 | if (v == 0) |
---|
230 | stderror(ERR_NAME | ERR_NOMATCH); |
---|
231 | } |
---|
232 | else |
---|
233 | v = gargv = saveblk(v); |
---|
234 | trim(v); |
---|
235 | for (k = 0; v[k] != NULL && v[k][0] != '-'; k++) |
---|
236 | continue; |
---|
237 | if (v[k]) { |
---|
238 | /* |
---|
239 | * We cannot process a flag therefore we let ls do it right. |
---|
240 | */ |
---|
241 | static Char STRls[] = {'l', 's', '\0'}; |
---|
242 | static Char STRmCF[] = {'-', 'C', 'F', '\0', '\0' }; |
---|
243 | Char *lspath; |
---|
244 | struct command *t; |
---|
245 | struct wordent cmd, *nextword, *lastword; |
---|
246 | Char *cp; |
---|
247 | struct varent *vp; |
---|
248 | |
---|
249 | #ifdef BSDSIGS |
---|
250 | sigmask_t omask = 0; |
---|
251 | |
---|
252 | if (setintr) |
---|
253 | omask = sigblock(sigmask(SIGINT)) & ~sigmask(SIGINT); |
---|
254 | #else /* !BSDSIGS */ |
---|
255 | (void) sighold(SIGINT); |
---|
256 | #endif /* BSDSIGS */ |
---|
257 | if (seterr) { |
---|
258 | xfree((ptr_t) seterr); |
---|
259 | seterr = NULL; |
---|
260 | } |
---|
261 | |
---|
262 | lspath = STRls; |
---|
263 | STRmCF[1] = 'C'; |
---|
264 | STRmCF[3] = '\0'; |
---|
265 | /* Look at listflags, to add -A to the flags, to get a path |
---|
266 | of ls if necessary */ |
---|
267 | if ((vp = adrof(STRlistflags)) != NULL && vp->vec[0] != STRNULL) { |
---|
268 | if (vp->vec[1] != NULL && vp->vec[1][0] != '\0') |
---|
269 | lspath = vp->vec[1]; |
---|
270 | for (cp = vp->vec[0]; *cp; cp++) |
---|
271 | switch (*cp) { |
---|
272 | case 'x': |
---|
273 | STRmCF[1] = 'x'; |
---|
274 | break; |
---|
275 | case 'a': |
---|
276 | STRmCF[3] = 'a'; |
---|
277 | break; |
---|
278 | case 'A': |
---|
279 | STRmCF[3] = 'A'; |
---|
280 | break; |
---|
281 | default: |
---|
282 | break; |
---|
283 | } |
---|
284 | } |
---|
285 | |
---|
286 | cmd.word = STRNULL; |
---|
287 | lastword = &cmd; |
---|
288 | nextword = (struct wordent *) xcalloc(1, sizeof cmd); |
---|
289 | nextword->word = Strsave(lspath); |
---|
290 | lastword->next = nextword; |
---|
291 | nextword->prev = lastword; |
---|
292 | lastword = nextword; |
---|
293 | nextword = (struct wordent *) xcalloc(1, sizeof cmd); |
---|
294 | nextword->word = Strsave(STRmCF); |
---|
295 | lastword->next = nextword; |
---|
296 | nextword->prev = lastword; |
---|
297 | #ifdef COLOR_LS_F |
---|
298 | if (color_context_ls) { |
---|
299 | lastword = nextword; |
---|
300 | nextword = (struct wordent *) xcalloc(1, sizeof cmd); |
---|
301 | nextword->word = Strsave(STRmmcolormauto); |
---|
302 | lastword->next = nextword; |
---|
303 | nextword->prev = lastword; |
---|
304 | } |
---|
305 | #endif /* COLOR_LS_F */ |
---|
306 | lastword = nextword; |
---|
307 | for (cp = *v; cp; cp = *++v) { |
---|
308 | nextword = (struct wordent *) xcalloc(1, sizeof cmd); |
---|
309 | nextword->word = Strsave(cp); |
---|
310 | lastword->next = nextword; |
---|
311 | nextword->prev = lastword; |
---|
312 | lastword = nextword; |
---|
313 | } |
---|
314 | lastword->next = &cmd; |
---|
315 | cmd.prev = lastword; |
---|
316 | |
---|
317 | /* build a syntax tree for the command. */ |
---|
318 | t = syntax(cmd.next, &cmd, 0); |
---|
319 | if (seterr) |
---|
320 | stderror(ERR_OLD); |
---|
321 | /* expand aliases like process() does */ |
---|
322 | /* alias(&cmd); */ |
---|
323 | /* execute the parse tree. */ |
---|
324 | execute(t, tpgrp > 0 ? tpgrp : -1, NULL, NULL); |
---|
325 | /* done. free the lex list and parse tree. */ |
---|
326 | freelex(&cmd), freesyn(t); |
---|
327 | if (setintr) |
---|
328 | #ifdef BSDSIGS |
---|
329 | (void) sigsetmask(omask); |
---|
330 | #else /* !BSDSIGS */ |
---|
331 | (void) sigrelse(SIGINT); |
---|
332 | #endif /* BSDSIGS */ |
---|
333 | } |
---|
334 | else { |
---|
335 | Char *dp, *tmp, buf[MAXPATHLEN]; |
---|
336 | #ifdef WINNT |
---|
337 | int is_unc = 0; |
---|
338 | #endif /* WINNT */ |
---|
339 | |
---|
340 | for (k = 0, i = 0; v[k] != NULL; k++) { |
---|
341 | tmp = dnormalize(v[k], symlinks == SYM_IGNORE); |
---|
342 | dp = &tmp[Strlen(tmp) - 1]; |
---|
343 | if (*dp == '/' && dp != tmp) |
---|
344 | #ifdef apollo |
---|
345 | if (dp != &tmp[1]) |
---|
346 | #endif /* apollo */ |
---|
347 | *dp = '\0'; |
---|
348 | #ifdef WINNT |
---|
349 | if ((((tmp[0] & CHAR) == '/') || ((tmp[0] & CHAR) == '\\')) && |
---|
350 | (((tmp[1] & CHAR) == '/') || ((tmp[1] & CHAR) == '\\'))) |
---|
351 | is_unc = 1; |
---|
352 | #endif /* WINNT */ |
---|
353 | if ( |
---|
354 | #ifdef WINNT |
---|
355 | ((char)tmp[1] != ':') && |
---|
356 | (!is_unc) && |
---|
357 | #endif /* WINNT */ |
---|
358 | stat(short2str(tmp), &st) == -1) { |
---|
359 | if (k != i) { |
---|
360 | if (i != 0) |
---|
361 | xputchar('\n'); |
---|
362 | print_by_column(STRNULL, &v[i], k - i, FALSE); |
---|
363 | } |
---|
364 | xprintf("%S: %s.\n", tmp, strerror(errno)); |
---|
365 | i = k + 1; |
---|
366 | } |
---|
367 | else if ( |
---|
368 | #ifdef WINNT |
---|
369 | ((char)tmp[1] == ':') || |
---|
370 | (is_unc) || |
---|
371 | #endif /* WINNT */ |
---|
372 | S_ISDIR(st.st_mode)) { |
---|
373 | Char *cp; |
---|
374 | |
---|
375 | if (k != i) { |
---|
376 | if (i != 0) |
---|
377 | xputchar('\n'); |
---|
378 | print_by_column(STRNULL, &v[i], k - i, FALSE); |
---|
379 | } |
---|
380 | if (k != 0 && v[1] != NULL) |
---|
381 | xputchar('\n'); |
---|
382 | xprintf("%S:\n", tmp); |
---|
383 | for (cp = tmp, dp = buf; *cp; *dp++ = (*cp++ | QUOTE)) |
---|
384 | continue; |
---|
385 | if ( |
---|
386 | #ifdef WINNT |
---|
387 | (dp[-1] != (Char) (':' | QUOTE)) && |
---|
388 | #endif /* WINNT */ |
---|
389 | (dp[-1] != (Char) ('/' | QUOTE))) |
---|
390 | *dp++ = '/'; |
---|
391 | else |
---|
392 | dp[-1] &= TRIM; |
---|
393 | *dp = '\0'; |
---|
394 | (void) t_search(buf, NULL, LIST, 0, TW_ZERO, 0, STRNULL, 0); |
---|
395 | i = k + 1; |
---|
396 | } |
---|
397 | xfree((ptr_t) tmp); |
---|
398 | } |
---|
399 | if (k != i) { |
---|
400 | if (i != 0) |
---|
401 | xputchar('\n'); |
---|
402 | print_by_column(STRNULL, &v[i], k - i, FALSE); |
---|
403 | } |
---|
404 | } |
---|
405 | |
---|
406 | if (gargv) { |
---|
407 | blkfree(gargv); |
---|
408 | gargv = 0; |
---|
409 | } |
---|
410 | } |
---|
411 | |
---|
412 | static char *defaulttell = "ALL"; |
---|
413 | extern bool GotTermCaps; |
---|
414 | |
---|
415 | /*ARGSUSED*/ |
---|
416 | void |
---|
417 | dotelltc(v, c) |
---|
418 | register Char **v; |
---|
419 | struct command *c; |
---|
420 | { |
---|
421 | USE(c); |
---|
422 | if (!GotTermCaps) |
---|
423 | GetTermCaps(); |
---|
424 | |
---|
425 | /* |
---|
426 | * Avoid a compiler bug on hpux 9.05 |
---|
427 | * Writing the following as func(a ? b : c) breaks |
---|
428 | */ |
---|
429 | if (v[1]) |
---|
430 | TellTC(short2str(v[1])); |
---|
431 | else |
---|
432 | TellTC(defaulttell); |
---|
433 | } |
---|
434 | |
---|
435 | /*ARGSUSED*/ |
---|
436 | void |
---|
437 | doechotc(v, c) |
---|
438 | register Char **v; |
---|
439 | struct command *c; |
---|
440 | { |
---|
441 | if (!GotTermCaps) |
---|
442 | GetTermCaps(); |
---|
443 | EchoTC(++v); |
---|
444 | } |
---|
445 | |
---|
446 | /*ARGSUSED*/ |
---|
447 | void |
---|
448 | dosettc(v, c) |
---|
449 | Char **v; |
---|
450 | struct command *c; |
---|
451 | { |
---|
452 | char tv[2][BUFSIZE]; |
---|
453 | |
---|
454 | if (!GotTermCaps) |
---|
455 | GetTermCaps(); |
---|
456 | |
---|
457 | (void) strcpy(tv[0], short2str(v[1])); |
---|
458 | (void) strcpy(tv[1], short2str(v[2])); |
---|
459 | SetTC(tv[0], tv[1]); |
---|
460 | } |
---|
461 | |
---|
462 | /* The dowhich() is by: |
---|
463 | * Andreas Luik <luik@isaak.isa.de> |
---|
464 | * I S A GmbH - Informationssysteme fuer computerintegrierte Automatisierung |
---|
465 | * Azenberstr. 35 |
---|
466 | * D-7000 Stuttgart 1 |
---|
467 | * West-Germany |
---|
468 | * Thanks!! |
---|
469 | */ |
---|
470 | int |
---|
471 | cmd_expand(cmd, str) |
---|
472 | Char *cmd; |
---|
473 | Char *str; |
---|
474 | { |
---|
475 | struct wordent lexp[3]; |
---|
476 | struct varent *vp; |
---|
477 | int rv = TRUE; |
---|
478 | |
---|
479 | lexp[0].next = &lexp[1]; |
---|
480 | lexp[1].next = &lexp[2]; |
---|
481 | lexp[2].next = &lexp[0]; |
---|
482 | |
---|
483 | lexp[0].prev = &lexp[2]; |
---|
484 | lexp[1].prev = &lexp[0]; |
---|
485 | lexp[2].prev = &lexp[1]; |
---|
486 | |
---|
487 | lexp[0].word = STRNULL; |
---|
488 | lexp[2].word = STRret; |
---|
489 | |
---|
490 | if ((vp = adrof1(cmd, &aliases)) != NULL) { |
---|
491 | if (str == NULL) { |
---|
492 | xprintf(CGETS(22, 1, "%S: \t aliased to "), cmd); |
---|
493 | blkpr(vp->vec); |
---|
494 | xputchar('\n'); |
---|
495 | } |
---|
496 | else |
---|
497 | blkexpand(vp->vec, str); |
---|
498 | } |
---|
499 | else { |
---|
500 | lexp[1].word = cmd; |
---|
501 | rv = tellmewhat(lexp, str); |
---|
502 | } |
---|
503 | return rv; |
---|
504 | } |
---|
505 | |
---|
506 | |
---|
507 | /*ARGSUSED*/ |
---|
508 | void |
---|
509 | dowhich(v, c) |
---|
510 | register Char **v; |
---|
511 | struct command *c; |
---|
512 | { |
---|
513 | int rv = TRUE; |
---|
514 | USE(c); |
---|
515 | |
---|
516 | #ifdef notdef |
---|
517 | /* |
---|
518 | * We don't want to glob dowhich args because we lose quoteing |
---|
519 | * E.g. which \ls if ls is aliased will not work correctly if |
---|
520 | * we glob here. |
---|
521 | */ |
---|
522 | gflag = 0, tglob(v); |
---|
523 | if (gflag) { |
---|
524 | v = globall(v); |
---|
525 | if (v == 0) |
---|
526 | stderror(ERR_NAME | ERR_NOMATCH); |
---|
527 | } |
---|
528 | else { |
---|
529 | v = gargv = saveblk(v); |
---|
530 | trim(v); |
---|
531 | } |
---|
532 | #endif |
---|
533 | |
---|
534 | while (*++v) |
---|
535 | rv &= cmd_expand(*v, NULL); |
---|
536 | |
---|
537 | if (!rv) |
---|
538 | set(STRstatus, Strsave(STR1), VAR_READWRITE); |
---|
539 | |
---|
540 | #ifdef notdef |
---|
541 | /* Again look at the comment above; since we don't glob, we don't free */ |
---|
542 | if (gargv) |
---|
543 | blkfree(gargv), gargv = 0; |
---|
544 | #endif |
---|
545 | } |
---|
546 | |
---|
547 | /* PWP: a hack to start up your stopped editor on a single keystroke */ |
---|
548 | /* jbs - fixed hack so it worked :-) 3/28/89 */ |
---|
549 | |
---|
550 | struct process * |
---|
551 | find_stop_ed() |
---|
552 | { |
---|
553 | register struct process *pp, *retp; |
---|
554 | register char *ep, *vp, *cp, *p; |
---|
555 | int epl, vpl, pstatus; |
---|
556 | |
---|
557 | if ((ep = getenv("EDITOR")) != NULL) { /* if we have a value */ |
---|
558 | if ((p = strrchr(ep, '/')) != NULL) /* if it has a path */ |
---|
559 | ep = p + 1; /* then we want only the last part */ |
---|
560 | } |
---|
561 | else |
---|
562 | ep = "ed"; |
---|
563 | |
---|
564 | if ((vp = getenv("VISUAL")) != NULL) { /* if we have a value */ |
---|
565 | if ((p = strrchr(vp, '/')) != NULL) /* and it has a path */ |
---|
566 | vp = p + 1; /* then we want only the last part */ |
---|
567 | } |
---|
568 | else |
---|
569 | vp = "vi"; |
---|
570 | |
---|
571 | for (vpl = 0; vp[vpl] && !Isspace(vp[vpl]); vpl++) |
---|
572 | continue; |
---|
573 | for (epl = 0; ep[epl] && !Isspace(ep[epl]); epl++) |
---|
574 | continue; |
---|
575 | |
---|
576 | if (pcurrent == NULL) /* see if we have any jobs */ |
---|
577 | return NULL; /* nope */ |
---|
578 | |
---|
579 | retp = NULL; |
---|
580 | for (pp = proclist.p_next; pp; pp = pp->p_next) |
---|
581 | if (pp->p_procid == pp->p_jobid) { |
---|
582 | |
---|
583 | /* |
---|
584 | * Only foreground an edit session if it is suspended. Some GUI |
---|
585 | * editors have may be happily running in a separate window, no |
---|
586 | * point in foregrounding these if they're already running - webb |
---|
587 | */ |
---|
588 | pstatus = pp->p_flags & PALLSTATES; |
---|
589 | if (pstatus != PINTERRUPTED && pstatus != PSTOPPED && |
---|
590 | pstatus != PSIGNALED) |
---|
591 | continue; |
---|
592 | |
---|
593 | p = short2str(pp->p_command); |
---|
594 | /* get the first word */ |
---|
595 | for (cp = p; *cp && !isspace((unsigned char) *cp); cp++) |
---|
596 | continue; |
---|
597 | *cp = '\0'; |
---|
598 | |
---|
599 | if ((cp = strrchr(p, '/')) != NULL) /* and it has a path */ |
---|
600 | cp = cp + 1; /* then we want only the last part */ |
---|
601 | else |
---|
602 | cp = p; /* else we get all of it */ |
---|
603 | |
---|
604 | /* if we find either in the current name, fg it */ |
---|
605 | if (strncmp(ep, cp, (size_t) epl) == 0 || |
---|
606 | strncmp(vp, cp, (size_t) vpl) == 0) { |
---|
607 | |
---|
608 | /* |
---|
609 | * If there is a choice, then choose the current process if |
---|
610 | * available, or the previous process otherwise, or else |
---|
611 | * anything will do - Robert Webb (robertw@mulga.cs.mu.oz.au). |
---|
612 | */ |
---|
613 | if (pp == pcurrent) |
---|
614 | return pp; |
---|
615 | else if (retp == NULL || pp == pprevious) |
---|
616 | retp = pp; |
---|
617 | } |
---|
618 | } |
---|
619 | |
---|
620 | return retp; /* Will be NULL if we didn't find a job */ |
---|
621 | } |
---|
622 | |
---|
623 | void |
---|
624 | fg_proc_entry(pp) |
---|
625 | register struct process *pp; |
---|
626 | { |
---|
627 | #ifdef BSDSIGS |
---|
628 | sigmask_t omask; |
---|
629 | #endif |
---|
630 | jmp_buf_t osetexit; |
---|
631 | bool ohaderr; |
---|
632 | Char oGettingInput; |
---|
633 | |
---|
634 | getexit(osetexit); |
---|
635 | |
---|
636 | #ifdef BSDSIGS |
---|
637 | omask = sigblock(sigmask(SIGINT)); |
---|
638 | #else |
---|
639 | (void) sighold(SIGINT); |
---|
640 | #endif |
---|
641 | oGettingInput = GettingInput; |
---|
642 | GettingInput = 0; |
---|
643 | |
---|
644 | ohaderr = haderr; /* we need to ignore setting of haderr due to |
---|
645 | * process getting stopped by a signal */ |
---|
646 | if (setexit() == 0) { /* come back here after pjwait */ |
---|
647 | pendjob(); |
---|
648 | (void) alarm(0); /* No autologout */ |
---|
649 | if (!pstart(pp, 1)) { |
---|
650 | pp->p_procid = 0; |
---|
651 | stderror(ERR_BADJOB, pp->p_command, strerror(errno)); |
---|
652 | } |
---|
653 | pjwait(pp); |
---|
654 | } |
---|
655 | setalarm(1); /* Autologout back on */ |
---|
656 | resexit(osetexit); |
---|
657 | haderr = ohaderr; |
---|
658 | GettingInput = oGettingInput; |
---|
659 | |
---|
660 | #ifdef BSDSIGS |
---|
661 | (void) sigsetmask(omask); |
---|
662 | #else /* !BSDSIGS */ |
---|
663 | (void) sigrelse(SIGINT); |
---|
664 | #endif /* BSDSIGS */ |
---|
665 | |
---|
666 | } |
---|
667 | |
---|
668 | static char * |
---|
669 | xgetpass(prm) |
---|
670 | char *prm; |
---|
671 | { |
---|
672 | static char pass[PASSMAX + 1]; |
---|
673 | int fd, i; |
---|
674 | signalfun_t sigint; |
---|
675 | |
---|
676 | sigint = (signalfun_t) sigset(SIGINT, SIG_IGN); |
---|
677 | (void) Rawmode(); /* Make sure, cause we want echo off */ |
---|
678 | if ((fd = open("/dev/tty", O_RDWR)) == -1) |
---|
679 | fd = SHIN; |
---|
680 | |
---|
681 | xprintf("%s", prm); flush(); |
---|
682 | for (i = 0;;) { |
---|
683 | if (read(fd, &pass[i], 1) < 1 || pass[i] == '\n') |
---|
684 | break; |
---|
685 | if (i < PASSMAX) |
---|
686 | i++; |
---|
687 | } |
---|
688 | |
---|
689 | pass[i] = '\0'; |
---|
690 | |
---|
691 | if (fd != SHIN) |
---|
692 | (void) close(fd); |
---|
693 | (void) sigset(SIGINT, sigint); |
---|
694 | |
---|
695 | return(pass); |
---|
696 | } |
---|
697 | |
---|
698 | /* |
---|
699 | * Ask the user for his login password to continue working |
---|
700 | * On systems that have a shadow password, this will only |
---|
701 | * work for root, but what can we do? |
---|
702 | * |
---|
703 | * If we fail to get the password, then we log the user out |
---|
704 | * immediately |
---|
705 | */ |
---|
706 | /*ARGSUSED*/ |
---|
707 | static void |
---|
708 | auto_lock(n) |
---|
709 | int n; |
---|
710 | { |
---|
711 | #ifndef NO_CRYPT |
---|
712 | |
---|
713 | int i; |
---|
714 | char *srpp = NULL; |
---|
715 | struct passwd *pw; |
---|
716 | #ifdef POSIX |
---|
717 | extern char *crypt __P((const char *, const char *)); |
---|
718 | #else |
---|
719 | extern char *crypt __P(()); |
---|
720 | #endif |
---|
721 | |
---|
722 | #undef XCRYPT |
---|
723 | |
---|
724 | #if defined(PW_AUTH) && !defined(XCRYPT) |
---|
725 | |
---|
726 | struct authorization *apw; |
---|
727 | extern char *crypt16 __P((const char *, const char *)); |
---|
728 | |
---|
729 | # define XCRYPT(a, b) crypt16(a, b) |
---|
730 | |
---|
731 | if ((pw = getpwuid(euid)) != NULL && /* effective user passwd */ |
---|
732 | (apw = getauthuid(euid)) != NULL) /* enhanced ultrix passwd */ |
---|
733 | srpp = apw->a_password; |
---|
734 | |
---|
735 | #endif /* PW_AUTH && !XCRYPT */ |
---|
736 | |
---|
737 | #if defined(PW_SHADOW) && !defined(XCRYPT) |
---|
738 | |
---|
739 | struct spwd *spw; |
---|
740 | |
---|
741 | # define XCRYPT(a, b) crypt(a, b) |
---|
742 | |
---|
743 | if ((pw = getpwuid(euid)) != NULL && /* effective user passwd */ |
---|
744 | (spw = getspnam(pw->pw_name)) != NULL) /* shadowed passwd */ |
---|
745 | srpp = spw->sp_pwdp; |
---|
746 | |
---|
747 | #endif /* PW_SHADOW && !XCRYPT */ |
---|
748 | |
---|
749 | #ifndef XCRYPT |
---|
750 | |
---|
751 | #define XCRYPT(a, b) crypt(a, b) |
---|
752 | |
---|
753 | if ((pw = getpwuid(euid)) != NULL) /* effective user passwd */ |
---|
754 | srpp = pw->pw_passwd; |
---|
755 | |
---|
756 | #endif /* !XCRYPT */ |
---|
757 | |
---|
758 | if (srpp == NULL) { |
---|
759 | auto_logout(0); |
---|
760 | /*NOTREACHED*/ |
---|
761 | return; |
---|
762 | } |
---|
763 | |
---|
764 | setalarm(0); /* Not for locking any more */ |
---|
765 | #ifdef BSDSIGS |
---|
766 | (void) sigsetmask(sigblock(0) & ~(sigmask(SIGALRM))); |
---|
767 | #else /* !BSDSIGS */ |
---|
768 | (void) sigrelse(SIGALRM); |
---|
769 | #endif /* BSDSIGS */ |
---|
770 | xputchar('\n'); |
---|
771 | for (i = 0; i < 5; i++) { |
---|
772 | const char *crpp; |
---|
773 | char *pp; |
---|
774 | #ifdef AFS |
---|
775 | char *afsname; |
---|
776 | Char *safs; |
---|
777 | |
---|
778 | if ((safs = varval(STRafsuser)) != STRNULL) |
---|
779 | afsname = short2str(safs); |
---|
780 | else |
---|
781 | if ((afsname = getenv("AFSUSER")) == NULL) |
---|
782 | afsname = pw->pw_name; |
---|
783 | #endif |
---|
784 | pp = xgetpass("Password:"); |
---|
785 | |
---|
786 | crpp = XCRYPT(pp, srpp); |
---|
787 | if ((strcmp(crpp, srpp) == 0) |
---|
788 | #ifdef AFS |
---|
789 | || (ka_UserAuthenticateGeneral(KA_USERAUTH_VERSION, |
---|
790 | afsname, /* name */ |
---|
791 | NULL, /* instance */ |
---|
792 | NULL, /* realm */ |
---|
793 | pp, /* password */ |
---|
794 | 0, /* lifetime */ |
---|
795 | 0, 0, /* spare */ |
---|
796 | NULL) /* reason */ |
---|
797 | == 0) |
---|
798 | #endif /* AFS */ |
---|
799 | ) { |
---|
800 | (void) memset(pp, 0, PASSMAX); |
---|
801 | if (GettingInput && !just_signaled) { |
---|
802 | (void) Rawmode(); |
---|
803 | ClearLines(); |
---|
804 | ClearDisp(); |
---|
805 | Refresh(); |
---|
806 | } |
---|
807 | just_signaled = 0; |
---|
808 | return; |
---|
809 | } |
---|
810 | xprintf(CGETS(22, 2, "\nIncorrect passwd for %s\n"), pw->pw_name); |
---|
811 | } |
---|
812 | #endif /* NO_CRYPT */ |
---|
813 | auto_logout(0); |
---|
814 | USE(n); |
---|
815 | } |
---|
816 | |
---|
817 | |
---|
818 | static void |
---|
819 | auto_logout(n) |
---|
820 | int n; |
---|
821 | { |
---|
822 | USE(n); |
---|
823 | xprintf("auto-logout\n"); |
---|
824 | /* Don't leave the tty in raw mode */ |
---|
825 | if (editing) |
---|
826 | (void) Cookedmode(); |
---|
827 | (void) close(SHIN); |
---|
828 | set(STRlogout, Strsave(STRautomatic), VAR_READWRITE); |
---|
829 | child = 1; |
---|
830 | #ifdef TESLA |
---|
831 | do_logout = 1; |
---|
832 | #endif /* TESLA */ |
---|
833 | GettingInput = FALSE; /* make flush() work to write hist files. Huber*/ |
---|
834 | goodbye(NULL, NULL); |
---|
835 | } |
---|
836 | |
---|
837 | sigret_t |
---|
838 | /*ARGSUSED*/ |
---|
839 | alrmcatch(snum) |
---|
840 | int snum; |
---|
841 | { |
---|
842 | #ifdef UNRELSIGS |
---|
843 | if (snum) |
---|
844 | (void) sigset(SIGALRM, alrmcatch); |
---|
845 | #endif /* UNRELSIGS */ |
---|
846 | |
---|
847 | (*alm_fun)(0); |
---|
848 | |
---|
849 | setalarm(1); |
---|
850 | #ifndef SIGVOID |
---|
851 | return (snum); |
---|
852 | #endif /* !SIGVOID */ |
---|
853 | } |
---|
854 | |
---|
855 | /* |
---|
856 | * Karl Kleinpaste, 21oct1983. |
---|
857 | * Added precmd(), which checks for the alias |
---|
858 | * precmd in aliases. If it's there, the alias |
---|
859 | * is executed as a command. This is done |
---|
860 | * after mailchk() and just before print- |
---|
861 | * ing the prompt. Useful for things like printing |
---|
862 | * one's current directory just before each command. |
---|
863 | */ |
---|
864 | void |
---|
865 | precmd() |
---|
866 | { |
---|
867 | #ifdef BSDSIGS |
---|
868 | sigmask_t omask; |
---|
869 | |
---|
870 | omask = sigblock(sigmask(SIGINT)); |
---|
871 | #else /* !BSDSIGS */ |
---|
872 | (void) sighold(SIGINT); |
---|
873 | #endif /* BSDSIGS */ |
---|
874 | if (precmd_active) { /* an error must have been caught */ |
---|
875 | aliasrun(2, STRunalias, STRprecmd); |
---|
876 | xprintf(CGETS(22, 3, "Faulty alias 'precmd' removed.\n")); |
---|
877 | goto leave; |
---|
878 | } |
---|
879 | precmd_active = 1; |
---|
880 | if (!whyles && adrof1(STRprecmd, &aliases)) |
---|
881 | aliasrun(1, STRprecmd, NULL); |
---|
882 | leave: |
---|
883 | precmd_active = 0; |
---|
884 | #ifdef BSDSIGS |
---|
885 | (void) sigsetmask(omask); |
---|
886 | #else /* !BSDSIGS */ |
---|
887 | (void) sigrelse(SIGINT); |
---|
888 | #endif /* BSDSIGS */ |
---|
889 | } |
---|
890 | |
---|
891 | /* |
---|
892 | * Paul Placeway 11/24/87 Added cwd_cmd by hacking precmd() into |
---|
893 | * submission... Run every time $cwd is set (after it is set). Useful |
---|
894 | * for putting your machine and cwd (or anything else) in an xterm title |
---|
895 | * space. |
---|
896 | */ |
---|
897 | void |
---|
898 | cwd_cmd() |
---|
899 | { |
---|
900 | #ifdef BSDSIGS |
---|
901 | sigmask_t omask; |
---|
902 | |
---|
903 | omask = sigblock(sigmask(SIGINT)); |
---|
904 | #else /* !BSDSIGS */ |
---|
905 | (void) sighold(SIGINT); |
---|
906 | #endif /* BSDSIGS */ |
---|
907 | if (cwdcmd_active) { /* an error must have been caught */ |
---|
908 | aliasrun(2, STRunalias, STRcwdcmd); |
---|
909 | xprintf(CGETS(22, 4, "Faulty alias 'cwdcmd' removed.\n")); |
---|
910 | goto leave; |
---|
911 | } |
---|
912 | cwdcmd_active = 1; |
---|
913 | if (!whyles && adrof1(STRcwdcmd, &aliases)) |
---|
914 | aliasrun(1, STRcwdcmd, NULL); |
---|
915 | leave: |
---|
916 | cwdcmd_active = 0; |
---|
917 | #ifdef BSDSIGS |
---|
918 | (void) sigsetmask(omask); |
---|
919 | #else /* !BSDSIGS */ |
---|
920 | (void) sigrelse(SIGINT); |
---|
921 | #endif /* BSDSIGS */ |
---|
922 | } |
---|
923 | |
---|
924 | /* |
---|
925 | * Joachim Hoenig 07/16/91 Added beep_cmd, run every time tcsh wishes |
---|
926 | * to beep the terminal bell. Useful for playing nice sounds instead. |
---|
927 | */ |
---|
928 | void |
---|
929 | beep_cmd() |
---|
930 | { |
---|
931 | #ifdef BSDSIGS |
---|
932 | sigmask_t omask; |
---|
933 | |
---|
934 | omask = sigblock(sigmask(SIGINT)); |
---|
935 | #else /* !BSDSIGS */ |
---|
936 | (void) sighold(SIGINT); |
---|
937 | #endif /* BSDSIGS */ |
---|
938 | if (beepcmd_active) { /* an error must have been caught */ |
---|
939 | aliasrun(2, STRunalias, STRbeepcmd); |
---|
940 | xprintf(CGETS(22, 5, "Faulty alias 'beepcmd' removed.\n")); |
---|
941 | } |
---|
942 | else { |
---|
943 | beepcmd_active = 1; |
---|
944 | if (!whyles && adrof1(STRbeepcmd, &aliases)) |
---|
945 | aliasrun(1, STRbeepcmd, NULL); |
---|
946 | } |
---|
947 | beepcmd_active = 0; |
---|
948 | #ifdef BSDSIGS |
---|
949 | (void) sigsetmask(omask); |
---|
950 | #else /* !BSDSIGS */ |
---|
951 | (void) sigrelse(SIGINT); |
---|
952 | #endif /* BSDSIGS */ |
---|
953 | } |
---|
954 | |
---|
955 | |
---|
956 | /* |
---|
957 | * Karl Kleinpaste, 18 Jan 1984. |
---|
958 | * Added period_cmd(), which executes the alias "periodic" every |
---|
959 | * $tperiod minutes. Useful for occasional checking of msgs and such. |
---|
960 | */ |
---|
961 | void |
---|
962 | period_cmd() |
---|
963 | { |
---|
964 | register Char *vp; |
---|
965 | time_t t, interval; |
---|
966 | #ifdef BSDSIGS |
---|
967 | sigmask_t omask; |
---|
968 | |
---|
969 | omask = sigblock(sigmask(SIGINT)); |
---|
970 | #else /* !BSDSIGS */ |
---|
971 | (void) sighold(SIGINT); |
---|
972 | #endif /* BSDSIGS */ |
---|
973 | if (periodic_active) { /* an error must have been caught */ |
---|
974 | aliasrun(2, STRunalias, STRperiodic); |
---|
975 | xprintf(CGETS(22, 6, "Faulty alias 'periodic' removed.\n")); |
---|
976 | goto leave; |
---|
977 | } |
---|
978 | periodic_active = 1; |
---|
979 | if (!whyles && adrof1(STRperiodic, &aliases)) { |
---|
980 | vp = varval(STRtperiod); |
---|
981 | if (vp == STRNULL) |
---|
982 | return; |
---|
983 | interval = getn(vp); |
---|
984 | (void) time(&t); |
---|
985 | if (t - t_period >= interval * 60) { |
---|
986 | t_period = t; |
---|
987 | aliasrun(1, STRperiodic, NULL); |
---|
988 | } |
---|
989 | } |
---|
990 | leave: |
---|
991 | periodic_active = 0; |
---|
992 | #ifdef BSDSIGS |
---|
993 | (void) sigsetmask(omask); |
---|
994 | #else /* !BSDSIGS */ |
---|
995 | (void) sigrelse(SIGINT); |
---|
996 | #endif /* BSDSIGS */ |
---|
997 | } |
---|
998 | |
---|
999 | /* |
---|
1000 | * Karl Kleinpaste, 21oct1983. |
---|
1001 | * Set up a one-word alias command, for use for special things. |
---|
1002 | * This code is based on the mainline of process(). |
---|
1003 | */ |
---|
1004 | void |
---|
1005 | aliasrun(cnt, s1, s2) |
---|
1006 | int cnt; |
---|
1007 | Char *s1, *s2; |
---|
1008 | { |
---|
1009 | struct wordent w, *new1, *new2; /* for holding alias name */ |
---|
1010 | struct command *t = NULL; |
---|
1011 | jmp_buf_t osetexit; |
---|
1012 | int status; |
---|
1013 | |
---|
1014 | getexit(osetexit); |
---|
1015 | if (seterr) { |
---|
1016 | xfree((ptr_t) seterr); |
---|
1017 | seterr = NULL; /* don't repeatedly print err msg. */ |
---|
1018 | } |
---|
1019 | w.word = STRNULL; |
---|
1020 | new1 = (struct wordent *) xcalloc(1, sizeof w); |
---|
1021 | new1->word = Strsave(s1); |
---|
1022 | if (cnt == 1) { |
---|
1023 | /* build a lex list with one word. */ |
---|
1024 | w.next = w.prev = new1; |
---|
1025 | new1->next = new1->prev = &w; |
---|
1026 | } |
---|
1027 | else { |
---|
1028 | /* build a lex list with two words. */ |
---|
1029 | new2 = (struct wordent *) xcalloc(1, sizeof w); |
---|
1030 | new2->word = Strsave(s2); |
---|
1031 | w.next = new2->prev = new1; |
---|
1032 | new1->next = w.prev = new2; |
---|
1033 | new1->prev = new2->next = &w; |
---|
1034 | } |
---|
1035 | |
---|
1036 | /* Save the old status */ |
---|
1037 | status = getn(varval(STRstatus)); |
---|
1038 | |
---|
1039 | /* expand aliases like process() does. */ |
---|
1040 | alias(&w); |
---|
1041 | /* build a syntax tree for the command. */ |
---|
1042 | t = syntax(w.next, &w, 0); |
---|
1043 | if (seterr) |
---|
1044 | stderror(ERR_OLD); |
---|
1045 | |
---|
1046 | psavejob(); |
---|
1047 | |
---|
1048 | |
---|
1049 | /* catch any errors here */ |
---|
1050 | if (setexit() == 0) |
---|
1051 | /* execute the parse tree. */ |
---|
1052 | /* |
---|
1053 | * From: Michael Schroeder <mlschroe@immd4.informatik.uni-erlangen.de> |
---|
1054 | * was execute(t, tpgrp); |
---|
1055 | */ |
---|
1056 | execute(t, tpgrp > 0 ? tpgrp : -1, NULL, NULL); |
---|
1057 | /* done. free the lex list and parse tree. */ |
---|
1058 | freelex(&w), freesyn(t); |
---|
1059 | if (haderr) { |
---|
1060 | haderr = 0; |
---|
1061 | /* |
---|
1062 | * Either precmd, or cwdcmd, or periodic had an error. Call it again so |
---|
1063 | * that it is removed |
---|
1064 | */ |
---|
1065 | if (precmd_active) |
---|
1066 | precmd(); |
---|
1067 | #ifdef notdef |
---|
1068 | /* |
---|
1069 | * XXX: On the other hand, just interrupting them causes an error too. |
---|
1070 | * So if we hit ^C in the middle of cwdcmd or periodic the alias gets |
---|
1071 | * removed. We don't want that. Note that we want to remove precmd |
---|
1072 | * though, cause that could lead into an infinite loop. This should be |
---|
1073 | * fixed correctly, but then haderr should give us the whole exit |
---|
1074 | * status not just true or false. |
---|
1075 | */ |
---|
1076 | else if (cwdcmd_active) |
---|
1077 | cwd_cmd(); |
---|
1078 | else if (beepcmd_active) |
---|
1079 | beep_cmd(); |
---|
1080 | else if (periodic_active) |
---|
1081 | period_cmd(); |
---|
1082 | #endif /* notdef */ |
---|
1083 | } |
---|
1084 | /* reset the error catcher to the old place */ |
---|
1085 | resexit(osetexit); |
---|
1086 | prestjob(); |
---|
1087 | pendjob(); |
---|
1088 | /* Restore status */ |
---|
1089 | set(STRstatus, putn(status), VAR_READWRITE); |
---|
1090 | } |
---|
1091 | |
---|
1092 | void |
---|
1093 | setalarm(lck) |
---|
1094 | int lck; |
---|
1095 | { |
---|
1096 | struct varent *vp; |
---|
1097 | Char *cp; |
---|
1098 | unsigned alrm_time = 0, logout_time, lock_time; |
---|
1099 | time_t cl, nl, sched_dif; |
---|
1100 | |
---|
1101 | if ((vp = adrof(STRautologout)) != NULL) { |
---|
1102 | if ((cp = vp->vec[0]) != 0) { |
---|
1103 | if ((logout_time = (unsigned) atoi(short2str(cp)) * 60) > 0) { |
---|
1104 | alrm_time = logout_time; |
---|
1105 | alm_fun = auto_logout; |
---|
1106 | } |
---|
1107 | } |
---|
1108 | if ((cp = vp->vec[1]) != 0) { |
---|
1109 | if ((lock_time = (unsigned) atoi(short2str(cp)) * 60) > 0) { |
---|
1110 | if (lck) { |
---|
1111 | if (alrm_time == 0 || lock_time < alrm_time) { |
---|
1112 | alrm_time = lock_time; |
---|
1113 | alm_fun = auto_lock; |
---|
1114 | } |
---|
1115 | } |
---|
1116 | else /* lock_time always < alrm_time */ |
---|
1117 | if (alrm_time) |
---|
1118 | alrm_time -= lock_time; |
---|
1119 | } |
---|
1120 | } |
---|
1121 | } |
---|
1122 | if ((nl = sched_next()) != -1) { |
---|
1123 | (void) time(&cl); |
---|
1124 | sched_dif = nl > cl ? nl - cl : 0; |
---|
1125 | if ((alrm_time == 0) || ((unsigned) sched_dif < alrm_time)) { |
---|
1126 | alrm_time = ((unsigned) sched_dif) + 1; |
---|
1127 | alm_fun = sched_run; |
---|
1128 | } |
---|
1129 | } |
---|
1130 | (void) alarm(alrm_time); /* Autologout ON */ |
---|
1131 | } |
---|
1132 | |
---|
1133 | #undef RMDEBUG /* For now... */ |
---|
1134 | |
---|
1135 | void |
---|
1136 | rmstar(cp) |
---|
1137 | struct wordent *cp; |
---|
1138 | { |
---|
1139 | struct wordent *we, *args; |
---|
1140 | register struct wordent *tmp, *del; |
---|
1141 | |
---|
1142 | #ifdef RMDEBUG |
---|
1143 | static Char STRrmdebug[] = {'r', 'm', 'd', 'e', 'b', 'u', 'g', '\0'}; |
---|
1144 | Char *tag; |
---|
1145 | #endif /* RMDEBUG */ |
---|
1146 | Char *charac; |
---|
1147 | char c; |
---|
1148 | int ask, doit, star = 0, silent = 0; |
---|
1149 | |
---|
1150 | if (!adrof(STRrmstar)) |
---|
1151 | return; |
---|
1152 | #ifdef RMDEBUG |
---|
1153 | tag = varval(STRrmdebug); |
---|
1154 | #endif /* RMDEBUG */ |
---|
1155 | we = cp->next; |
---|
1156 | while (*we->word == ';' && we != cp) |
---|
1157 | we = we->next; |
---|
1158 | while (we != cp) { |
---|
1159 | #ifdef RMDEBUG |
---|
1160 | if (*tag) |
---|
1161 | xprintf(CGETS(22, 7, "parsing command line\n")); |
---|
1162 | #endif /* RMDEBUG */ |
---|
1163 | if (!Strcmp(we->word, STRrm)) { |
---|
1164 | args = we->next; |
---|
1165 | ask = (*args->word != '-'); |
---|
1166 | while (*args->word == '-' && !silent) { /* check options */ |
---|
1167 | for (charac = (args->word + 1); *charac && !silent; charac++) |
---|
1168 | silent = (*charac == 'i' || *charac == 'f'); |
---|
1169 | args = args->next; |
---|
1170 | } |
---|
1171 | ask = (ask || (!ask && !silent)); |
---|
1172 | if (ask) { |
---|
1173 | for (; !star && *args->word != ';' |
---|
1174 | && args != cp; args = args->next) |
---|
1175 | if (!Strcmp(args->word, STRstar)) |
---|
1176 | star = 1; |
---|
1177 | if (ask && star) { |
---|
1178 | xprintf(CGETS(22, 8, |
---|
1179 | "Do you really want to delete all files? [n/y] ")); |
---|
1180 | flush(); |
---|
1181 | (void) force_read(SHIN, &c, 1); |
---|
1182 | /* |
---|
1183 | * Perhaps we should use the yesexpr from the |
---|
1184 | * actual locale |
---|
1185 | */ |
---|
1186 | doit = (strchr(CGETS(22, 14, "Yy"), c) != NULL); |
---|
1187 | while (c != '\n' && force_read(SHIN, &c, 1) == 1) |
---|
1188 | continue; |
---|
1189 | if (!doit) { |
---|
1190 | /* remove the command instead */ |
---|
1191 | #ifdef RMDEBUG |
---|
1192 | if (*tag) |
---|
1193 | xprintf(CGETS(22, 9, |
---|
1194 | "skipping deletion of files!\n")); |
---|
1195 | #endif /* RMDEBUG */ |
---|
1196 | for (tmp = we; |
---|
1197 | *tmp->word != '\n' && |
---|
1198 | *tmp->word != ';' && tmp != cp;) { |
---|
1199 | tmp->prev->next = tmp->next; |
---|
1200 | tmp->next->prev = tmp->prev; |
---|
1201 | xfree((ptr_t) tmp->word); |
---|
1202 | del = tmp; |
---|
1203 | tmp = tmp->next; |
---|
1204 | xfree((ptr_t) del); |
---|
1205 | } |
---|
1206 | if (*tmp->word == ';') { |
---|
1207 | tmp->prev->next = tmp->next; |
---|
1208 | tmp->next->prev = tmp->prev; |
---|
1209 | xfree((ptr_t) tmp->word); |
---|
1210 | del = tmp; |
---|
1211 | xfree((ptr_t) del); |
---|
1212 | } |
---|
1213 | } |
---|
1214 | } |
---|
1215 | } |
---|
1216 | } |
---|
1217 | for (we = we->next; |
---|
1218 | *we->word != ';' && we != cp; |
---|
1219 | we = we->next) |
---|
1220 | continue; |
---|
1221 | if (*we->word == ';') |
---|
1222 | we = we->next; |
---|
1223 | } |
---|
1224 | #ifdef RMDEBUG |
---|
1225 | if (*tag) { |
---|
1226 | xprintf(CGETS(22, 10, "command line now is:\n")); |
---|
1227 | for (we = cp->next; we != cp; we = we->next) |
---|
1228 | xprintf("%S ", we->word); |
---|
1229 | } |
---|
1230 | #endif /* RMDEBUG */ |
---|
1231 | return; |
---|
1232 | } |
---|
1233 | |
---|
1234 | #ifdef BSDJOBS |
---|
1235 | /* Check if command is in continue list |
---|
1236 | and do a "aliasing" if it exists as a job in background */ |
---|
1237 | |
---|
1238 | #undef CNDEBUG /* For now */ |
---|
1239 | void |
---|
1240 | continue_jobs(cp) |
---|
1241 | struct wordent *cp; |
---|
1242 | { |
---|
1243 | struct wordent *we; |
---|
1244 | register struct process *pp, *np; |
---|
1245 | Char *cmd, *continue_list, *continue_args_list; |
---|
1246 | |
---|
1247 | #ifdef CNDEBUG |
---|
1248 | Char *tag; |
---|
1249 | static Char STRcndebug[] = |
---|
1250 | {'c', 'n', 'd', 'e', 'b', 'u', 'g', '\0'}; |
---|
1251 | #endif /* CNDEBUG */ |
---|
1252 | bool in_cont_list, in_cont_arg_list; |
---|
1253 | |
---|
1254 | |
---|
1255 | #ifdef CNDEBUG |
---|
1256 | tag = varval(STRcndebug); |
---|
1257 | #endif /* CNDEBUG */ |
---|
1258 | continue_list = varval(STRcontinue); |
---|
1259 | continue_args_list = varval(STRcontinue_args); |
---|
1260 | if (*continue_list == '\0' && *continue_args_list == '\0') |
---|
1261 | return; |
---|
1262 | |
---|
1263 | we = cp->next; |
---|
1264 | while (*we->word == ';' && we != cp) |
---|
1265 | we = we->next; |
---|
1266 | while (we != cp) { |
---|
1267 | #ifdef CNDEBUG |
---|
1268 | if (*tag) |
---|
1269 | xprintf(CGETS(22, 11, "parsing command line\n")); |
---|
1270 | #endif /* CNDEBUG */ |
---|
1271 | cmd = we->word; |
---|
1272 | in_cont_list = inlist(continue_list, cmd); |
---|
1273 | in_cont_arg_list = inlist(continue_args_list, cmd); |
---|
1274 | if (in_cont_list || in_cont_arg_list) { |
---|
1275 | #ifdef CNDEBUG |
---|
1276 | if (*tag) |
---|
1277 | xprintf(CGETS(22, 12, "in one of the lists\n")); |
---|
1278 | #endif /* CNDEBUG */ |
---|
1279 | np = NULL; |
---|
1280 | for (pp = proclist.p_next; pp; pp = pp->p_next) { |
---|
1281 | if (prefix(cmd, pp->p_command)) { |
---|
1282 | if (pp->p_index) { |
---|
1283 | np = pp; |
---|
1284 | break; |
---|
1285 | } |
---|
1286 | } |
---|
1287 | } |
---|
1288 | if (np) { |
---|
1289 | insert(we, in_cont_arg_list); |
---|
1290 | } |
---|
1291 | } |
---|
1292 | for (we = we->next; |
---|
1293 | *we->word != ';' && we != cp; |
---|
1294 | we = we->next) |
---|
1295 | continue; |
---|
1296 | if (*we->word == ';') |
---|
1297 | we = we->next; |
---|
1298 | } |
---|
1299 | #ifdef CNDEBUG |
---|
1300 | if (*tag) { |
---|
1301 | xprintf(CGETS(22, 13, "command line now is:\n")); |
---|
1302 | for (we = cp->next; we != cp; we = we->next) |
---|
1303 | xprintf("%S ", we->word); |
---|
1304 | } |
---|
1305 | #endif /* CNDEBUG */ |
---|
1306 | return; |
---|
1307 | } |
---|
1308 | |
---|
1309 | /* The actual "aliasing" of for backgrounds() is done here |
---|
1310 | with the aid of insert_we(). */ |
---|
1311 | static void |
---|
1312 | insert(pl, file_args) |
---|
1313 | struct wordent *pl; |
---|
1314 | bool file_args; |
---|
1315 | { |
---|
1316 | struct wordent *now, *last; |
---|
1317 | Char *cmd, *bcmd, *cp1, *cp2; |
---|
1318 | int cmd_len; |
---|
1319 | Char *pause = STRunderpause; |
---|
1320 | int p_len = (int) Strlen(pause); |
---|
1321 | |
---|
1322 | cmd_len = (int) Strlen(pl->word); |
---|
1323 | cmd = (Char *) xcalloc(1, (size_t) ((cmd_len + 1) * sizeof(Char))); |
---|
1324 | (void) Strcpy(cmd, pl->word); |
---|
1325 | /* Do insertions at beginning, first replace command word */ |
---|
1326 | |
---|
1327 | if (file_args) { |
---|
1328 | now = pl; |
---|
1329 | xfree((ptr_t) now->word); |
---|
1330 | now->word = (Char *) xcalloc(1, (size_t) (5 * sizeof(Char))); |
---|
1331 | (void) Strcpy(now->word, STRecho); |
---|
1332 | |
---|
1333 | now = (struct wordent *) xcalloc(1, (size_t) sizeof(struct wordent)); |
---|
1334 | now->word = (Char *) xcalloc(1, (size_t) (6 * sizeof(Char))); |
---|
1335 | (void) Strcpy(now->word, STRbackqpwd); |
---|
1336 | insert_we(now, pl); |
---|
1337 | |
---|
1338 | for (last = now; *last->word != '\n' && *last->word != ';'; |
---|
1339 | last = last->next) |
---|
1340 | continue; |
---|
1341 | |
---|
1342 | now = (struct wordent *) xcalloc(1, (size_t) sizeof(struct wordent)); |
---|
1343 | now->word = (Char *) xcalloc(1, (size_t) (2 * sizeof(Char))); |
---|
1344 | (void) Strcpy(now->word, STRgt); |
---|
1345 | insert_we(now, last->prev); |
---|
1346 | |
---|
1347 | now = (struct wordent *) xcalloc(1, (size_t) sizeof(struct wordent)); |
---|
1348 | now->word = (Char *) xcalloc(1, (size_t) (2 * sizeof(Char))); |
---|
1349 | (void) Strcpy(now->word, STRbang); |
---|
1350 | insert_we(now, last->prev); |
---|
1351 | |
---|
1352 | now = (struct wordent *) xcalloc(1, (size_t) sizeof(struct wordent)); |
---|
1353 | now->word = (Char *) xcalloc(1, (size_t) cmd_len + p_len + 4); |
---|
1354 | cp1 = now->word; |
---|
1355 | cp2 = cmd; |
---|
1356 | *cp1++ = '~'; |
---|
1357 | *cp1++ = '/'; |
---|
1358 | *cp1++ = '.'; |
---|
1359 | while ((*cp1++ = *cp2++) != '\0') |
---|
1360 | continue; |
---|
1361 | cp1--; |
---|
1362 | cp2 = pause; |
---|
1363 | while ((*cp1++ = *cp2++) != '\0') |
---|
1364 | continue; |
---|
1365 | insert_we(now, last->prev); |
---|
1366 | |
---|
1367 | now = (struct wordent *) xcalloc(1, (size_t) sizeof(struct wordent)); |
---|
1368 | now->word = (Char *) xcalloc(1, (size_t) (2 * sizeof(Char))); |
---|
1369 | (void) Strcpy(now->word, STRsemi); |
---|
1370 | insert_we(now, last->prev); |
---|
1371 | bcmd = (Char *) xcalloc(1, (size_t) ((cmd_len + 2) * sizeof(Char))); |
---|
1372 | cp1 = bcmd; |
---|
1373 | cp2 = cmd; |
---|
1374 | *cp1++ = '%'; |
---|
1375 | while ((*cp1++ = *cp2++) != '\0') |
---|
1376 | continue; |
---|
1377 | now = (struct wordent *) xcalloc(1, (size_t) (sizeof(struct wordent))); |
---|
1378 | now->word = bcmd; |
---|
1379 | insert_we(now, last->prev); |
---|
1380 | } |
---|
1381 | else { |
---|
1382 | struct wordent *del; |
---|
1383 | |
---|
1384 | now = pl; |
---|
1385 | xfree((ptr_t) now->word); |
---|
1386 | now->word = (Char *) xcalloc(1, |
---|
1387 | (size_t) ((cmd_len + 2) * sizeof(Char))); |
---|
1388 | cp1 = now->word; |
---|
1389 | cp2 = cmd; |
---|
1390 | *cp1++ = '%'; |
---|
1391 | while ((*cp1++ = *cp2++) != '\0') |
---|
1392 | continue; |
---|
1393 | for (now = now->next; |
---|
1394 | *now->word != '\n' && *now->word != ';' && now != pl;) { |
---|
1395 | now->prev->next = now->next; |
---|
1396 | now->next->prev = now->prev; |
---|
1397 | xfree((ptr_t) now->word); |
---|
1398 | del = now; |
---|
1399 | now = now->next; |
---|
1400 | xfree((ptr_t) del); |
---|
1401 | } |
---|
1402 | } |
---|
1403 | } |
---|
1404 | |
---|
1405 | static void |
---|
1406 | insert_we(new, where) |
---|
1407 | struct wordent *new, *where; |
---|
1408 | { |
---|
1409 | |
---|
1410 | new->prev = where; |
---|
1411 | new->next = where->next; |
---|
1412 | where->next = new; |
---|
1413 | new->next->prev = new; |
---|
1414 | } |
---|
1415 | |
---|
1416 | static int |
---|
1417 | inlist(list, name) |
---|
1418 | Char *list, *name; |
---|
1419 | { |
---|
1420 | register Char *l, *n; |
---|
1421 | |
---|
1422 | l = list; |
---|
1423 | n = name; |
---|
1424 | |
---|
1425 | while (*l && *n) { |
---|
1426 | if (*l == *n) { |
---|
1427 | l++; |
---|
1428 | n++; |
---|
1429 | if (*n == '\0' && (*l == ' ' || *l == '\0')) |
---|
1430 | return (1); |
---|
1431 | else |
---|
1432 | continue; |
---|
1433 | } |
---|
1434 | else { |
---|
1435 | while (*l && *l != ' ') |
---|
1436 | l++; /* skip to blank */ |
---|
1437 | while (*l && *l == ' ') |
---|
1438 | l++; /* and find first nonblank character */ |
---|
1439 | n = name; |
---|
1440 | } |
---|
1441 | } |
---|
1442 | return (0); |
---|
1443 | } |
---|
1444 | |
---|
1445 | #endif /* BSDJOBS */ |
---|
1446 | |
---|
1447 | |
---|
1448 | /* |
---|
1449 | * Implement a small cache for tilde names. This is used primarily |
---|
1450 | * to expand tilde names to directories, but also |
---|
1451 | * we can find users from their home directories for the tilde |
---|
1452 | * prompt, on machines where yp lookup is slow this can be a big win... |
---|
1453 | * As with any cache this can run out of sync, rehash can sync it again. |
---|
1454 | */ |
---|
1455 | static struct tildecache { |
---|
1456 | Char *user; |
---|
1457 | Char *home; |
---|
1458 | int hlen; |
---|
1459 | } *tcache = NULL; |
---|
1460 | |
---|
1461 | #define TILINCR 10 |
---|
1462 | int tlength = 0; |
---|
1463 | static int tsize = TILINCR; |
---|
1464 | |
---|
1465 | static int |
---|
1466 | tildecompare(p1, p2) |
---|
1467 | struct tildecache *p1, *p2; |
---|
1468 | { |
---|
1469 | return Strcmp(p1->user, p2->user); |
---|
1470 | } |
---|
1471 | |
---|
1472 | static Char * |
---|
1473 | gethomedir(us) |
---|
1474 | Char *us; |
---|
1475 | { |
---|
1476 | register struct passwd *pp; |
---|
1477 | #ifdef HESIOD |
---|
1478 | char **res, **res1, *cp; |
---|
1479 | Char *rp; |
---|
1480 | #endif /* HESIOD */ |
---|
1481 | |
---|
1482 | pp = getpwnam(short2str(us)); |
---|
1483 | #ifdef YPBUGS |
---|
1484 | fix_yp_bugs(); |
---|
1485 | #endif /* YPBUGS */ |
---|
1486 | if (pp != NULL) |
---|
1487 | return Strsave(str2short(pp->pw_dir)); |
---|
1488 | #ifdef HESIOD |
---|
1489 | res = hes_resolve(short2str(us), "filsys"); |
---|
1490 | rp = 0; |
---|
1491 | if (res != 0) { |
---|
1492 | extern char *strtok(); |
---|
1493 | if ((*res) != 0) { |
---|
1494 | /* |
---|
1495 | * Look at the first token to determine how to interpret |
---|
1496 | * the rest of it. |
---|
1497 | * Yes, strtok is evil (it's not thread-safe), but it's also |
---|
1498 | * easy to use. |
---|
1499 | */ |
---|
1500 | cp = strtok(*res, " "); |
---|
1501 | if (strcmp(cp, "AFS") == 0) { |
---|
1502 | /* next token is AFS pathname.. */ |
---|
1503 | cp = strtok(NULL, " "); |
---|
1504 | if (cp != NULL) |
---|
1505 | rp = Strsave(str2short(cp)); |
---|
1506 | } else if (strcmp(cp, "NFS") == 0) { |
---|
1507 | cp = NULL; |
---|
1508 | if ((strtok(NULL, " ")) && /* skip remote pathname */ |
---|
1509 | (strtok(NULL, " ")) && /* skip host */ |
---|
1510 | (strtok(NULL, " ")) && /* skip mode */ |
---|
1511 | (cp = strtok(NULL, " "))) { |
---|
1512 | rp = Strsave(str2short(cp)); |
---|
1513 | } |
---|
1514 | } |
---|
1515 | } |
---|
1516 | for (res1 = res; *res1; res1++) |
---|
1517 | free(*res1); |
---|
1518 | return rp; |
---|
1519 | } |
---|
1520 | #endif /* HESIOD */ |
---|
1521 | return NULL; |
---|
1522 | } |
---|
1523 | |
---|
1524 | Char * |
---|
1525 | gettilde(us) |
---|
1526 | Char *us; |
---|
1527 | { |
---|
1528 | struct tildecache *bp1, *bp2, *bp; |
---|
1529 | Char *hd; |
---|
1530 | |
---|
1531 | /* Ignore NIS special names */ |
---|
1532 | if (*us == '+' || *us == '-') |
---|
1533 | return NULL; |
---|
1534 | |
---|
1535 | if (tcache == NULL) |
---|
1536 | tcache = (struct tildecache *) xmalloc((size_t) (TILINCR * |
---|
1537 | sizeof(struct tildecache))); |
---|
1538 | /* |
---|
1539 | * Binary search |
---|
1540 | */ |
---|
1541 | for (bp1 = tcache, bp2 = tcache + tlength; bp1 < bp2;) { |
---|
1542 | register int i; |
---|
1543 | |
---|
1544 | bp = bp1 + ((bp2 - bp1) >> 1); |
---|
1545 | if ((i = *us - *bp->user) == 0 && (i = Strcmp(us, bp->user)) == 0) |
---|
1546 | return (bp->home); |
---|
1547 | if (i < 0) |
---|
1548 | bp2 = bp; |
---|
1549 | else |
---|
1550 | bp1 = bp + 1; |
---|
1551 | } |
---|
1552 | /* |
---|
1553 | * Not in the cache, try to get it from the passwd file |
---|
1554 | */ |
---|
1555 | hd = gethomedir(us); |
---|
1556 | if (hd == NULL) |
---|
1557 | return NULL; |
---|
1558 | |
---|
1559 | /* |
---|
1560 | * Update the cache |
---|
1561 | */ |
---|
1562 | tcache[tlength].user = Strsave(us); |
---|
1563 | tcache[tlength].home = hd; |
---|
1564 | tcache[tlength++].hlen = (int) Strlen(hd); |
---|
1565 | |
---|
1566 | qsort((ptr_t) tcache, (size_t) tlength, sizeof(struct tildecache), |
---|
1567 | (int (*) __P((const void *, const void *))) tildecompare); |
---|
1568 | |
---|
1569 | if (tlength == tsize) { |
---|
1570 | tsize += TILINCR; |
---|
1571 | tcache = (struct tildecache *) xrealloc((ptr_t) tcache, |
---|
1572 | (size_t) (tsize * |
---|
1573 | sizeof(struct tildecache))); |
---|
1574 | } |
---|
1575 | return (hd); |
---|
1576 | } |
---|
1577 | |
---|
1578 | /* |
---|
1579 | * Return the username if the directory path passed contains a |
---|
1580 | * user's home directory in the tilde cache, otherwise return NULL |
---|
1581 | * hm points to the place where the path became different. |
---|
1582 | * Special case: Our own home directory. |
---|
1583 | * If we are passed a null pointer, then we flush the cache. |
---|
1584 | */ |
---|
1585 | Char * |
---|
1586 | getusername(hm) |
---|
1587 | Char **hm; |
---|
1588 | { |
---|
1589 | Char *h, *p; |
---|
1590 | int i, j; |
---|
1591 | |
---|
1592 | if (hm == NULL) { |
---|
1593 | for (i = 0; i < tlength; i++) { |
---|
1594 | xfree((ptr_t) tcache[i].home); |
---|
1595 | xfree((ptr_t) tcache[i].user); |
---|
1596 | } |
---|
1597 | xfree((ptr_t) tcache); |
---|
1598 | tlength = 0; |
---|
1599 | tsize = TILINCR; |
---|
1600 | tcache = NULL; |
---|
1601 | return NULL; |
---|
1602 | } |
---|
1603 | if (((h = varval(STRhome)) != STRNULL) && |
---|
1604 | (Strncmp(p = *hm, h, (size_t) (j = (int) Strlen(h))) == 0) && |
---|
1605 | (p[j] == '/' || p[j] == '\0')) { |
---|
1606 | *hm = &p[j]; |
---|
1607 | return STRNULL; |
---|
1608 | } |
---|
1609 | for (i = 0; i < tlength; i++) |
---|
1610 | if ((Strncmp(p = *hm, tcache[i].home, (size_t) |
---|
1611 | (j = tcache[i].hlen)) == 0) && (p[j] == '/' || p[j] == '\0')) { |
---|
1612 | *hm = &p[j]; |
---|
1613 | return tcache[i].user; |
---|
1614 | } |
---|
1615 | return NULL; |
---|
1616 | } |
---|
1617 | |
---|
1618 | #ifdef OBSOLETE |
---|
1619 | /* |
---|
1620 | * PWP: read a bunch of aliases out of a file QUICKLY. The format |
---|
1621 | * is almost the same as the result of saying "alias > FILE", except |
---|
1622 | * that saying "aliases > FILE" does not expand non-letters to printable |
---|
1623 | * sequences. |
---|
1624 | */ |
---|
1625 | /*ARGSUSED*/ |
---|
1626 | void |
---|
1627 | doaliases(v, c) |
---|
1628 | Char **v; |
---|
1629 | struct command *c; |
---|
1630 | { |
---|
1631 | jmp_buf_t oldexit; |
---|
1632 | Char **vec, *lp; |
---|
1633 | int fd; |
---|
1634 | Char buf[BUFSIZE], line[BUFSIZE]; |
---|
1635 | char tbuf[BUFSIZE + 1], *tmp; |
---|
1636 | extern bool output_raw; /* PWP: in sh.print.c */ |
---|
1637 | |
---|
1638 | USE(c); |
---|
1639 | v++; |
---|
1640 | if (*v == 0) { |
---|
1641 | output_raw = 1; |
---|
1642 | plist(&aliases, VAR_ALL); |
---|
1643 | output_raw = 0; |
---|
1644 | return; |
---|
1645 | } |
---|
1646 | |
---|
1647 | gflag = 0, tglob(v); |
---|
1648 | if (gflag) { |
---|
1649 | v = globall(v); |
---|
1650 | if (v == 0) |
---|
1651 | stderror(ERR_NAME | ERR_NOMATCH); |
---|
1652 | } |
---|
1653 | else { |
---|
1654 | v = gargv = saveblk(v); |
---|
1655 | trim(v); |
---|
1656 | } |
---|
1657 | |
---|
1658 | if ((fd = open(tmp = short2str(*v), O_RDONLY)) < 0) |
---|
1659 | stderror(ERR_NAME | ERR_SYSTEM, tmp, strerror(errno)); |
---|
1660 | |
---|
1661 | getexit(oldexit); |
---|
1662 | if (setexit() == 0) { |
---|
1663 | for (;;) { |
---|
1664 | Char *p = NULL; |
---|
1665 | int n = 0; |
---|
1666 | lp = line; |
---|
1667 | for (;;) { |
---|
1668 | if (n <= 0) { |
---|
1669 | int i; |
---|
1670 | |
---|
1671 | if ((n = read(fd, tbuf, BUFSIZE)) <= 0) { |
---|
1672 | #ifdef convex |
---|
1673 | stderror(ERR_SYSTEM, progname, strerror(errno)); |
---|
1674 | #endif /* convex */ |
---|
1675 | goto eof; |
---|
1676 | } |
---|
1677 | for (i = 0; i < n; i++) |
---|
1678 | buf[i] = (Char) tbuf[i]; |
---|
1679 | p = buf; |
---|
1680 | } |
---|
1681 | n--; |
---|
1682 | if ((*lp++ = *p++) == '\n') { |
---|
1683 | lp[-1] = '\0'; |
---|
1684 | break; |
---|
1685 | } |
---|
1686 | } |
---|
1687 | for (lp = line; *lp; lp++) { |
---|
1688 | if (isspc(*lp)) { |
---|
1689 | *lp++ = '\0'; |
---|
1690 | while (isspc(*lp)) |
---|
1691 | lp++; |
---|
1692 | vec = (Char **) xmalloc((size_t) |
---|
1693 | (2 * sizeof(Char **))); |
---|
1694 | vec[0] = Strsave(lp); |
---|
1695 | vec[1] = NULL; |
---|
1696 | setq(strip(line), vec, &aliases, VAR_READWRITE); |
---|
1697 | break; |
---|
1698 | } |
---|
1699 | } |
---|
1700 | } |
---|
1701 | } |
---|
1702 | |
---|
1703 | eof: |
---|
1704 | (void) close(fd); |
---|
1705 | tw_cmd_free(); |
---|
1706 | if (gargv) |
---|
1707 | blkfree(gargv), gargv = 0; |
---|
1708 | resexit(oldexit); |
---|
1709 | } |
---|
1710 | #endif /* OBSOLETE */ |
---|
1711 | |
---|
1712 | |
---|
1713 | /* |
---|
1714 | * set the shell-level var to 1 or apply change to it. |
---|
1715 | */ |
---|
1716 | void |
---|
1717 | shlvl(val) |
---|
1718 | int val; |
---|
1719 | { |
---|
1720 | char *cp; |
---|
1721 | |
---|
1722 | if ((cp = getenv("SHLVL")) != NULL) { |
---|
1723 | |
---|
1724 | if (loginsh) |
---|
1725 | val = 1; |
---|
1726 | else |
---|
1727 | val += atoi(cp); |
---|
1728 | |
---|
1729 | if (val <= 0) { |
---|
1730 | if (adrof(STRshlvl) != NULL) |
---|
1731 | unsetv(STRshlvl); |
---|
1732 | Unsetenv(STRKSHLVL); |
---|
1733 | } |
---|
1734 | else { |
---|
1735 | Char buff[BUFSIZE]; |
---|
1736 | |
---|
1737 | Itoa(val, buff); |
---|
1738 | set(STRshlvl, Strsave(buff), VAR_READWRITE); |
---|
1739 | tsetenv(STRKSHLVL, buff); |
---|
1740 | } |
---|
1741 | } |
---|
1742 | else { |
---|
1743 | set(STRshlvl, SAVE("1"), VAR_READWRITE); |
---|
1744 | tsetenv(STRKSHLVL, str2short("1")); |
---|
1745 | } |
---|
1746 | } |
---|
1747 | |
---|
1748 | |
---|
1749 | /* fixio(): |
---|
1750 | * Try to recover from a read error |
---|
1751 | */ |
---|
1752 | int |
---|
1753 | fixio(fd, e) |
---|
1754 | int fd, e; |
---|
1755 | { |
---|
1756 | switch (e) { |
---|
1757 | case -1: /* Make sure that the code is reachable */ |
---|
1758 | |
---|
1759 | #ifdef EWOULDBLOCK |
---|
1760 | case EWOULDBLOCK: |
---|
1761 | # define FDRETRY |
---|
1762 | #endif /* EWOULDBLOCK */ |
---|
1763 | |
---|
1764 | #if defined(POSIX) && defined(EAGAIN) |
---|
1765 | # if !defined(EWOULDBLOCK) || EWOULDBLOCK != EAGAIN |
---|
1766 | case EAGAIN: |
---|
1767 | # define FDRETRY |
---|
1768 | # endif /* !EWOULDBLOCK || EWOULDBLOCK != EAGAIN */ |
---|
1769 | #endif /* POSIX && EAGAIN */ |
---|
1770 | |
---|
1771 | e = 0; |
---|
1772 | #ifdef FDRETRY |
---|
1773 | # ifdef F_SETFL |
---|
1774 | /* |
---|
1775 | * Great! we have on suns 3 flavors and 5 names... |
---|
1776 | * I hope that will cover everything. |
---|
1777 | * I added some more defines... many systems have different defines. |
---|
1778 | * Rather than dealing with getting the right includes, we'll just |
---|
1779 | * cover all the known possibilities here. -- sterling@netcom.com |
---|
1780 | */ |
---|
1781 | # ifndef O_NONBLOCK |
---|
1782 | # define O_NONBLOCK 0 |
---|
1783 | # endif /* O_NONBLOCK */ |
---|
1784 | # ifndef O_NDELAY |
---|
1785 | # define O_NDELAY 0 |
---|
1786 | # endif /* O_NDELAY */ |
---|
1787 | # ifndef FNBIO |
---|
1788 | # define FNBIO 0 |
---|
1789 | # endif /* FNBIO */ |
---|
1790 | # ifndef _FNBIO |
---|
1791 | # define _FNBIO 0 |
---|
1792 | # endif /* _FNBIO */ |
---|
1793 | # ifndef FNONBIO |
---|
1794 | # define FNONBIO 0 |
---|
1795 | # endif /* FNONBIO */ |
---|
1796 | # ifndef FNONBLOCK |
---|
1797 | # define FNONBLOCK 0 |
---|
1798 | # endif /* FNONBLOCK */ |
---|
1799 | # ifndef _FNONBLOCK |
---|
1800 | # define _FNONBLOCK 0 |
---|
1801 | # endif /* _FNONBLOCK */ |
---|
1802 | # ifndef FNDELAY |
---|
1803 | # define FNDELAY 0 |
---|
1804 | # endif /* FNDELAY */ |
---|
1805 | # ifndef _FNDELAY |
---|
1806 | # define _FNDELAY 0 |
---|
1807 | # endif /* _FNDELAY */ |
---|
1808 | # ifndef FNDLEAY /* Some linux versions have this typo */ |
---|
1809 | # define FNDLEAY 0 |
---|
1810 | # endif /* FNDLEAY */ |
---|
1811 | if ((e = fcntl(fd, F_GETFL, 0)) == -1) |
---|
1812 | return -1; |
---|
1813 | |
---|
1814 | e &= ~(O_NDELAY|O_NONBLOCK|FNBIO|_FNBIO|FNONBIO|FNONBLOCK|_FNONBLOCK| |
---|
1815 | FNDELAY|_FNDELAY|FNDLEAY); /* whew! */ |
---|
1816 | if (fcntl(fd, F_SETFL, e) == -1) |
---|
1817 | return -1; |
---|
1818 | else |
---|
1819 | e = 1; |
---|
1820 | # endif /* F_SETFL */ |
---|
1821 | |
---|
1822 | # ifdef FIONBIO |
---|
1823 | e = 0; |
---|
1824 | if (ioctl(fd, FIONBIO, (ioctl_t) &e) == -1) |
---|
1825 | return -1; |
---|
1826 | else |
---|
1827 | e = 1; |
---|
1828 | # endif /* FIONBIO */ |
---|
1829 | |
---|
1830 | #endif /* FDRETRY */ |
---|
1831 | return e ? 0 : -1; |
---|
1832 | |
---|
1833 | case EINTR: |
---|
1834 | return 0; |
---|
1835 | |
---|
1836 | default: |
---|
1837 | return -1; |
---|
1838 | } |
---|
1839 | } |
---|
1840 | |
---|
1841 | /* collate(): |
---|
1842 | * String collation |
---|
1843 | */ |
---|
1844 | int |
---|
1845 | collate(a, b) |
---|
1846 | const Char *a; |
---|
1847 | const Char *b; |
---|
1848 | { |
---|
1849 | int rv; |
---|
1850 | #ifdef SHORT_STRINGS |
---|
1851 | /* This strips the quote bit as a side effect */ |
---|
1852 | char *sa = strsave(short2str(a)); |
---|
1853 | char *sb = strsave(short2str(b)); |
---|
1854 | #else |
---|
1855 | char *sa = strip(strsave(a)); |
---|
1856 | char *sb = strip(strsave(b)); |
---|
1857 | #endif /* SHORT_STRINGS */ |
---|
1858 | |
---|
1859 | #if defined(NLS) && !defined(NOSTRCOLL) |
---|
1860 | errno = 0; /* strcoll sets errno, another brain-damage */ |
---|
1861 | |
---|
1862 | rv = strcoll(sa, sb); |
---|
1863 | |
---|
1864 | /* |
---|
1865 | * We should be checking for errno != 0, but some systems |
---|
1866 | * forget to reset errno to 0. So we only check for the |
---|
1867 | * only documented valid errno value for strcoll [EINVAL] |
---|
1868 | */ |
---|
1869 | if (errno == EINVAL) { |
---|
1870 | xfree((ptr_t) sa); |
---|
1871 | xfree((ptr_t) sb); |
---|
1872 | stderror(ERR_SYSTEM, "strcoll", strerror(errno)); |
---|
1873 | } |
---|
1874 | #else |
---|
1875 | rv = strcmp(sa, sb); |
---|
1876 | #endif /* NLS && !NOSTRCOLL */ |
---|
1877 | |
---|
1878 | xfree((ptr_t) sa); |
---|
1879 | xfree((ptr_t) sb); |
---|
1880 | |
---|
1881 | return rv; |
---|
1882 | } |
---|
1883 | |
---|
1884 | #ifdef HASHBANG |
---|
1885 | /* |
---|
1886 | * From: peter@zeus.dialix.oz.au (Peter Wemm) |
---|
1887 | * If exec() fails look first for a #! [word] [word] .... |
---|
1888 | * If it is, splice the header into the argument list and retry. |
---|
1889 | */ |
---|
1890 | #define HACKBUFSZ 1024 /* Max chars in #! vector */ |
---|
1891 | #define HACKVECSZ 128 /* Max words in #! vector */ |
---|
1892 | int |
---|
1893 | hashbang(fd, vp) |
---|
1894 | int fd; |
---|
1895 | Char ***vp; |
---|
1896 | { |
---|
1897 | unsigned char lbuf[HACKBUFSZ]; |
---|
1898 | char *sargv[HACKVECSZ]; |
---|
1899 | unsigned char *p, *ws; |
---|
1900 | int sargc = 0; |
---|
1901 | #ifdef WINNT |
---|
1902 | int fw = 0; /* found at least one word */ |
---|
1903 | int first_word = 0; |
---|
1904 | #endif /* WINNT */ |
---|
1905 | |
---|
1906 | if (read(fd, (char *) lbuf, HACKBUFSZ) <= 0) |
---|
1907 | return -1; |
---|
1908 | |
---|
1909 | ws = 0; /* word started = 0 */ |
---|
1910 | |
---|
1911 | for (p = lbuf; p < &lbuf[HACKBUFSZ]; ) |
---|
1912 | switch (*p) { |
---|
1913 | case ' ': |
---|
1914 | case '\t': |
---|
1915 | #ifdef WINNT |
---|
1916 | case '\r': |
---|
1917 | #endif /* WINNT */ |
---|
1918 | if (ws) { /* a blank after a word.. save it */ |
---|
1919 | *p = '\0'; |
---|
1920 | #ifndef WINNT |
---|
1921 | if (sargc < HACKVECSZ - 1) |
---|
1922 | sargv[sargc++] = ws; |
---|
1923 | ws = NULL; |
---|
1924 | #else /* WINNT */ |
---|
1925 | if (sargc < HACKVECSZ - 1) { |
---|
1926 | sargv[sargc] = first_word ? NULL: hb_subst(ws); |
---|
1927 | if (sargv[sargc] == NULL) |
---|
1928 | sargv[sargc] = ws; |
---|
1929 | sargc++; |
---|
1930 | } |
---|
1931 | ws = NULL; |
---|
1932 | fw = 1; |
---|
1933 | first_word = 1; |
---|
1934 | #endif /* WINNT */ |
---|
1935 | } |
---|
1936 | p++; |
---|
1937 | continue; |
---|
1938 | |
---|
1939 | case '\0': /* Whoa!! what the hell happened */ |
---|
1940 | return -1; |
---|
1941 | |
---|
1942 | case '\n': /* The end of the line. */ |
---|
1943 | if ( |
---|
1944 | #ifdef WINNT |
---|
1945 | fw || |
---|
1946 | #endif /* WINNT */ |
---|
1947 | ws) { /* terminate the last word */ |
---|
1948 | *p = '\0'; |
---|
1949 | #ifndef WINNT |
---|
1950 | if (sargc < HACKVECSZ - 1) |
---|
1951 | sargv[sargc++] = ws; |
---|
1952 | #else /* WINNT */ |
---|
1953 | if (sargc < HACKVECSZ - 1) { /* deal with the 1-word case */ |
---|
1954 | sargv[sargc] = first_word? NULL : hb_subst(ws); |
---|
1955 | if (sargv[sargc] == NULL) |
---|
1956 | sargv[sargc] = ws; |
---|
1957 | sargc++; |
---|
1958 | } |
---|
1959 | #endif /* !WINNT */ |
---|
1960 | } |
---|
1961 | sargv[sargc] = NULL; |
---|
1962 | ws = NULL; |
---|
1963 | if (sargc > 0) { |
---|
1964 | *vp = blk2short(sargv); |
---|
1965 | return 0; |
---|
1966 | } |
---|
1967 | else |
---|
1968 | return -1; |
---|
1969 | |
---|
1970 | default: |
---|
1971 | if (!ws) /* Start a new word? */ |
---|
1972 | ws = p; |
---|
1973 | p++; |
---|
1974 | break; |
---|
1975 | } |
---|
1976 | return -1; |
---|
1977 | } |
---|
1978 | #endif /* HASHBANG */ |
---|
1979 | |
---|
1980 | #ifdef REMOTEHOST |
---|
1981 | |
---|
1982 | static sigret_t |
---|
1983 | palarm(snum) |
---|
1984 | int snum; |
---|
1985 | { |
---|
1986 | USE(snum); |
---|
1987 | #ifdef UNRELSIGS |
---|
1988 | if (snum) |
---|
1989 | (void) sigset(snum, SIG_IGN); |
---|
1990 | #endif /* UNRELSIGS */ |
---|
1991 | (void) alarm(0); |
---|
1992 | reset(); |
---|
1993 | |
---|
1994 | #ifndef SIGVOID |
---|
1995 | return (snum); |
---|
1996 | #endif |
---|
1997 | } |
---|
1998 | |
---|
1999 | |
---|
2000 | static void |
---|
2001 | getremotehost() |
---|
2002 | { |
---|
2003 | const char *host = NULL; |
---|
2004 | struct hostent* hp; |
---|
2005 | struct sockaddr_in saddr; |
---|
2006 | int len = sizeof(struct sockaddr_in); |
---|
2007 | #if defined(UTHOST) && !defined(HAVENOUTMP) |
---|
2008 | char *sptr = NULL; |
---|
2009 | #endif |
---|
2010 | |
---|
2011 | if (getpeername(SHIN, (struct sockaddr *) &saddr, &len) != -1) { |
---|
2012 | #if 0 |
---|
2013 | if ((hp = gethostbyaddr((char *)&saddr.sin_addr, sizeof(struct in_addr), |
---|
2014 | AF_INET)) != NULL) |
---|
2015 | host = hp->h_name; |
---|
2016 | else |
---|
2017 | #endif |
---|
2018 | host = inet_ntoa(saddr.sin_addr); |
---|
2019 | } |
---|
2020 | #if defined(UTHOST) && !defined(HAVENOUTMP) |
---|
2021 | else { |
---|
2022 | char *ptr; |
---|
2023 | char *name = utmphost(); |
---|
2024 | /* Avoid empty names and local X displays */ |
---|
2025 | if (name != NULL && *name != '\0' && *name != ':') { |
---|
2026 | /* Look for host:display.screen */ |
---|
2027 | if ((sptr = strchr(name, ':')) != NULL) |
---|
2028 | *sptr = '\0'; |
---|
2029 | /* Leave IP address as is */ |
---|
2030 | if (isdigit(*name)) |
---|
2031 | host = name; |
---|
2032 | else { |
---|
2033 | if (sptr != name) { |
---|
2034 | if ((hp = gethostbyname(name)) == NULL) { |
---|
2035 | /* Try again eliminating the trailing domain */ |
---|
2036 | if ((ptr = strchr(name, '.')) != NULL) { |
---|
2037 | *ptr = '\0'; |
---|
2038 | if ((hp = gethostbyname(name)) != NULL) |
---|
2039 | host = hp->h_name; |
---|
2040 | *ptr = '.'; |
---|
2041 | } |
---|
2042 | } |
---|
2043 | else |
---|
2044 | host = hp->h_name; |
---|
2045 | } |
---|
2046 | } |
---|
2047 | } |
---|
2048 | } |
---|
2049 | #endif |
---|
2050 | |
---|
2051 | if (host) |
---|
2052 | tsetenv(STRREMOTEHOST, str2short(host)); |
---|
2053 | |
---|
2054 | #if defined(UTHOST) && !defined(HAVENOUTMP) |
---|
2055 | if (sptr) |
---|
2056 | *sptr = ':'; |
---|
2057 | #endif |
---|
2058 | } |
---|
2059 | |
---|
2060 | |
---|
2061 | /* |
---|
2062 | * From: <lesv@ppvku.ericsson.se> (Lennart Svensson) |
---|
2063 | */ |
---|
2064 | void |
---|
2065 | remotehost() |
---|
2066 | { |
---|
2067 | /* Don't get stuck if the resolver does not work! */ |
---|
2068 | signalfun_t osig = sigset(SIGALRM, palarm); |
---|
2069 | |
---|
2070 | jmp_buf_t osetexit; |
---|
2071 | getexit(osetexit); |
---|
2072 | |
---|
2073 | (void) alarm(2); |
---|
2074 | |
---|
2075 | if (setexit() == 0) |
---|
2076 | getremotehost(); |
---|
2077 | |
---|
2078 | resexit(osetexit); |
---|
2079 | |
---|
2080 | (void) alarm(0); |
---|
2081 | (void) sigset(SIGALRM, osig); |
---|
2082 | |
---|
2083 | #ifdef YPBUGS |
---|
2084 | /* From: casper@fwi.uva.nl (Casper H.S. Dik), for Solaris 2.3 */ |
---|
2085 | fix_yp_bugs(); |
---|
2086 | #endif /* YPBUGS */ |
---|
2087 | |
---|
2088 | } |
---|
2089 | #endif /* REMOTEHOST */ |
---|