# 2.11BSD#431 - /usr/src/bin/tcsh/tc.func.c

##### Functions

    Itoa              X
    aliasrun          X
    alrmcatch         X
    con_jobs          X
    cwd_cmd           X
    do_aliases        X
    doechotc          X
    dolist            X
    dosettc           X
    dotelltc          X
    dowhich           X
    expand_lex        X
    fg_proc_entry     X
    find_stop_ed      X
    gettilde          X
    getusername       X
    period_cmd        X
    precmd            X
    rmstar            X
    setalarm          X
    sprlex            X

##### Macros

    CNDEBUG           X
    RMDEBUG           X
    TILINCR           X

##### struct's

    tildecache        X

       1: /* $Header: /home/hyperion/mu/christos/src/sys/tcsh-6.00/RCS/tc.func.c,v 3.0 1991/07/04 21:49:28 christos 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 "config.h"
      38: #if !defined(lint) && !defined(pdp11)
      39: static char *rcsid()
      40:     { return "$Id: tc.func.c,v 3.0 1991/07/04 21:49:28 christos Exp $"; }
      41: #endif
      42:
      43: #include "sh.h"
      44: #include "ed.h"
      45: #include "ed.defns.h"       /* for the function names */
      46: #include "tw.h"
      47:
      48: extern time_t t_period;
      49: static bool precmd_active = 0;
      50: static bool periodic_active = 0;
      51: static bool cwdcmd_active = 0;  /* PWP: for cwd_cmd */
      52:
      53: static  void    Reverse     __P((Char *));
      54: static  void    auto_logout __P((void));
      55: static  void    insert      __P((struct wordent *, bool));
      56: static  void    insert_we   __P((struct wordent *, struct wordent *));
      57: static  int inlist      __P((Char *, Char *));
      58:
      59:
      60: /*
      61:  * Tops-C shell
      62:  */
      63:
      64: /*
      65:  * expand_lex: Take the given lex and put an expanded version of it in the
      66:  * string buf. First guy in lex list is ignored; last guy is ^J which we
      67:  * ignore Only take lex'es from position from to position to inclusive Note:
      68:  * csh sometimes sets bit 8 in characters which causes all kinds of problems
      69:  * if we don't mask it here. Note: excl's in lexes have been un-back-slashed
      70:  * and must be re-back-slashed
      71:  * (PWP: NOTE: this returns a pointer to the END of the string expanded
      72:  *             (in other words, where the NUL is).)
      73:  */
      74: /* PWP: this is a combination of the old sprlex() and the expand_lex from
      75:    the magic-space stuff */
      76:
      77: Char   *
      78: expand_lex(buf, bufsiz, sp0, from, to)
      79:     Char   *buf;
      80:     int     bufsiz;
      81:     struct wordent *sp0;
      82:     int     from, to;
      83: {
      84:     register struct wordent *sp;
      85:     register Char *s, *d, *e;
      86:     register Char prev_c;
      87:     register int i;
      88:
      89:     buf[0] = '\0';
      90:     prev_c = '\0';
      91:     d = buf;
      92:     e = &buf[bufsiz];       /* for bounds checking */
      93:
      94:     if (!sp0)
      95:     return (buf);       /* null lex */
      96:     if ((sp = sp0->next) == sp0)
      97:     return (buf);       /* nada */
      98:     if (sp == (sp0 = sp0->prev))
      99:     return (buf);       /* nada */
     100:
     101:     for (i = 0; i < NCARGS; i++) {
     102:     if ((i >= from) && (i <= to)) { /* if in range */
     103:         for (s = sp->word; *s && d < e; s++) {
     104:         /*
     105: 		 * bugfix by Michael Bloom: anything but the current history
     106: 		 * character {(PWP) and backslash} seem to be dealt with
     107: 		 * elsewhere.
     108: 		 */
     109:         if ((*s & QUOTE)
     110:             && (((*s & TRIM) == HIST) ||
     111:             ((*s & TRIM) == '\\') && (prev_c != '\\'))) {
     112:             *d++ = '\\';
     113:         }
     114:         *d++ = (*s & TRIM);
     115:         prev_c = *s;
     116:         }
     117:         if (d < e)
     118:         *d++ = ' ';
     119:     }
     120:     sp = sp->next;
     121:     if (sp == sp0)
     122:         break;
     123:     }
     124:     if (d > buf)
     125:     d--;            /* get rid of trailing space */
     126:
     127:     return (d);
     128: }
     129:
     130: Char   *
     131: sprlex(buf, sp0)
     132:     Char   *buf;
     133:     struct wordent *sp0;
     134: {
     135:     Char   *cp;
     136:
     137:     cp = expand_lex(buf, INBUFSIZ, sp0, 0, NCARGS);
     138:     *cp = '\0';
     139:     return (buf);
     140: }
     141:
     142: void
     143: Itoa(n, s)          /* convert n to characters in s */
     144:     int     n;
     145:     Char   *s;
     146: {
     147:     int     i, sign;
     148:
     149:     if ((sign = n) < 0)     /* record sign */
     150:     n = -n;
     151:     i = 0;
     152:     do {
     153:     s[i++] = n % 10 + '0';
     154:     } while ((n /= 10) > 0);
     155:     if (sign < 0)
     156:     s[i++] = '-';
     157:     s[i] = '\0';
     158:     Reverse(s);
     159: }
     160:
     161: static void
     162: Reverse(s)
     163:     Char   *s;
     164: {
     165:     int     c, i, j;
     166:
     167:     for (i = 0, j = Strlen(s) - 1; i < j; i++, j--) {
     168:     c = s[i];
     169:     s[i] = s[j];
     170:     s[j] = c;
     171:     }
     172: }
     173:
     174:
     175: void
     176: dolist(v)
     177:     register Char **v;
     178: {
     179:     int     i, k;
     180:     struct stat st;
     181:
     182:     if (*++v == NULL) {
     183:     (void) t_search(STRNULL, NULL, LIST, 0, 0, 0);
     184:     return;
     185:     }
     186:     gflag = 0;
     187:     tglob(v);
     188:     if (gflag) {
     189:     v = globall(v);
     190:     if (v == 0)
     191:         stderror(ERR_NAME | ERR_NOMATCH);
     192:     }
     193:     else
     194:     v = gargv = saveblk(v);
     195:     trim(v);
     196:     for (k = 0; v[k] != NULL && v[k][0] != '-'; k++);
     197:     if (v[k]) {
     198:     /*
     199: 	 * We cannot process a flag therefore we let ls do it right.
     200: 	 */
     201:     static Char STRls[] =
     202:     {'l', 's', '\0'};
     203:     static Char STRmCF[] =
     204:     {'-', 'C', 'F', '\0'};
     205:     struct command *t;
     206:     struct wordent cmd, *nextword, *lastword;
     207:     Char   *cp;
     208:
     209: #ifdef BSDSIGS
     210:     sigmask_t omask = 0;
     211:
     212:     if (setintr)
     213:         omask = sigblock(sigmask(SIGINT)) & ~sigmask(SIGINT);
     214: #else
     215:     sighold(SIGINT);
     216: #endif
     217:     if (seterr) {
     218:         xfree((ptr_t) seterr);
     219:         seterr = NULL;
     220:     }
     221:     cmd.word = STRNULL;
     222:     lastword = &cmd;
     223:     nextword = (struct wordent *) xcalloc(1, sizeof cmd);
     224:     nextword->word = Strsave(STRls);
     225:     lastword->next = nextword;
     226:     nextword->prev = lastword;
     227:     lastword = nextword;
     228:     nextword = (struct wordent *) xcalloc(1, sizeof cmd);
     229:     nextword->word = Strsave(STRmCF);
     230:     lastword->next = nextword;
     231:     nextword->prev = lastword;
     232:     lastword = nextword;
     233:     for (cp = *v; cp; cp = *++v) {
     234:         nextword = (struct wordent *) xcalloc(1, sizeof cmd);
     235:         nextword->word = Strsave(cp);
     236:         lastword->next = nextword;
     237:         nextword->prev = lastword;
     238:         lastword = nextword;
     239:     }
     240:     lastword->next = &cmd;
     241:     cmd.prev = lastword;
     242:
     243:     /* build a syntax tree for the command. */
     244:     t = syntax(cmd.next, &cmd, 0);
     245:     if (seterr)
     246:         stderror(ERR_OLD);
     247:     /* expand aliases like process() does */
     248:     /* alias(&cmd); */
     249:     /* execute the parse tree. */
     250:     execute(t, tpgrp > 0 ? tpgrp : -1, NULL, NULL);
     251:     /* done. free the lex list and parse tree. */
     252:     freelex(&cmd), freesyn(t);
     253:     if (setintr)
     254: #ifdef BSDSIGS
     255:         (void) sigsetmask(omask);
     256: #else
     257:         (void) sigrelse(SIGINT);
     258: #endif
     259:     }
     260:     else {
     261:     Char   *dp, *tmp, buf[MAXPATHLEN];
     262:
     263:     for (k = 0, i = 0; v[k] != NULL; k++) {
     264:         tmp = dnormalize(v[k]);
     265:         dp = &tmp[Strlen(tmp) - 1];
     266:         if (*dp == '/' && dp != tmp)
     267: #ifdef apollo
     268:         if (dp != &tmp[1])
     269: #endif
     270:         *dp = '\0';
     271:         if (stat(short2str(tmp), &st) == -1) {
     272:         if (k != i) {
     273:             if (i != 0)
     274:             xputchar('\n');
     275:             print_by_column(STRNULL, &v[i], k - i, FALSE);
     276:         }
     277:         xprintf("%s: %s.\n", short2str(tmp), strerror(errno));
     278:         i = k + 1;
     279:         }
     280:         else if (S_ISDIR(st.st_mode)) {
     281:         Char   *cp;
     282:
     283:         if (k != i) {
     284:             if (i != 0)
     285:             xputchar('\n');
     286:             print_by_column(STRNULL, &v[i], k - i, FALSE);
     287:         }
     288:         if (k != 0 && v[1] != NULL)
     289:             xputchar('\n');
     290:         xprintf("%s:\n", short2str(tmp));
     291:         for (cp = tmp, dp = buf; *cp; *dp++ = (*cp++ | QUOTE));
     292:         if (dp[-1] != (Char) ('/' | QUOTE))
     293:             *dp++ = '/';
     294:         else
     295:             dp[-1] &= TRIM;
     296:         *dp = '\0';
     297:         (void) t_search(buf, NULL, LIST, 0, 0, 0);
     298:         i = k + 1;
     299:         }
     300:         xfree((ptr_t) tmp);
     301:     }
     302:     if (k != i) {
     303:         if (i != 0)
     304:         xputchar('\n');
     305:         print_by_column(STRNULL, &v[i], k - i, FALSE);
     306:     }
     307:     }
     308:
     309:     if (gargv) {
     310:     blkfree(gargv);
     311:     gargv = 0;
     312:     }
     313: }
     314:
     315: static char *d_tell = "ALL";
     316: extern bool GotTermCaps;
     317:
     318: void
     319: dotelltc(v)
     320:     register Char **v;
     321: {
     322:
     323:     if (!GotTermCaps)
     324:     GetTermCaps();
     325:
     326:     TellTC(v[1] ? short2str(v[1]) : d_tell);
     327: }
     328:
     329: void
     330: doechotc(v)
     331:     register Char **v;
     332: {
     333:     if (!GotTermCaps)
     334:     GetTermCaps();
     335:     EchoTC(++v);
     336: }
     337:
     338: void
     339: dosettc(v)
     340:     Char  **v;
     341: {
     342:     char    tv[2][BUFSIZ];
     343:
     344:     if (!GotTermCaps)
     345:     GetTermCaps();
     346:
     347:     (void) strcpy(tv[0], short2str(v[1]));
     348:     (void) strcpy(tv[1], short2str(v[2]));
     349:     SetTC(tv[0], tv[1]);
     350: }
     351:
     352: /* The dowhich() is by:
     353:  *  Andreas Luik <luik@isaak.isa.de>
     354:  *  I S A  GmbH - Informationssysteme fuer computerintegrierte Automatisierung
     355:  *  Azenberstr. 35
     356:  *  D-7000 Stuttgart 1
     357:  *  West-Germany
     358:  * Thanks!!
     359:  */
     360:
     361: void
     362: dowhich(v)
     363:     register Char **v;
     364: {
     365:     struct wordent lex[3];
     366:     struct varent *vp;
     367:
     368:     lex[0].next = &lex[1];
     369:     lex[1].next = &lex[2];
     370:     lex[2].next = &lex[0];
     371:
     372:     lex[0].prev = &lex[2];
     373:     lex[1].prev = &lex[0];
     374:     lex[2].prev = &lex[1];
     375:
     376:     lex[0].word = STRNULL;
     377:     lex[2].word = STRret;
     378:
     379:     while (*++v) {
     380:     if (vp = adrof1(*v, &aliases)) {
     381:         xprintf("%s: \t aliased to ", short2str(*v));
     382:         blkpr(vp->vec);
     383:         xprintf("\n");
     384:     }
     385:     else {
     386:         lex[1].word = *v;
     387:         tellmewhat(lex);
     388:     }
     389:     }
     390: }
     391:
     392: /* PWP: a hack to start up your stopped editor on a single keystroke */
     393: /* jbs - fixed hack so it worked :-) 3/28/89 */
     394:
     395: struct process *
     396: find_stop_ed()
     397: {
     398:     register struct process *pp;
     399:     register char *ep, *vp, *p;
     400:     int     epl, vpl;
     401:
     402:     if ((ep = getenv("EDITOR")) != NULL) {  /* if we have a value */
     403:     if ((p = strrchr(ep, '/')) != NULL) {   /* if it has a path */
     404:         ep = p + 1;     /* then we want only the last part */
     405:     }
     406:     }
     407:     else {
     408:     ep = "ed";
     409:     }
     410:     if ((vp = getenv("VISUAL")) != NULL) {  /* if we have a value */
     411:     if ((p = strrchr(vp, '/')) != NULL) {   /* and it has a path */
     412:         vp = p + 1;     /* then we want only the last part */
     413:     }
     414:     }
     415:     else {
     416:     vp = "vi";
     417:     }
     418:     vpl = strlen(vp);
     419:     epl = strlen(ep);
     420:
     421:     if (pcurrent == PNULL)  /* see if we have any jobs */
     422:     return PNULL;       /* nope */
     423:
     424:     for (pp = proclist.p_next; pp; pp = pp->p_next) {
     425:     if (pp->p_pid == pp->p_jobid) {
     426:         p = short2str(pp->p_command);
     427:         /* if we find either in the current name, fg it */
     428:         if (strncmp(ep, p, (size_t) epl) == 0 ||
     429:         strncmp(vp, p, (size_t) vpl) == 0)
     430:         return pp;
     431:     }
     432:     }
     433:     return PNULL;       /* didn't find a job */
     434: }
     435:
     436: void
     437: fg_proc_entry(pp)
     438:     register struct process *pp;
     439: {
     440: #ifdef BSDSIGS
     441:     sigmask_t omask;
     442: #endif
     443:     jmp_buf osetexit;
     444:     bool    ohaderr;
     445:
     446:     getexit(osetexit);
     447:
     448: #ifdef BSDSIGS
     449:     omask = sigblock(sigmask(SIGINT));
     450: #else
     451:     (void) sighold(SIGINT);
     452: #endif
     453:
     454:     ohaderr = haderr;       /* we need to ignore setting of haderr due to
     455: 				 * process getting stopped by a signal */
     456:     if (setexit() == 0) {   /* come back here after pjwait */
     457:     pendjob();
     458:     pstart(pp, 1);      /* found it. */
     459:     pjwait(pp);
     460:     }
     461:
     462:     resexit(osetexit);
     463:     haderr = ohaderr;
     464:
     465: #ifdef BSDSIGS
     466:     (void) sigsetmask(omask);
     467: #else
     468:     (void) sigrelse(SIGINT);
     469: #endif
     470:
     471: }
     472:
     473: static void
     474: auto_logout()
     475: {
     476:     xprintf("auto-logout\n");
     477:     /* Don't leave the tty in raw mode */
     478:     if (editing)
     479:     (void) Cookedmode();
     480:     (void) close(SHIN);
     481:     set(STRlogout, Strsave(STRa_matic));
     482:     child = 1;
     483: #ifdef TESLA
     484:     do_logout = 1;
     485: #endif				/* TESLA */
     486:     goodbye();
     487: }
     488:
     489: sigret_t
     490: /*ARGSUSED*/
     491: alrmcatch(snum)
     492: int snum;
     493: {
     494:     time_t  cl, nl;
     495:
     496:     if ((nl = sched_next()) == -1)
     497:     auto_logout();      /* no other possibility - logout */
     498:     (void) time(&cl);
     499:     if (nl <= cl + 1)
     500:     sched_run();
     501:     else
     502:     auto_logout();
     503:     setalarm();
     504: #ifndef SIGVOID
     505:     return (snum);
     506: #endif
     507: }
     508:
     509: /*
     510:  * Karl Kleinpaste, 21oct1983.
     511:  * Added precmd(), which checks for the alias
     512:  * precmd in aliases.  If it's there, the alias
     513:  * is executed as a command.  This is done
     514:  * after mailchk() and just before print-
     515:  * ing the prompt.  Useful for things like printing
     516:  * one's current directory just before each command.
     517:  */
     518: void
     519: precmd()
     520: {
     521: #ifdef BSDSIGS
     522:     sigmask_t omask;
     523: #endif
     524:
     525: #ifdef BSDSIGS
     526:     omask = sigblock(sigmask(SIGINT));
     527: #else
     528:     (void) sighold(SIGINT);
     529: #endif
     530:     if (precmd_active) {    /* an error must have been caught */
     531:     aliasrun(2, STRunalias, STRprecmd);
     532:     xprintf("Faulty alias 'precmd' removed.\n");
     533:     goto leave;
     534:     }
     535:     precmd_active = 1;
     536:     if (!whyles && adrof1(STRprecmd, &aliases))
     537:     aliasrun(1, STRprecmd, NULL);
     538: leave:
     539:     precmd_active = 0;
     540: #ifdef BSDSIGS
     541:     (void) sigsetmask(omask);
     542: #else
     543:     (void) sigrelse(SIGINT);
     544: #endif
     545: }
     546:
     547: /*
     548:  * Paul Placeway  11/24/87  Added cwd_cmd by hacking precmd() into
     549:  * submission...  Run every time $cwd is set (after it is set).  Useful
     550:  * for putting your machine and cwd (or anything else) in an xterm title
     551:  * space.
     552:  */
     553: void
     554: cwd_cmd()
     555: {
     556: #ifdef BSDSIGS
     557:     sigmask_t omask;
     558: #endif
     559:
     560: #ifdef BSDSIGS
     561:     omask = sigblock(sigmask(SIGINT));
     562: #else
     563:     (void) sighold(SIGINT);
     564: #endif
     565:     if (cwdcmd_active) {    /* an error must have been caught */
     566:     aliasrun(2, STRunalias, STRcwdcmd);
     567:     xprintf("Faulty alias 'cwdcmd' removed.\n");
     568:     goto leave;
     569:     }
     570:     cwdcmd_active = 1;
     571:     if (!whyles && adrof1(STRcwdcmd, &aliases))
     572:     aliasrun(1, STRcwdcmd, NULL);
     573: leave:
     574:     cwdcmd_active = 0;
     575: #ifdef BSDSIGS
     576:     (void) sigsetmask(omask);
     577: #else
     578:     (void) sigrelse(SIGINT);
     579: #endif
     580: }
     581:
     582:
     583: /*
     584:  * Karl Kleinpaste, 18 Jan 1984.
     585:  * Added period_cmd(), which executes the alias "periodic" every
     586:  * $tperiod minutes.  Useful for occasional checking of msgs and such.
     587:  */
     588: void
     589: period_cmd()
     590: {
     591:     register Char *vp;
     592:     time_t  t, interval;
     593: #ifdef BSDSIGS
     594:     sigmask_t omask;
     595: #endif
     596:
     597: #ifdef BSDSIGS
     598:     omask = sigblock(sigmask(SIGINT));
     599: #else
     600:     (void) sighold(SIGINT);
     601: #endif
     602:     if (periodic_active) {  /* an error must have been caught */
     603:     aliasrun(2, STRunalias, STRperiodic);
     604:     xprintf("Faulty alias 'periodic' removed.\n");
     605:     goto leave;
     606:     }
     607:     periodic_active = 1;
     608:     if (!whyles && adrof1(STRperiodic, &aliases)) {
     609:     vp = value(STRtperiod);
     610:     if (vp == NOSTR)
     611:         return;
     612:     interval = getn(vp);
     613:     (void) time(&t);
     614:     if (t - t_period >= interval * 60) {
     615:         t_period = t;
     616:         aliasrun(1, STRperiodic, NULL);
     617:     }
     618:     }
     619: leave:
     620:     periodic_active = 0;
     621: #ifdef BSDSIGS
     622:     (void) sigsetmask(omask);
     623: #else
     624:     (void) sigrelse(SIGINT);
     625: #endif
     626: }
     627:
     628: /*
     629:  * Karl Kleinpaste, 21oct1983.
     630:  * Set up a one-word alias command, for use for special things.
     631:  * This code is based on the mainline of process().
     632:  */
     633: void
     634: aliasrun(cnt, s1, s2)
     635:     int     cnt;
     636:     Char   *s1, *s2;
     637: {
     638:     struct wordent w, *new1, *new2; /* for holding alias name */
     639:     struct command *t = NULL;
     640:     jmp_buf osetexit;
     641:
     642:     getexit(osetexit);
     643:     if (seterr) {
     644:     xfree((ptr_t) seterr);
     645:     seterr = NULL;  /* don't repeatedly print err msg. */
     646:     }
     647:     w.word = STRNULL;
     648:     new1 = (struct wordent *) xcalloc(1, sizeof w);
     649:     new1->word = Strsave(s1);
     650:     if (cnt == 1) {
     651:     /* build a lex list with one word. */
     652:     w.next = w.prev = new1;
     653:     new1->next = new1->prev = &w;
     654:     }
     655:     else {
     656:     /* build a lex list with two words. */
     657:     new2 = (struct wordent *) xcalloc(1, sizeof w);
     658:     new2->word = Strsave(s2);
     659:     w.next = new2->prev = new1;
     660:     new1->next = w.prev = new2;
     661:     new1->prev = new2->next = &w;
     662:     }
     663:
     664:     /* expand aliases like process() does. */
     665:     alias(&w);
     666:     /* build a syntax tree for the command. */
     667:     t = syntax(w.next, &w, 0);
     668:     if (seterr)
     669:     stderror(ERR_OLD);
     670:
     671:     psavejob();
     672:     /* catch any errors here */
     673:     if (setexit() == 0)
     674:     /* execute the parse tree. */
     675:     /*
     676: 	 * From: Michael Schroeder <mlschroe@immd4.informatik.uni-erlangen.de>
     677: 	 * was execute(t, tpgrp);
     678: 	 */
     679:     execute(t, tpgrp > 0 ? tpgrp : -1, NULL, NULL);
     680:     /* done. free the lex list and parse tree. */
     681:     freelex(&w), freesyn(t);
     682:     if (haderr) {
     683:     haderr = 0;
     684:     /*
     685: 	 * Either precmd, or cwdcmd, or periodic had an error. Call it again so
     686: 	 * that it is removed
     687: 	 */
     688:     if (precmd_active)
     689:         precmd();
     690: #ifdef notdef
     691:     /*
     692: 	 * XXX: On the other hand, just interrupting them causes an error too.
     693: 	 * So if we hit ^C in the middle of cwdcmd or periodic the alias gets
     694: 	 * removed. We don't want that. Note that we want to remove precmd
     695: 	 * though, cause that could lead into an infinite loop. This should be
     696: 	 * fixed correctly, but then haderr should give us the whole exit
     697: 	 * status not just true or false.
     698: 	 */
     699:     else if (cwdcmd_active)
     700:         cwd_cmd();
     701:     else if (periodic_active)
     702:         period_cmd();
     703: #endif
     704:     }
     705:     /* reset the error catcher to the old place */
     706:     resexit(osetexit);
     707:     prestjob();
     708:     pendjob();
     709: }
     710:
     711: void
     712: setalarm()
     713: {
     714:     struct varent *vp;
     715:     Char   *cp;
     716:     unsigned alrm_time = 0;
     717:     long    cl, nl, sched_dif;
     718:
     719:     if (vp = adrof(STRa_logout)) {
     720:     if (cp = vp->vec[0])
     721:         alrm_time = (atoi(short2str(cp)) * 60);
     722:     }
     723:     if ((nl = sched_next()) != -1) {
     724:     (void) time(&cl);
     725:     sched_dif = nl - cl;
     726:     if ((alrm_time == 0) || (sched_dif < alrm_time))
     727:         alrm_time = ((int) sched_dif) + 1;
     728:     }
     729:     (void) alarm(alrm_time);    /* Autologout ON */
     730: }
     731:
     732: #define RMDEBUG         /* For now... */
     733:
     734: void
     735: rmstar(cp)
     736:     struct wordent *cp;
     737: {
     738:     struct wordent *we, *args;
     739:     register struct wordent *tmp, *del;
     740:
     741: #ifdef RMDEBUG
     742:     static Char STRrmdebug[] =
     743:     {'r', 'm', 'd', 'e', 'b', 'u', 'g', '\0'};
     744:     Char   *tag;
     745:
     746: #endif
     747:     Char   *charac;
     748:     char    c;
     749:     int     ask, doit, star = 0, silent = 0;
     750:
     751:     if (!adrof(STRrmstar))
     752:     return;
     753: #ifdef RMDEBUG
     754:     tag = value(STRrmdebug);
     755: #endif
     756:     we = cp->next;
     757:     while (*we->word == ';' && we != cp)
     758:     we = we->next;
     759:     while (we != cp) {
     760: #ifdef RMDEBUG
     761:     if (*tag)
     762:         xprintf("parsing command line\n");
     763: #endif
     764:     if (!Strcmp(we->word, STRrm)) {
     765:         args = we->next;
     766:         ask = (*args->word != '-');
     767:         while (*args->word == '-' && !silent) { /* check options */
     768:         for (charac = (args->word + 1); *charac && !silent; charac++)
     769:             silent = (*charac == 'i' || *charac == 'f');
     770:         args = args->next;
     771:         }
     772:         ask = (ask || !ask && !silent);
     773:         if (ask) {
     774:         for (; !star && *args->word != ';'
     775:              && args != cp; args = args->next)
     776:             if (!Strcmp(args->word, STRstar))
     777:             star = 1;
     778:         if (ask && star) {
     779:             xprintf("Do you really want to delete all files? [n/y] ");
     780:             flush();
     781:             (void) read(SHIN, &c, 1);
     782:             doit = (c == 'Y' || c == 'y');
     783:             while (c != '\n')
     784:             (void) read(SHIN, &c, 1);
     785:             if (!doit) {
     786:             /* remove the command instead */
     787:             if (*tag)
     788:                 xprintf("skipping deletion of files!\n");
     789:             for (tmp = we;
     790:                  *tmp->word != '\n' &&
     791:                  *tmp->word != ';' && tmp != cp;) {
     792:                 tmp->prev->next = tmp->next;
     793:                 tmp->next->prev = tmp->prev;
     794:                 xfree((ptr_t) tmp->word);
     795:                 del = tmp;
     796:                 tmp = tmp->next;
     797:                 xfree((ptr_t) del);
     798:             }
     799:             if (*tmp->word == ';') {
     800:                 tmp->prev->next = tmp->next;
     801:                 tmp->next->prev = tmp->prev;
     802:                 xfree((ptr_t) tmp->word);
     803:                 del = tmp;
     804:                 xfree((ptr_t) del);
     805:             }
     806:             }
     807:         }
     808:         }
     809:     }
     810:     for (we = we->next;
     811:          *we->word != ';' && we != cp;
     812:          we = we->next);
     813:     if (*we->word == ';')
     814:         we = we->next;
     815:     }
     816: #ifdef RMDEBUG
     817:     if (*tag) {
     818:     xprintf("command line now is:\n");
     819:     for (we = cp->next; we != cp; we = we->next)
     820:         xprintf("%s ", short2str(we->word));
     821:     }
     822: #endif
     823:     return;
     824: }
     825:
     826: #ifdef BSDJOBS
     827: /* Check if command is in continue list
     828:    and do a "aliasing" if it exists as a job in background */
     829:
     830: #define CNDEBUG         /* For now */
     831: void
     832: con_jobs(cp)
     833:     struct wordent *cp;
     834: {
     835:     struct wordent *we;
     836:     register struct process *pp, *np;
     837:     Char   *cmd, *con_list, *con_args_list;
     838:
     839: #ifdef CNDEBUG
     840:     Char   *tag;
     841:     static Char STRcndebug[] =
     842:     {'c', 'n', 'd', 'e', 'b', 'u', 'g', '\0'};
     843:
     844: #endif
     845:     bool    in_c__list, in_c__arg_list;
     846:
     847:
     848: #ifdef CNDEBUG
     849:     tag = value(STRcndebug);
     850: #endif
     851:     con_list = value(STRcontinue);
     852:     con_args_list = value(STRcon_args);
     853:     if (*con_list == '\0' && *con_args_list == '\0')
     854:     return;
     855:
     856:     we = cp->next;
     857:     while (*we->word == ';' && we != cp)
     858:     we = we->next;
     859:     while (we != cp) {
     860: #ifdef CNDEBUG
     861:     if (*tag)
     862:         xprintf("parsing command line\n");
     863: #endif
     864:     cmd = we->word;
     865:     in_c__list = inlist(con_list, cmd);
     866:     in_c__arg_list = inlist(con_args_list, cmd);
     867:     if (in_c__list || in_c__arg_list) {
     868: #ifdef CNDEBUG
     869:         if (*tag)
     870:         xprintf("in one of the lists\n");
     871: #endif
     872:         np = PNULL;
     873:         for (pp = proclist.p_next; pp; pp = pp->p_next) {
     874:         if (prefix(cmd, pp->p_command)) {
     875:             if (pp->p_index) {
     876:             np = pp;
     877:             break;
     878:             }
     879:         }
     880:         }
     881:         if (np) {
     882:         insert(we, in_c__arg_list);
     883:         }
     884:     }
     885:     for (we = we->next;
     886:          *we->word != ';' && we != cp;
     887:          we = we->next);
     888:     if (*we->word == ';')
     889:         we = we->next;
     890:     }
     891: #ifdef CNDEBUG
     892:     if (*tag) {
     893:     xprintf("command line now is:\n");
     894:     for (we = cp->next; we != cp; we = we->next)
     895:         xprintf("%s ",
     896:             short2str(we->word));
     897:     }
     898: #endif
     899:     return;
     900: }
     901:
     902: /* The actual "aliasing" of for backgrounds() is done here
     903:    with the aid of insert_we().   */
     904: static void
     905: insert(plist, file_args)
     906:     struct wordent *plist;
     907:     bool    file_args;
     908: {
     909:     struct wordent *now, *last;
     910:     Char   *cmd, *bcmd, *cp1, *cp2;
     911:     int     cmd_len;
     912:     Char   *pause = STRunderpause;
     913:     int     p_len = Strlen(pause);
     914:
     915:     cmd_len = Strlen(plist->word);
     916:     cmd = (Char *) xcalloc(1, (size_t) ((cmd_len + 1) * sizeof(Char)));
     917:     (void) Strcpy(cmd, plist->word);
     918: /* Do insertions at beginning, first replace command word */
     919:
     920:     if (file_args) {
     921:     now = plist;
     922:     xfree((ptr_t) now->word);
     923:     now->word = (Char *) xcalloc(1, (size_t) (5 * sizeof(Char)));
     924:     (void) Strcpy(now->word, STRecho);
     925:
     926:     now = (struct wordent *) xcalloc(1, (size_t) sizeof(struct wordent));
     927:     now->word = (Char *) xcalloc(1, (size_t) (6 * sizeof(Char)));
     928:     (void) Strcpy(now->word, STRbKqpwd);
     929:     insert_we(now, plist);
     930:
     931:     for (last = now; *last->word != '\n' && *last->word != ';';
     932:          last = last->next);
     933:
     934:     now = (struct wordent *) xcalloc(1, (size_t) sizeof(struct wordent));
     935:     now->word = (Char *) xcalloc(1, (size_t) (2 * sizeof(Char)));
     936:     (void) Strcpy(now->word, STRgt);
     937:     insert_we(now, last->prev);
     938:
     939:     now = (struct wordent *) xcalloc(1, (size_t) sizeof(struct wordent));
     940:     now->word = (Char *) xcalloc(1, (size_t) (2 * sizeof(Char)));
     941:     (void) Strcpy(now->word, STRbang);
     942:     insert_we(now, last->prev);
     943:
     944:     now = (struct wordent *) xcalloc(1, (size_t) sizeof(struct wordent));
     945:     now->word = (Char *) xcalloc(1, (size_t) cmd_len + p_len + 4);
     946:     cp1 = now->word;
     947:     cp2 = cmd;
     948:     *cp1++ = '~';
     949:     *cp1++ = '/';
     950:     *cp1++ = '.';
     951:     while (*cp1++ = *cp2++);
     952:     cp1--;
     953:     cp2 = pause;
     954:     while (*cp1++ = *cp2++);
     955:     insert_we(now, last->prev);
     956:
     957:     now = (struct wordent *) xcalloc(1, (size_t) sizeof(struct wordent));
     958:     now->word = (Char *) xcalloc(1, (size_t) (2 * sizeof(Char)));
     959:     (void) Strcpy(now->word, STRsm);
     960:     insert_we(now, last->prev);
     961:     bcmd = (Char *) xcalloc(1, (size_t) ((cmd_len + 2) * sizeof(Char)));
     962:     cp1 = bcmd;
     963:     cp2 = cmd;
     964:     *cp1++ = '%';
     965:     while (*cp1++ = *cp2++);
     966:     now = (struct wordent *) xcalloc(1, (size_t) (sizeof(struct wordent)));
     967:     now->word = bcmd;
     968:     insert_we(now, last->prev);
     969:     }
     970:     else {
     971:     struct wordent *del;
     972:
     973:     now = plist;
     974:     xfree((ptr_t) now->word);
     975:     now->word = (Char *) xcalloc(1, (size_t) ((cmd_len + 2) * sizeof(Char)));
     976:     cp1 = now->word;
     977:     cp2 = cmd;
     978:     *cp1++ = '%';
     979:     while (*cp1++ = *cp2++);
     980:     for (now = now->next;
     981:          *now->word != '\n' && *now->word != ';' && now != plist;) {
     982:         now->prev->next = now->next;
     983:         now->next->prev = now->prev;
     984:         xfree((ptr_t) now->word);
     985:         del = now;
     986:         now = now->next;
     987:         xfree((ptr_t) del);
     988:     }
     989:     }
     990: }
     991:
     992: static void
     993: insert_we(new, where)
     994:     struct wordent *new, *where;
     995: {
     996:
     997:     new->prev = where;
     998:     new->next = where->next;
     999:     where->next = new;
    1000:     new->next->prev = new;
    1001: }
    1002:
    1003: static int
    1004: inlist(list, name)
    1005:     Char   *list, *name;
    1006: {
    1007:     register Char *l, *n;
    1008:
    1009:     l = list;
    1010:     n = name;
    1011:
    1012:     while (*l && *n) {
    1013:     if (*l == *n) {
    1014:         l++;
    1015:         n++;
    1016:         if (*n == '\0' && (*l == ' ' || *l == '\0'))
    1017:         return (1);
    1018:         else
    1019:         continue;
    1020:     }
    1021:     else {
    1022:         while (*l && *l != ' ')
    1023:         l++;        /* skip to blank */
    1024:         while (*l && *l == ' ')
    1025:         l++;        /* and find first nonblank character */
    1026:         n = name;
    1027:     }
    1028:     }
    1029:     return (0);
    1030: }
    1031:
    1032: #endif				/* BSDJOBS */
    1033:
    1034:
    1035: /*
    1036:  * Implement a small cache for tilde names. This is used primarily
    1037:  * to expand tilde names to directories, but also
    1038:  * we can find users from their home directories for the tilde
    1039:  * prompt, on machines where yp lookup is slow this can be a big win...
    1040:  * As with any cache this can run out of sync...
    1041:  */
    1042: static struct tildecache {
    1043:     Char   *user;
    1044:     Char   *home;
    1045:     int     hlen;
    1046: }      *tcache = NULL;
    1047:
    1048: #define TILINCR 10
    1049: static int tlength = 0, tsize = TILINCR;
    1050:
    1051: static int
    1052: tildecompare(p1, p2)
    1053:     struct tildecache *p1, *p2;
    1054: {
    1055:     return Strcmp(p1->user, p2->user);
    1056: }
    1057:
    1058: Char   *
    1059: gettilde(us)
    1060:     Char   *us;
    1061: {
    1062:     struct tildecache *bp1, *bp2, *bp;
    1063:     register struct passwd *pp;
    1064:
    1065:     if (tcache == NULL)
    1066:     tcache = (struct tildecache *) xmalloc((size_t) (TILINCR *
    1067:                           sizeof(struct tildecache)));
    1068:     /*
    1069:      * Binary search
    1070:      */
    1071:     for (bp1 = tcache, bp2 = tcache + tlength; bp1 < bp2;) {
    1072:     register int i;
    1073:
    1074:     bp = bp1 + ((bp2 - bp1) >> 1);
    1075:     if ((i = *us - *bp->user) == 0 && (i = Strcmp(us, bp->user)) == 0)
    1076:         return (bp->home);
    1077:     if (i < 0)
    1078:         bp2 = bp;
    1079:     else
    1080:         bp1 = bp + 1;
    1081:     }
    1082:     /*
    1083:      * Not in the cache, try to get it from the passwd file
    1084:      */
    1085:     pp = getpwnam(short2str(us));
    1086: #ifdef YPBUGS
    1087:     fix_yp_bugs();
    1088: #endif
    1089:     if (pp == NULL)
    1090:     return NULL;
    1091:
    1092:     /*
    1093:      * Update the cache
    1094:      */
    1095:     tcache[tlength].user = Strsave(us);
    1096:     us = tcache[tlength].home = Strsave(str2short(pp->pw_dir));
    1097:     tcache[tlength++].hlen = Strlen(us);
    1098:
    1099:     (void) qsort((ptr_t) tcache, (size_t) tlength, sizeof(struct tildecache),
    1100:          tildecompare);
    1101:
    1102:     if (tlength == tsize) {
    1103:     tsize += TILINCR;
    1104:     tcache = (struct tildecache *) xrealloc((ptr_t) tcache,
    1105:                         (size_t) (tsize *
    1106:                           sizeof(struct tildecache)));
    1107:     }
    1108:     return (us);
    1109: }
    1110:
    1111: /*
    1112:  * Return the username if the directory path passed contains a
    1113:  * user's home directory in the tilde cache, otherwise return NULL
    1114:  * hm points to the place where the path became different.
    1115:  * Special case: Our own home directory.
    1116:  */
    1117: Char   *
    1118: getusername(hm)
    1119:     Char  **hm;
    1120: {
    1121:     Char   *h, *p;
    1122:     int     i, j;
    1123:
    1124:     if (((h = value(STRhome)) != NULL) &&
    1125:     (Strncmp(p = *hm, h, j = Strlen(h)) == 0) &&
    1126:     (p[j] == '/' || p[j] == '\0')) {
    1127:     *hm = &p[j];
    1128:     return STRNULL;
    1129:     }
    1130:     for (i = 0; i < tlength; i++)
    1131:     if ((Strncmp(p = *hm, tcache[i].home, j = tcache[i].hlen) == 0) &&
    1132:         (p[j] == '/' || p[j] == '\0')) {
    1133:         *hm = &p[j];
    1134:         return tcache[i].user;
    1135:     }
    1136:     return NULL;
    1137: }
    1138:
    1139: /*
    1140:  * PWP: read a bunch of aliases out of a file QUICKLY.  The format
    1141:  *  is almost the same as the result of saying "alias > FILE", except
    1142:  *  that saying "aliases > FILE" does not expand non-letters to printable
    1143:  *  sequences.
    1144:  */
    1145: void
    1146: do_aliases(v)
    1147:     Char  **v;
    1148: {
    1149:     jmp_buf oldexit;
    1150:     Char  **vec, *lp;
    1151:     int     fd;
    1152:     Char    buf[BUFSIZ], line[BUFSIZ];
    1153:     char    tbuf[BUFSIZ + 1], *tmp;
    1154:     extern bool output_raw; /* PWP: in sh.print.c */
    1155:
    1156:     v++;
    1157:     if (*v == 0) {
    1158:     output_raw = 1;
    1159:     plist(&aliases);
    1160:     output_raw = 0;
    1161:     return;
    1162:     }
    1163:
    1164:     gflag = 0, tglob(v);
    1165:     if (gflag) {
    1166:     v = globall(v);
    1167:     if (v == 0)
    1168:         stderror(ERR_NAME | ERR_NOMATCH);
    1169:     }
    1170:     else {
    1171:     v = gargv = saveblk(v);
    1172:     trim(v);
    1173:     }
    1174:
    1175:     if ((fd = open(tmp = short2str(*v), O_RDONLY)) < 0)
    1176:     stderror(ERR_NAME | ERR_SYSTEM, tmp, strerror(errno));
    1177:
    1178:     getexit(oldexit);
    1179:     if (setexit() == 0) {
    1180:     for (;;) {
    1181:         lp = line;
    1182:         for (;;) {
    1183:         Char   *p = NULL;
    1184:         int     n = 0;
    1185:         if (n <= 0) {
    1186:             int     i;
    1187:
    1188:             if ((n = read(fd, tbuf, BUFSIZ)) <= 0)
    1189:             goto eof;
    1190:             for (i = 0; i < n; i++)
    1191:             buf[i] = tbuf[i];
    1192:             p = buf;
    1193:         }
    1194:         n--;
    1195:         if ((*lp++ = *p++) == '\n') {
    1196:             lp[-1] = '\0';
    1197:             break;
    1198:         }
    1199:         }
    1200:         for (lp = line; *lp; lp++) {
    1201:         if (isspc(*lp)) {
    1202:             *lp++ = '\0';
    1203:             while (isspc(*lp))
    1204:             lp++;
    1205:             vec = (Char **) xmalloc((size_t)
    1206:                         (2 * sizeof(Char **)));
    1207:             vec[0] = Strsave(lp);
    1208:             vec[1] = NULL;
    1209:             setq(strip(line), vec, &aliases);
    1210:             break;
    1211:         }
    1212:         }
    1213:     }
    1214:     }
    1215:
    1216: eof:
    1217:     (void) close(fd);
    1218:     tw_clear_comm_list();
    1219:     if (gargv)
    1220:     blkfree(gargv), gargv = 0;
    1221:     resexit(oldexit);
    1222: }

