source: trunk/third/tcsh/tc.func.c @ 12039

Revision 12039, 46.8 KB checked in by danw, 26 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r12038, which included commits to RCS files with non-trunk default branches.
Line 
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
39RCSID("$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>
53long ka_UserAuthenticateGeneral();
54#else
55#ifndef PASSMAX
56#define PASSMAX 8
57#endif
58#endif /* AFS */
59
60#ifdef TESLA
61extern int do_logout;
62#endif /* TESLA */
63extern time_t t_period;
64extern int just_signaled;
65static bool precmd_active = 0;
66static bool periodic_active = 0;
67static bool cwdcmd_active = 0;  /* PWP: for cwd_cmd */
68static bool beepcmd_active = 0;
69static signalfun_t alm_fun = NULL;
70
71static  void     Reverse        __P((Char *));
72static  void     auto_logout    __P((int));
73static  char    *xgetpass       __P((char *));
74static  void     auto_lock      __P((int));
75#ifdef BSDJOBS
76static  void     insert         __P((struct wordent *, bool));
77static  void     insert_we      __P((struct wordent *, struct wordent *));
78static  int      inlist         __P((Char *, Char *));
79#endif /* BSDJOBS */
80struct tildecache;
81static  int      tildecompare   __P((struct tildecache *, struct tildecache *));
82static  Char    *gethomedir     __P((Char *));
83#ifdef REMOTEHOST
84static  sigret_t palarm         __P((int));
85static  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
105Char   *
106expand_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
161Char   *
162sprlex(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
174void
175Itoa(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
193static void
194Reverse(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*/
209void
210dolist(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
412static char *defaulttell = "ALL";
413extern bool GotTermCaps;
414
415/*ARGSUSED*/
416void
417dotelltc(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*/
436void
437doechotc(v, c)
438    register Char **v;
439    struct command *c;
440{
441    if (!GotTermCaps)
442        GetTermCaps();
443    EchoTC(++v);
444}
445
446/*ARGSUSED*/
447void
448dosettc(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 */
470int
471cmd_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*/
508void
509dowhich(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
550struct process *
551find_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
623void
624fg_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
668static char *
669xgetpass(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*/
707static void
708auto_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
818static void
819auto_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
837sigret_t
838/*ARGSUSED*/
839alrmcatch(snum)
840int 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 */
864void
865precmd()
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);
882leave:
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 */
897void
898cwd_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);
915leave:
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 */
928void
929beep_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 */
961void
962period_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    }
990leave:
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 */
1004void
1005aliasrun(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
1092void
1093setalarm(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
1135void
1136rmstar(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 */
1239void
1240continue_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().   */
1311static void
1312insert(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
1405static void
1406insert_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
1416static int
1417inlist(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 */
1455static struct tildecache {
1456    Char   *user;
1457    Char   *home;
1458    int     hlen;
1459}      *tcache = NULL;
1460
1461#define TILINCR 10
1462int tlength = 0;
1463static int tsize = TILINCR;
1464
1465static int
1466tildecompare(p1, p2)
1467    struct tildecache *p1, *p2;
1468{
1469    return Strcmp(p1->user, p2->user);
1470}
1471
1472static Char *
1473gethomedir(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
1524Char   *
1525gettilde(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 */
1585Char   *
1586getusername(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*/
1626void
1627doaliases(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
1703eof:
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 */
1716void
1717shlvl(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 */
1752int
1753fixio(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 */
1844int
1845collate(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 */
1892int
1893hashbang(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
1982static sigret_t
1983palarm(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
2000static void
2001getremotehost()
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 */
2064void
2065remotehost()
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 */
Note: See TracBrowser for help on using the repository browser.