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
Reverse defined in line 161; used 1 times
aliasrun defined in line 633; used 13 times
alrmcatch defined in line 489; never used
auto_logout defined in line 473; used 2 times
con_jobs defined in line 831; never used
cwd_cmd defined in line 553; used 2 times
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
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
getusername defined in line 1117; used 1 times
inlist defined in line 1003; used 2 times
insert defined in line 904; used 1 times
insert_we defined in line 992; used 6 times
period_cmd defined in line 588; used 2 times
precmd defined in line 518; used 2 times
rcsid defined in line 39; never used
rmstar defined in line 734; never used
setalarm defined in line 711; used 2 times
sprlex defined in line 130; used 7 times
tildecompare defined in line 1051; used 1 times

Defined variables

cwdcmd_active defined in line 51; used 4 times
d_tell defined in line 315; used 1 times
periodic_active defined in line 50; used 4 times
precmd_active defined in line 49; used 4 times
tcache defined in line 1046; used 13 times
tlength defined in line 1049; used 7 times

Defined struct's

tildecache defined in line 1042; used 14 times

Defined macros

CNDEBUG defined in line 830; used 5 times
RMDEBUG defined in line 732; used 4 times
TILINCR defined in line 1048; used 3 times
Last modified: 1991-08-21
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 6347
Valid CSS Valid XHTML 1.0 Strict