#### Defined functions

Itoa defined in line 142; used 11 times

- in /usr/src/bin/tcsh/tc.prompt.c line 100, 128-133(2), 262, 268, 279, 290, 301, 312, 323, 386

Reverse defined in line 161; used 1 times

- in line 158

aliasrun defined in line 633; used 13 times

- in line 531, 537, 566, 572, 603, 616
- in /usr/src/bin/tcsh/tc.func.c line 531, 537, 566, 572, 603, 616
- in /usr/src/bin/tcsh/tw.help.c line 93

alrmcatch defined in line 489; never used
auto_logout defined in line 473; used 2 times

- in line 497-502(2)

con_jobs defined in line 831; never used
cwd_cmd defined in line 553; used 2 times

- in line 700
- in /usr/src/bin/tcsh/tc.func.c line 700

do_aliases defined in line 1145; never used
doechotc defined in line 329; never used
dolist defined in line 175; never used
dosettc defined in line 338; never used
dotelltc defined in line 318; never used
dowhich defined in line 361; never used
expand_lex defined in line 77; used 7 times

- in line 137
- in /usr/src/bin/tcsh/ed.chared.c line 277-286(3), 292, 391-394(2)

fg_proc_entry defined in line 436; never used
find_stop_ed defined in line 395; never used
gettilde defined in line 1058; used 1 times

