1: #
   2: 
   3: #include "rcv.h"
   4: #include <sys/stat.h>
   5: 
   6: /*
   7:  * Mail -- a mail program
   8:  *
   9:  * Still more user commands.
  10:  */
  11: 
  12: static char *SccsId = "@(#)cmd3.c	2.13 6/28/83";
  13: 
  14: /*
  15:  * Process a shell escape by saving signals, ignoring signals,
  16:  * and forking a sh -c
  17:  */
  18: 
  19: shell(str)
  20:     char *str;
  21: {
  22:     int (*sig[2])(), stat[1];
  23:     register int t;
  24:     char *Shell;
  25:     char cmd[BUFSIZ];
  26: 
  27:     strcpy(cmd, str);
  28:     if (bangexp(cmd) < 0)
  29:         return(-1);
  30:     if ((Shell = value("SHELL")) == NOSTR)
  31:         Shell = SHELL;
  32:     for (t = 2; t < 4; t++)
  33:         sig[t-2] = sigset(t, SIG_IGN);
  34:     t = vfork();
  35:     if (t == 0) {
  36:         sigchild();
  37:         for (t = 2; t < 4; t++)
  38:             if (sig[t-2] != SIG_IGN)
  39:                 sigsys(t, SIG_DFL);
  40:         execl(Shell, Shell, "-c", cmd, 0);
  41:         perror(Shell);
  42:         _exit(1);
  43:     }
  44:     while (wait(stat) != t)
  45:         ;
  46:     if (t == -1)
  47:         perror("fork");
  48:     for (t = 2; t < 4; t++)
  49:         sigset(t, sig[t-2]);
  50:     printf("!\n");
  51:     return(0);
  52: }
  53: 
  54: /*
  55:  * Fork an interactive shell.
  56:  */
  57: 
  58: dosh(str)
  59:     char *str;
  60: {
  61:     int (*sig[2])(), stat[1];
  62:     register int t;
  63:     char *Shell;
  64:     if ((Shell = value("SHELL")) == NOSTR)
  65:         Shell = SHELL;
  66:     for (t = 2; t < 4; t++)
  67:         sig[t-2] = sigset(t, SIG_IGN);
  68:     t = vfork();
  69:     if (t == 0) {
  70:         sigchild();
  71:         for (t = 2; t < 4; t++)
  72:             if (sig[t-2] != SIG_IGN)
  73:                 sigsys(t, SIG_DFL);
  74:         execl(Shell, Shell, 0);
  75:         perror(Shell);
  76:         _exit(1);
  77:     }
  78:     while (wait(stat) != t)
  79:         ;
  80:     if (t == -1)
  81:         perror("fork");
  82:     for (t = 2; t < 4; t++)
  83:         sigsys(t, sig[t-2]);
  84:     putchar('\n');
  85:     return(0);
  86: }
  87: 
  88: /*
  89:  * Expand the shell escape by expanding unescaped !'s into the
  90:  * last issued command where possible.
  91:  */
  92: 
  93: char    lastbang[128];
  94: 
  95: bangexp(str)
  96:     char *str;
  97: {
  98:     char bangbuf[BUFSIZ];
  99:     register char *cp, *cp2;
 100:     register int n;
 101:     int changed = 0;
 102: 
 103:     cp = str;
 104:     cp2 = bangbuf;
 105:     n = BUFSIZ;
 106:     while (*cp) {
 107:         if (*cp == '!') {
 108:             if (n < strlen(lastbang)) {
 109: overf:
 110:                 printf("Command buffer overflow\n");
 111:                 return(-1);
 112:             }
 113:             changed++;
 114:             strcpy(cp2, lastbang);
 115:             cp2 += strlen(lastbang);
 116:             n -= strlen(lastbang);
 117:             cp++;
 118:             continue;
 119:         }
 120:         if (*cp == '\\' && cp[1] == '!') {
 121:             if (--n <= 1)
 122:                 goto overf;
 123:             *cp2++ = '!';
 124:             cp += 2;
 125:             changed++;
 126:         }
 127:         if (--n <= 1)
 128:             goto overf;
 129:         *cp2++ = *cp++;
 130:     }
 131:     *cp2 = 0;
 132:     if (changed) {
 133:         printf("!%s\n", bangbuf);
 134:         fflush(stdout);
 135:     }
 136:     strcpy(str, bangbuf);
 137:     strncpy(lastbang, bangbuf, 128);
 138:     lastbang[127] = 0;
 139:     return(0);
 140: }
 141: 
 142: /*
 143:  * Print out a nice help message from some file or another.
 144:  */
 145: 
 146: help()
 147: {
 148:     register c;
 149:     register FILE *f;
 150: 
 151:     if ((f = fopen(HELPFILE, "r")) == NULL) {
 152:         perror(HELPFILE);
 153:         return(1);
 154:     }
 155:     while ((c = getc(f)) != EOF)
 156:         putchar(c);
 157:     fclose(f);
 158:     return(0);
 159: }
 160: 
 161: /*
 162:  * Change user's working directory.
 163:  */
 164: 
 165: schdir(str)
 166:     char *str;
 167: {
 168:     register char *cp;
 169: 
 170:     for (cp = str; *cp == ' '; cp++)
 171:         ;
 172:     if (*cp == '\0')
 173:         cp = homedir;
 174:     else
 175:         if ((cp = expand(cp)) == NOSTR)
 176:             return(1);
 177:     if (chdir(cp) < 0) {
 178:         perror(cp);
 179:         return(1);
 180:     }
 181:     return(0);
 182: }
 183: 
 184: /*
 185:  * Reply to a list of messages.  Extract each name from the
 186:  * message header and send them off to mail1()
 187:  */
 188: 
 189: respond(msgvec)
 190:     int *msgvec;
 191: {
 192:     struct message *mp;
 193:     char *cp, *cp2, *cp3, *rcv, *replyto;
 194:     char buf[2 * LINESIZE], **ap;
 195:     struct name *np;
 196:     struct header head;
 197: 
 198:     if (msgvec[1] != 0) {
 199:         printf("Sorry, can't reply to multiple messages at once\n");
 200:         return(1);
 201:     }
 202:     mp = &message[msgvec[0] - 1];
 203:     dot = mp;
 204:     rcv = NOSTR;
 205:     cp = skin(nameof(mp, 1));
 206:     if (cp != NOSTR)
 207:         rcv = cp;
 208:     cp = skin(hfield("from", mp));
 209:     if (cp != NOSTR)
 210:         rcv = cp;
 211:     replyto = skin(hfield("reply-to", mp));
 212:     strcpy(buf, "");
 213:     if (replyto != NOSTR)
 214:         strcpy(buf, replyto);
 215:     else {
 216:         cp = skin(hfield("to", mp));
 217:         if (cp != NOSTR)
 218:             strcpy(buf, cp);
 219:     }
 220:     np = elide(extract(buf, GTO));
 221:     /* rcv = rename(rcv); */
 222:     mapf(np, rcv);
 223:     /*
 224: 	 * Delete my name from the reply list,
 225: 	 * and with it, all my alternate names.
 226: 	 */
 227:     np = delname(np, myname, icequal);
 228:     if (altnames)
 229:         for (ap = altnames; *ap; ap++)
 230:             np = delname(np, *ap, icequal);
 231:     head.h_seq = 1;
 232:     cp = detract(np, 0);
 233:     if (cp != NOSTR && replyto == NOSTR) {
 234:         strcpy(buf, cp);
 235:         strcat(buf, " ");
 236:         strcat(buf, rcv);
 237:     }
 238:     else {
 239:         if (cp == NOSTR && replyto != NOSTR)
 240:             printf("Empty reply-to field -- replying to author\n");
 241:         if (cp == NOSTR)
 242:             strcpy(buf, rcv);
 243:         else
 244:             strcpy(buf, cp);
 245:     }
 246:     head.h_to = buf;
 247:     head.h_subject = hfield("subject", mp);
 248:     if (head.h_subject == NOSTR)
 249:         head.h_subject = hfield("subj", mp);
 250:     head.h_subject = reedit(head.h_subject);
 251:     head.h_cc = NOSTR;
 252:     if (replyto == NOSTR) {
 253:         cp = hfield("cc", mp);
 254:         if (cp != NOSTR) {
 255:             np = elide(extract(cp, GCC));
 256:             mapf(np, rcv);
 257:             np = delname(np, myname, icequal);
 258:             if (altnames != 0)
 259:                 for (ap = altnames; *ap; ap++)
 260:                     np = delname(np, *ap, icequal);
 261:             head.h_cc = detract(np, 0);
 262:         }
 263:     }
 264:     head.h_bcc = NOSTR;
 265:     mail1(&head);
 266:     return(0);
 267: }
 268: 
 269: /*
 270:  * Modify the subject we are replying to to begin with Re: if
 271:  * it does not already.
 272:  */
 273: 
 274: char *
 275: reedit(subj)
 276:     char *subj;
 277: {
 278:     char sbuf[10];
 279:     register char *newsubj;
 280: 
 281:     if (subj == NOSTR)
 282:         return(NOSTR);
 283:     strncpy(sbuf, subj, 3);
 284:     sbuf[3] = 0;
 285:     if (icequal(sbuf, "re:"))
 286:         return(subj);
 287:     newsubj = salloc(strlen(subj) + 6);
 288:     sprintf(newsubj, "Re:  %s", subj);
 289:     return(newsubj);
 290: }
 291: 
 292: /*
 293:  * Preserve the named messages, so that they will be sent
 294:  * back to the system mailbox.
 295:  */
 296: 
 297: preserve(msgvec)
 298:     int *msgvec;
 299: {
 300:     register struct message *mp;
 301:     register int *ip, mesg;
 302: 
 303:     if (edit) {
 304:         printf("Cannot \"preserve\" in edit mode\n");
 305:         return(1);
 306:     }
 307:     for (ip = msgvec; *ip != NULL; ip++) {
 308:         mesg = *ip;
 309:         mp = &message[mesg-1];
 310:         mp->m_flag |= MPRESERVE;
 311:         mp->m_flag &= ~MBOX;
 312:         dot = mp;
 313:     }
 314:     return(0);
 315: }
 316: 
 317: /*
 318:  * Print the size of each message.
 319:  */
 320: 
 321: messize(msgvec)
 322:     int *msgvec;
 323: {
 324:     register struct message *mp;
 325:     register int *ip, mesg;
 326: 
 327:     for (ip = msgvec; *ip != NULL; ip++) {
 328:         mesg = *ip;
 329:         mp = &message[mesg-1];
 330:         printf("%d: %ld\n", mesg, mp->m_size);
 331:     }
 332:     return(0);
 333: }
 334: 
 335: /*
 336:  * Quit quickly.  If we are sourcing, just pop the input level
 337:  * by returning an error.
 338:  */
 339: 
 340: rexit(e)
 341: {
 342:     if (sourcing)
 343:         return(1);
 344:     if (Tflag != NOSTR)
 345:         close(creat(Tflag, 0600));
 346:     exit(e);
 347: }
 348: 
 349: /*
 350:  * Set or display a variable value.  Syntax is similar to that
 351:  * of csh.
 352:  */
 353: 
 354: set(arglist)
 355:     char **arglist;
 356: {
 357:     register struct var *vp;
 358:     register char *cp, *cp2;
 359:     char varbuf[BUFSIZ], **ap, **p;
 360:     int errs, h, s;
 361: 
 362:     if (argcount(arglist) == 0) {
 363:         for (h = 0, s = 1; h < HSHSIZE; h++)
 364:             for (vp = variables[h]; vp != NOVAR; vp = vp->v_link)
 365:                 s++;
 366:         ap = (char **) salloc(s * sizeof *ap);
 367:         for (h = 0, p = ap; h < HSHSIZE; h++)
 368:             for (vp = variables[h]; vp != NOVAR; vp = vp->v_link)
 369:                 *p++ = vp->v_name;
 370:         *p = NOSTR;
 371:         sort(ap);
 372:         for (p = ap; *p != NOSTR; p++)
 373:             printf("%s\t%s\n", *p, value(*p));
 374:         return(0);
 375:     }
 376:     errs = 0;
 377:     for (ap = arglist; *ap != NOSTR; ap++) {
 378:         cp = *ap;
 379:         cp2 = varbuf;
 380:         while (*cp != '=' && *cp != '\0')
 381:             *cp2++ = *cp++;
 382:         *cp2 = '\0';
 383:         if (*cp == '\0')
 384:             cp = "";
 385:         else
 386:             cp++;
 387:         if (equal(varbuf, "")) {
 388:             printf("Non-null variable name required\n");
 389:             errs++;
 390:             continue;
 391:         }
 392:         assign(varbuf, cp);
 393:     }
 394:     return(errs);
 395: }
 396: 
 397: /*
 398:  * Unset a bunch of variable values.
 399:  */
 400: 
 401: unset(arglist)
 402:     char **arglist;
 403: {
 404:     register struct var *vp, *vp2;
 405:     register char *cp;
 406:     int errs, h;
 407:     char **ap;
 408: 
 409:     errs = 0;
 410:     for (ap = arglist; *ap != NOSTR; ap++) {
 411:         if ((vp2 = lookup(*ap)) == NOVAR) {
 412:             if (!sourcing) {
 413:                 printf("\"%s\": undefined variable\n", *ap);
 414:                 errs++;
 415:             }
 416:             continue;
 417:         }
 418:         h = hash(*ap);
 419:         if (vp2 == variables[h]) {
 420:             variables[h] = variables[h]->v_link;
 421:             vfree(vp2->v_name);
 422:             vfree(vp2->v_value);
 423:             cfree(vp2);
 424:             continue;
 425:         }
 426:         for (vp = variables[h]; vp->v_link != vp2; vp = vp->v_link)
 427:             ;
 428:         vp->v_link = vp2->v_link;
 429:         vfree(vp2->v_name);
 430:         vfree(vp2->v_value);
 431:         cfree(vp2);
 432:     }
 433:     return(errs);
 434: }
 435: 
 436: /*
 437:  * Put add users to a group.
 438:  */
 439: 
 440: group(argv)
 441:     char **argv;
 442: {
 443:     register struct grouphead *gh;
 444:     register struct group *gp;
 445:     register int h;
 446:     int s;
 447:     char **ap, *gname, **p;
 448: 
 449:     if (argcount(argv) == 0) {
 450:         for (h = 0, s = 1; h < HSHSIZE; h++)
 451:             for (gh = groups[h]; gh != NOGRP; gh = gh->g_link)
 452:                 s++;
 453:         ap = (char **) salloc(s * sizeof *ap);
 454:         for (h = 0, p = ap; h < HSHSIZE; h++)
 455:             for (gh = groups[h]; gh != NOGRP; gh = gh->g_link)
 456:                 *p++ = gh->g_name;
 457:         *p = NOSTR;
 458:         sort(ap);
 459:         for (p = ap; *p != NOSTR; p++)
 460:             printgroup(*p);
 461:         return(0);
 462:     }
 463:     if (argcount(argv) == 1) {
 464:         printgroup(*argv);
 465:         return(0);
 466:     }
 467:     gname = *argv;
 468:     h = hash(gname);
 469:     if ((gh = findgroup(gname)) == NOGRP) {
 470:         gh = (struct grouphead *) calloc(sizeof *gh, 1);
 471:         gh->g_name = vcopy(gname);
 472:         gh->g_list = NOGE;
 473:         gh->g_link = groups[h];
 474:         groups[h] = gh;
 475:     }
 476: 
 477:     /*
 478: 	 * Insert names from the command list into the group.
 479: 	 * Who cares if there are duplicates?  They get tossed
 480: 	 * later anyway.
 481: 	 */
 482: 
 483:     for (ap = argv+1; *ap != NOSTR; ap++) {
 484:         gp = (struct group *) calloc(sizeof *gp, 1);
 485:         gp->ge_name = vcopy(*ap);
 486:         gp->ge_link = gh->g_list;
 487:         gh->g_list = gp;
 488:     }
 489:     return(0);
 490: }
 491: 
 492: /*
 493:  * Sort the passed string vecotor into ascending dictionary
 494:  * order.
 495:  */
 496: 
 497: sort(list)
 498:     char **list;
 499: {
 500:     register char **ap;
 501:     int diction();
 502: 
 503:     for (ap = list; *ap != NOSTR; ap++)
 504:         ;
 505:     if (ap-list < 2)
 506:         return;
 507:     qsort(list, ap-list, sizeof *list, diction);
 508: }
 509: 
 510: /*
 511:  * Do a dictionary order comparison of the arguments from
 512:  * qsort.
 513:  */
 514: 
 515: diction(a, b)
 516:     register char **a, **b;
 517: {
 518:     return(strcmp(*a, *b));
 519: }
 520: 
 521: /*
 522:  * The do nothing command for comments.
 523:  */
 524: 
 525: null(e)
 526: {
 527:     return(0);
 528: }
 529: 
 530: /*
 531:  * Print out the current edit file, if we are editing.
 532:  * Otherwise, print the name of the person who's mail
 533:  * we are reading.
 534:  */
 535: 
 536: file(argv)
 537:     char **argv;
 538: {
 539:     register char *cp;
 540:     char fname[BUFSIZ];
 541:     int edit;
 542: 
 543:     if (argv[0] == NOSTR) {
 544:         newfileinfo();
 545:         return(0);
 546:     }
 547: 
 548:     /*
 549: 	 * Acker's!  Must switch to the new file.
 550: 	 * We use a funny interpretation --
 551: 	 *	# -- gets the previous file
 552: 	 *	% -- gets the invoker's post office box
 553: 	 *	%user -- gets someone else's post office box
 554: 	 *	& -- gets invoker's mbox file
 555: 	 *	string -- reads the given file
 556: 	 */
 557: 
 558:     cp = getfilename(argv[0], &edit);
 559:     if (cp == NOSTR)
 560:         return(-1);
 561:     if (setfile(cp, edit)) {
 562:         perror(cp);
 563:         return(-1);
 564:     }
 565:     newfileinfo();
 566: }
 567: 
 568: /*
 569:  * Evaluate the string given as a new mailbox name.
 570:  * Ultimately, we want this to support a number of meta characters.
 571:  * Possibly:
 572:  *	% -- for my system mail box
 573:  *	%user -- for user's system mail box
 574:  *	# -- for previous file
 575:  *	& -- get's invoker's mbox file
 576:  *	file name -- for any other file
 577:  */
 578: 
 579: char    prevfile[PATHSIZE];
 580: 
 581: char *
 582: getfilename(name, aedit)
 583:     char *name;
 584:     int *aedit;
 585: {
 586:     register char *cp;
 587:     char savename[BUFSIZ];
 588:     char oldmailname[BUFSIZ];
 589: 
 590:     /*
 591: 	 * Assume we will be in "edit file" mode, until
 592: 	 * proven wrong.
 593: 	 */
 594:     *aedit = 1;
 595:     switch (*name) {
 596:     case '%':
 597:         *aedit = 0;
 598:         strcpy(prevfile, mailname);
 599:         if (name[1] != 0) {
 600:             strcpy(savename, myname);
 601:             strcpy(oldmailname, mailname);
 602:             strncpy(myname, name+1, PATHSIZE-1);
 603:             myname[PATHSIZE-1] = 0;
 604:             findmail();
 605:             cp = savestr(mailname);
 606:             strcpy(myname, savename);
 607:             strcpy(mailname, oldmailname);
 608:             return(cp);
 609:         }
 610:         strcpy(oldmailname, mailname);
 611:         findmail();
 612:         cp = savestr(mailname);
 613:         strcpy(mailname, oldmailname);
 614:         return(cp);
 615: 
 616:     case '#':
 617:         if (name[1] != 0)
 618:             goto regular;
 619:         if (prevfile[0] == 0) {
 620:             printf("No previous file\n");
 621:             return(NOSTR);
 622:         }
 623:         cp = savestr(prevfile);
 624:         strcpy(prevfile, mailname);
 625:         return(cp);
 626: 
 627:     case '&':
 628:         strcpy(prevfile, mailname);
 629:         if (name[1] == 0)
 630:             return(mbox);
 631:         /* Fall into . . . */
 632: 
 633:     default:
 634: regular:
 635:         strcpy(prevfile, mailname);
 636:         cp = expand(name);
 637:         return(cp);
 638:     }
 639: }
 640: 
 641: /*
 642:  * Expand file names like echo
 643:  */
 644: 
 645: echo(argv)
 646:     char **argv;
 647: {
 648:     register char **ap;
 649:     register char *cp;
 650: 
 651:     for (ap = argv; *ap != NOSTR; ap++) {
 652:         cp = *ap;
 653:         if ((cp = expand(cp)) != NOSTR)
 654:             printf("%s ", cp);
 655:     }
 656:     return(0);
 657: }
 658: 
 659: /*
 660:  * Reply to a series of messages by simply mailing to the senders
 661:  * and not messing around with the To: and Cc: lists as in normal
 662:  * reply.
 663:  */
 664: 
 665: Respond(msgvec)
 666:     int msgvec[];
 667: {
 668:     struct header head;
 669:     struct message *mp;
 670:     register int s, *ap;
 671:     register char *cp, *cp2, *subject;
 672: 
 673:     for (s = 0, ap = msgvec; *ap != 0; ap++) {
 674:         mp = &message[*ap - 1];
 675:         dot = mp;
 676:         if ((cp = skin(hfield("from", mp))) != NOSTR)
 677:             s+= strlen(cp) + 1;
 678:         else
 679:             s += strlen(skin(nameof(mp, 2))) + 1;
 680:     }
 681:     if (s == 0)
 682:         return(0);
 683:     cp = salloc(s + 2);
 684:     head.h_to = cp;
 685:     for (ap = msgvec; *ap != 0; ap++) {
 686:         mp = &message[*ap - 1];
 687:         if ((cp2 = skin(hfield("from", mp))) == NOSTR)
 688:             cp2 = skin(nameof(mp, 2));
 689:         cp = copy(cp2, cp);
 690:         *cp++ = ' ';
 691:     }
 692:     *--cp = 0;
 693:     mp = &message[msgvec[0] - 1];
 694:     subject = hfield("subject", mp);
 695:     head.h_seq = 0;
 696:     if (subject == NOSTR)
 697:         subject = hfield("subj", mp);
 698:     head.h_subject = reedit(subject);
 699:     if (subject != NOSTR)
 700:         head.h_seq++;
 701:     head.h_cc = NOSTR;
 702:     head.h_bcc = NOSTR;
 703:     mail1(&head);
 704:     return(0);
 705: }
 706: 
 707: /*
 708:  * Conditional commands.  These allow one to parameterize one's
 709:  * .mailrc and do some things if sending, others if receiving.
 710:  */
 711: 
 712: ifcmd(argv)
 713:     char **argv;
 714: {
 715:     register char *cp;
 716: 
 717:     if (cond != CANY) {
 718:         printf("Illegal nested \"if\"\n");
 719:         return(1);
 720:     }
 721:     cond = CANY;
 722:     cp = argv[0];
 723:     switch (*cp) {
 724:     case 'r': case 'R':
 725:         cond = CRCV;
 726:         break;
 727: 
 728:     case 's': case 'S':
 729:         cond = CSEND;
 730:         break;
 731: 
 732:     default:
 733:         printf("Unrecognized if-keyword: \"%s\"\n", cp);
 734:         return(1);
 735:     }
 736:     return(0);
 737: }
 738: 
 739: /*
 740:  * Implement 'else'.  This is pretty simple -- we just
 741:  * flip over the conditional flag.
 742:  */
 743: 
 744: elsecmd()
 745: {
 746: 
 747:     switch (cond) {
 748:     case CANY:
 749:         printf("\"Else\" without matching \"if\"\n");
 750:         return(1);
 751: 
 752:     case CSEND:
 753:         cond = CRCV;
 754:         break;
 755: 
 756:     case CRCV:
 757:         cond = CSEND;
 758:         break;
 759: 
 760:     default:
 761:         printf("Mail's idea of conditions is screwed up\n");
 762:         cond = CANY;
 763:         break;
 764:     }
 765:     return(0);
 766: }
 767: 
 768: /*
 769:  * End of if statement.  Just set cond back to anything.
 770:  */
 771: 
 772: endifcmd()
 773: {
 774: 
 775:     if (cond == CANY) {
 776:         printf("\"Endif\" without matching \"if\"\n");
 777:         return(1);
 778:     }
 779:     cond = CANY;
 780:     return(0);
 781: }
 782: 
 783: /*
 784:  * Set the list of alternate names.
 785:  */
 786: alternates(namelist)
 787:     char **namelist;
 788: {
 789:     register int c;
 790:     register char **ap, **ap2, *cp;
 791: 
 792:     c = argcount(namelist) + 1;
 793:     if (c == 1) {
 794:         if (altnames == 0)
 795:             return(0);
 796:         for (ap = altnames; *ap; ap++)
 797:             printf("%s ", *ap);
 798:         printf("\n");
 799:         return(0);
 800:     }
 801:     if (altnames != 0)
 802:         cfree((char *) altnames);
 803:     altnames = (char **) calloc(c, sizeof (char *));
 804:     for (ap = namelist, ap2 = altnames; *ap; ap++, ap2++) {
 805:         cp = (char *) calloc(strlen(*ap) + 1, sizeof (char));
 806:         strcpy(cp, *ap);
 807:         *ap2 = cp;
 808:     }
 809:     *ap2 = 0;
 810:     return(0);
 811: }

Defined functions

Respond defined in line 665; used 3 times
alternates defined in line 786; used 2 times
bangexp defined in line 95; used 1 times
  • in line 28
diction defined in line 515; used 2 times
dosh defined in line 58; used 2 times
echo defined in line 645; used 2 times
elsecmd defined in line 744; used 2 times
endifcmd defined in line 772; used 2 times
file defined in line 536; used 3 times
getfilename defined in line 581; used 2 times
group defined in line 440; used 3 times
help defined in line 146; used 3 times
ifcmd defined in line 712; used 2 times
messize defined in line 321; used 2 times
null defined in line 525; used 2 times
preserve defined in line 297; used 3 times
reedit defined in line 274; used 3 times
respond defined in line 189; used 3 times
rexit defined in line 340; used 3 times
schdir defined in line 165; used 3 times
set defined in line 354; used 2 times
shell defined in line 19; used 4 times
sort defined in line 497; used 2 times
unset defined in line 401; used 2 times

Defined variables

SccsId defined in line 12; never used
lastbang defined in line 93; used 6 times
prevfile defined in line 579; used 6 times
Last modified: 1983-07-08
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1877
Valid CSS Valid XHTML 1.0 Strict