- in /usr/src/bin/tcsh/sh.c line 1621

getusername defined in line 1117; used 1 times

- in /usr/src/bin/tcsh/tc.prompt.c line 186

inlist defined in line 1003; used 2 times

- in line 865-866(2)

insert defined in line 904; used 1 times

- in line 882

insert_we defined in line 992; used 6 times

- in line 929, 937-942(2), 955-960(2), 968

period_cmd defined in line 588; used 2 times

- in line 702
- in /usr/src/bin/tcsh/tc.func.c line 702

precmd defined in line 518; used 2 times

- in line 689
- in /usr/src/bin/tcsh/tc.func.c line 689

rcsid defined in line 39; never used
rmstar defined in line 734; never used
setalarm defined in line 711; used 2 times

- in line 503
- in /usr/src/bin/tcsh/tc.func.c line 503

sprlex defined in line 130; used 7 times

- in /usr/src/bin/tcsh/ed.chared.c line 748, 800, 861, 944, 966, 1004, 1036

tildecompare defined in line 1051; used 1 times

- in line 1100

#### Defined variables

cwdcmd_active defined in line 51; used 4 times

- in line 565-574(3), 699

d_tell defined in line 315; used 1 times

- in line 326

periodic_active defined in line 50; used 4 times

- in line 602-607(2), 620, 701

precmd_active defined in line 49; used 4 times

- in line 530-539(3), 688

tcache defined in line 1046; used 13 times

- in line 1065-1071(4), 1095-1104(6), 1131-1134(3)

tlength defined in line 1049; used 7 times

- in line 1071, 1095-1102(5), 1130

#### Defined struct's

tildecache defined in line 1042; used 14 times

- in line 1053(2), 1062-1067(6), 1099-1106(6)

#### Defined macros

CNDEBUG defined in line 830; used 5 times

- in line 839, 848, 860, 868, 891

RMDEBUG defined in line 732; used 4 times

- in line 741, 753, 760, 816

TILINCR defined in line 1048; used 3 times

- in line 1049, 1066, 1103

Last modified: 1991-08-21 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 2706 |