Annotation of src/usr.bin/mail/cmd3.c, Revision 1.13
1.13 ! millert 1: /* $OpenBSD: cmd3.c,v 1.12 2000/06/30 16:00:16 millert Exp $ */
1.5 millert 2: /* $NetBSD: cmd3.c,v 1.8 1997/07/09 05:29:49 mikel Exp $ */
1.2 deraadt 3:
1.1 deraadt 4: /*
5: * Copyright (c) 1980, 1993
6: * The Regents of the University of California. All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. All advertising materials mentioning features or use of this software
17: * must display the following acknowledgement:
18: * This product includes software developed by the University of
19: * California, Berkeley and its contributors.
20: * 4. Neither the name of the University nor the names of its contributors
21: * may be used to endorse or promote products derived from this software
22: * without specific prior written permission.
23: *
24: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34: * SUCH DAMAGE.
35: */
36:
37: #ifndef lint
1.2 deraadt 38: #if 0
1.5 millert 39: static char sccsid[] = "@(#)cmd3.c 8.2 (Berkeley) 4/20/95";
1.2 deraadt 40: #else
1.13 ! millert 41: static char rcsid[] = "$OpenBSD: cmd3.c,v 1.12 2000/06/30 16:00:16 millert Exp $";
1.2 deraadt 42: #endif
1.1 deraadt 43: #endif /* not lint */
44:
45: #include "rcv.h"
46: #include "extern.h"
47:
48: /*
49: * Mail -- a mail program
50: *
51: * Still more user commands.
52: */
1.2 deraadt 53: static int diction __P((const void *, const void *));
1.1 deraadt 54:
55: /*
56: * Process a shell escape by saving signals, ignoring signals,
57: * and forking a sh -c
58: */
59: int
1.2 deraadt 60: shell(v)
61: void *v;
1.1 deraadt 62: {
1.2 deraadt 63: char *str = v;
1.1 deraadt 64: sig_t sigint = signal(SIGINT, SIG_IGN);
65: char *shell;
66: char cmd[BUFSIZ];
67:
1.8 millert 68: (void)strncpy(cmd, str, sizeof(cmd) - 1);
69: cmd[sizeof(cmd) - 1] = '\0';
70: if (bangexp(cmd, sizeof(cmd)) < 0)
1.5 millert 71: return(1);
1.7 millert 72: if ((shell = value("SHELL")) == NULL)
1.1 deraadt 73: shell = _PATH_CSHELL;
1.7 millert 74: (void)run_command(shell, 0, -1, -1, "-c", cmd, NULL);
1.6 millert 75: (void)signal(SIGINT, sigint);
1.5 millert 76: puts("!");
77: return(0);
1.1 deraadt 78: }
79:
80: /*
81: * Fork an interactive shell.
82: */
83: /*ARGSUSED*/
84: int
1.2 deraadt 85: dosh(v)
86: void *v;
1.1 deraadt 87: {
88: sig_t sigint = signal(SIGINT, SIG_IGN);
89: char *shell;
90:
1.7 millert 91: if ((shell = value("SHELL")) == NULL)
1.1 deraadt 92: shell = _PATH_CSHELL;
1.7 millert 93: (void)run_command(shell, 0, -1, -1, NULL, NULL, NULL);
1.6 millert 94: (void)signal(SIGINT, sigint);
1.1 deraadt 95: putchar('\n');
1.5 millert 96: return(0);
1.1 deraadt 97: }
98:
99: /*
100: * Expand the shell escape by expanding unescaped !'s into the
101: * last issued command where possible.
102: */
103: int
1.8 millert 104: bangexp(str, strsize)
1.1 deraadt 105: char *str;
1.8 millert 106: size_t strsize;
1.1 deraadt 107: {
108: char bangbuf[BUFSIZ];
1.8 millert 109: static char lastbang[BUFSIZ];
1.10 millert 110: char *cp, *cp2;
111: int n, changed = 0;
1.1 deraadt 112:
113: cp = str;
114: cp2 = bangbuf;
115: n = BUFSIZ;
116: while (*cp) {
117: if (*cp == '!') {
118: if (n < strlen(lastbang)) {
119: overf:
1.5 millert 120: puts("Command buffer overflow");
1.1 deraadt 121: return(-1);
122: }
123: changed++;
1.9 millert 124: strncpy(cp2, lastbang, sizeof(bangbuf) - (cp2 - bangbuf) - 1);
125: bangbuf[sizeof(bangbuf) - 1] = '\0';
1.1 deraadt 126: cp2 += strlen(lastbang);
127: n -= strlen(lastbang);
128: cp++;
129: continue;
130: }
131: if (*cp == '\\' && cp[1] == '!') {
132: if (--n <= 1)
133: goto overf;
134: *cp2++ = '!';
135: cp += 2;
136: changed++;
137: }
138: if (--n <= 1)
139: goto overf;
140: *cp2++ = *cp++;
141: }
142: *cp2 = 0;
143: if (changed) {
1.8 millert 144: (void)printf("!%s\n", bangbuf);
145: (void)fflush(stdout);
1.1 deraadt 146: }
1.8 millert 147: (void)strncpy(str, bangbuf, strsize - 1);
148: str[strsize - 1] = '\0';
149: (void)strncpy(lastbang, bangbuf, sizeof(lastbang) - 1);
1.5 millert 150: lastbang[sizeof(lastbang) - 1] = '\0';
1.1 deraadt 151: return(0);
152: }
153:
154: /*
155: * Print out a nice help message from some file or another.
156: */
157:
158: int
1.2 deraadt 159: help(v)
160: void *v;
1.1 deraadt 161: {
1.10 millert 162: int c;
163: FILE *f;
1.1 deraadt 164:
165: if ((f = Fopen(_PATH_HELP, "r")) == NULL) {
1.5 millert 166: warn(_PATH_HELP);
1.1 deraadt 167: return(1);
168: }
169: while ((c = getc(f)) != EOF)
170: putchar(c);
1.5 millert 171: (void)Fclose(f);
1.1 deraadt 172: return(0);
173: }
174:
175: /*
176: * Change user's working directory.
177: */
178: int
1.2 deraadt 179: schdir(v)
180: void *v;
1.1 deraadt 181: {
1.2 deraadt 182: char **arglist = v;
1.1 deraadt 183: char *cp;
184:
1.13 ! millert 185: if (*arglist == NULL) {
! 186: if (homedir == NULL)
! 187: return(1);
1.1 deraadt 188: cp = homedir;
1.13 ! millert 189: } else {
1.7 millert 190: if ((cp = expand(*arglist)) == NULL)
1.1 deraadt 191: return(1);
1.13 ! millert 192: }
1.1 deraadt 193: if (chdir(cp) < 0) {
1.12 millert 194: warn("%s", cp);
1.1 deraadt 195: return(1);
196: }
1.5 millert 197: return(0);
1.1 deraadt 198: }
199:
200: int
1.2 deraadt 201: respond(v)
202: void *v;
1.1 deraadt 203: {
1.2 deraadt 204: int *msgvec = v;
1.7 millert 205: if (value("Replyall") == NULL)
1.5 millert 206: return(_respond(msgvec));
1.1 deraadt 207: else
1.5 millert 208: return(_Respond(msgvec));
1.1 deraadt 209: }
210:
211: /*
212: * Reply to a list of messages. Extract each name from the
213: * message header and send them off to mail1()
214: */
215: int
216: _respond(msgvec)
217: int *msgvec;
218: {
219: struct message *mp;
220: char *cp, *rcv, *replyto;
221: char **ap;
222: struct name *np;
223: struct header head;
224:
225: if (msgvec[1] != 0) {
1.5 millert 226: puts("Sorry, can't reply to multiple messages at once");
1.1 deraadt 227: return(1);
228: }
229: mp = &message[msgvec[0] - 1];
230: touch(mp);
231: dot = mp;
1.7 millert 232: if ((rcv = skin(hfield("from", mp))) == NULL)
1.1 deraadt 233: rcv = skin(nameof(mp, 1));
1.7 millert 234: if ((replyto = skin(hfield("reply-to", mp))) != NULL)
1.1 deraadt 235: np = extract(replyto, GTO);
1.7 millert 236: else if ((cp = skin(hfield("to", mp))) != NULL)
1.1 deraadt 237: np = extract(cp, GTO);
238: else
239: np = NIL;
240: np = elide(np);
241: /*
242: * Delete my name from the reply list,
243: * and with it, all my alternate names.
244: */
245: np = delname(np, myname);
246: if (altnames)
247: for (ap = altnames; *ap; ap++)
248: np = delname(np, *ap);
1.7 millert 249: if (np != NIL && replyto == NULL)
1.1 deraadt 250: np = cat(np, extract(rcv, GTO));
251: else if (np == NIL) {
1.7 millert 252: if (replyto != NULL)
1.5 millert 253: puts("Empty reply-to field -- replying to author");
1.1 deraadt 254: np = extract(rcv, GTO);
255: }
256: head.h_to = np;
1.7 millert 257: if ((head.h_subject = hfield("subject", mp)) == NULL)
1.1 deraadt 258: head.h_subject = hfield("subj", mp);
259: head.h_subject = reedit(head.h_subject);
1.7 millert 260: if (replyto == NULL && (cp = skin(hfield("cc", mp))) != NULL) {
1.1 deraadt 261: np = elide(extract(cp, GCC));
262: np = delname(np, myname);
263: if (altnames != 0)
264: for (ap = altnames; *ap; ap++)
265: np = delname(np, *ap);
266: head.h_cc = np;
267: } else
268: head.h_cc = NIL;
269: head.h_bcc = NIL;
270: head.h_smopts = NIL;
271: mail1(&head, 1);
272: return(0);
273: }
274:
275: /*
276: * Modify the subject we are replying to to begin with Re: if
277: * it does not already.
278: */
279: char *
280: reedit(subj)
1.10 millert 281: char *subj;
1.1 deraadt 282: {
283: char *newsubj;
284:
1.7 millert 285: if (subj == NULL)
286: return(NULL);
1.1 deraadt 287: if ((subj[0] == 'r' || subj[0] == 'R') &&
288: (subj[1] == 'e' || subj[1] == 'E') &&
289: subj[2] == ':')
1.5 millert 290: return(subj);
1.1 deraadt 291: newsubj = salloc(strlen(subj) + 5);
292: strcpy(newsubj, "Re: ");
293: strcpy(newsubj + 4, subj);
1.5 millert 294: return(newsubj);
1.1 deraadt 295: }
296:
297: /*
298: * Preserve the named messages, so that they will be sent
299: * back to the system mailbox.
300: */
301: int
1.2 deraadt 302: preserve(v)
303: void *v;
1.1 deraadt 304: {
1.2 deraadt 305: int *msgvec = v;
1.10 millert 306: int *ip, mesg;
307: struct message *mp;
1.1 deraadt 308:
309: if (edit) {
1.5 millert 310: puts("Cannot \"preserve\" in edit mode");
1.1 deraadt 311: return(1);
312: }
313: for (ip = msgvec; *ip != NULL; ip++) {
314: mesg = *ip;
315: mp = &message[mesg-1];
316: mp->m_flag |= MPRESERVE;
317: mp->m_flag &= ~MBOX;
318: dot = mp;
319: }
320: return(0);
321: }
322:
323: /*
324: * Mark all given messages as unread.
325: */
326: int
1.2 deraadt 327: unread(v)
328: void *v;
1.1 deraadt 329: {
1.2 deraadt 330: int *msgvec = v;
1.10 millert 331: int *ip;
1.1 deraadt 332:
333: for (ip = msgvec; *ip != NULL; ip++) {
334: dot = &message[*ip-1];
335: dot->m_flag &= ~(MREAD|MTOUCH);
336: dot->m_flag |= MSTATUS;
337: }
338: return(0);
339: }
340:
341: /*
342: * Print the size of each message.
343: */
344: int
1.2 deraadt 345: messize(v)
346: void *v;
1.1 deraadt 347: {
1.2 deraadt 348: int *msgvec = v;
1.10 millert 349: struct message *mp;
350: int *ip, mesg;
1.1 deraadt 351:
352: for (ip = msgvec; *ip != NULL; ip++) {
353: mesg = *ip;
354: mp = &message[mesg-1];
1.3 millert 355: printf("%d: %d/%d\n", mesg, mp->m_lines, mp->m_size);
1.1 deraadt 356: }
357: return(0);
358: }
359:
360: /*
361: * Quit quickly. If we are sourcing, just pop the input level
362: * by returning an error.
363: */
364: int
1.2 deraadt 365: rexit(v)
366: void *v;
1.1 deraadt 367: {
368: if (sourcing)
369: return(1);
1.2 deraadt 370: exit(0);
1.1 deraadt 371: /*NOTREACHED*/
372: }
373:
374: /*
375: * Set or display a variable value. Syntax is similar to that
376: * of csh.
377: */
378: int
1.2 deraadt 379: set(v)
380: void *v;
1.1 deraadt 381: {
1.2 deraadt 382: char **arglist = v;
1.10 millert 383: struct var *vp;
384: char *cp, *cp2;
1.1 deraadt 385: char varbuf[BUFSIZ], **ap, **p;
386: int errs, h, s;
387:
1.7 millert 388: if (*arglist == NULL) {
1.1 deraadt 389: for (h = 0, s = 1; h < HSHSIZE; h++)
390: for (vp = variables[h]; vp != NOVAR; vp = vp->v_link)
391: s++;
1.6 millert 392: ap = (char **)salloc(s * sizeof(*ap));
1.1 deraadt 393: for (h = 0, p = ap; h < HSHSIZE; h++)
394: for (vp = variables[h]; vp != NOVAR; vp = vp->v_link)
395: *p++ = vp->v_name;
1.7 millert 396: *p = NULL;
1.1 deraadt 397: sort(ap);
1.7 millert 398: for (p = ap; *p != NULL; p++)
1.1 deraadt 399: printf("%s\t%s\n", *p, value(*p));
400: return(0);
401: }
402: errs = 0;
1.7 millert 403: for (ap = arglist; *ap != NULL; ap++) {
1.1 deraadt 404: cp = *ap;
405: cp2 = varbuf;
406: while (*cp != '=' && *cp != '\0')
407: *cp2++ = *cp++;
408: *cp2 = '\0';
409: if (*cp == '\0')
410: cp = "";
411: else
412: cp++;
413: if (equal(varbuf, "")) {
1.5 millert 414: puts("Non-null variable name required");
1.1 deraadt 415: errs++;
416: continue;
417: }
418: assign(varbuf, cp);
419: }
420: return(errs);
421: }
422:
423: /*
424: * Unset a bunch of variable values.
425: */
426: int
1.2 deraadt 427: unset(v)
428: void *v;
1.1 deraadt 429: {
1.2 deraadt 430: char **arglist = v;
1.10 millert 431: struct var *vp, *vp2;
1.1 deraadt 432: int errs, h;
433: char **ap;
434:
435: errs = 0;
1.7 millert 436: for (ap = arglist; *ap != NULL; ap++) {
1.1 deraadt 437: if ((vp2 = lookup(*ap)) == NOVAR) {
438: if (!sourcing) {
439: printf("\"%s\": undefined variable\n", *ap);
440: errs++;
441: }
442: continue;
443: }
444: h = hash(*ap);
445: if (vp2 == variables[h]) {
446: variables[h] = variables[h]->v_link;
447: vfree(vp2->v_name);
448: vfree(vp2->v_value);
1.6 millert 449: (void)free(vp2);
1.1 deraadt 450: continue;
451: }
452: for (vp = variables[h]; vp->v_link != vp2; vp = vp->v_link)
453: ;
454: vp->v_link = vp2->v_link;
455: vfree(vp2->v_name);
456: vfree(vp2->v_value);
1.6 millert 457: (void)free(vp2);
1.1 deraadt 458: }
459: return(errs);
460: }
461:
462: /*
463: * Put add users to a group.
464: */
465: int
1.2 deraadt 466: group(v)
467: void *v;
1.1 deraadt 468: {
1.2 deraadt 469: char **argv = v;
1.10 millert 470: struct grouphead *gh;
471: struct group *gp;
1.1 deraadt 472: char **ap, *gname, **p;
1.10 millert 473: int h, s;
1.1 deraadt 474:
1.7 millert 475: if (*argv == NULL) {
1.1 deraadt 476: for (h = 0, s = 1; h < HSHSIZE; h++)
477: for (gh = groups[h]; gh != NOGRP; gh = gh->g_link)
478: s++;
1.6 millert 479: ap = (char **)salloc(s * sizeof(*ap));
1.1 deraadt 480: for (h = 0, p = ap; h < HSHSIZE; h++)
481: for (gh = groups[h]; gh != NOGRP; gh = gh->g_link)
482: *p++ = gh->g_name;
1.7 millert 483: *p = NULL;
1.1 deraadt 484: sort(ap);
1.7 millert 485: for (p = ap; *p != NULL; p++)
1.1 deraadt 486: printgroup(*p);
487: return(0);
488: }
1.7 millert 489: if (argv[1] == NULL) {
1.1 deraadt 490: printgroup(*argv);
491: return(0);
492: }
493: gname = *argv;
494: h = hash(gname);
495: if ((gh = findgroup(gname)) == NOGRP) {
1.6 millert 496: gh = (struct grouphead *)calloc(sizeof(*gh), 1);
1.1 deraadt 497: gh->g_name = vcopy(gname);
498: gh->g_list = NOGE;
499: gh->g_link = groups[h];
500: groups[h] = gh;
501: }
502:
503: /*
504: * Insert names from the command list into the group.
505: * Who cares if there are duplicates? They get tossed
506: * later anyway.
507: */
508:
1.7 millert 509: for (ap = argv+1; *ap != NULL; ap++) {
1.6 millert 510: gp = (struct group *)calloc(sizeof(*gp), 1);
1.1 deraadt 511: gp->ge_name = vcopy(*ap);
512: gp->ge_link = gh->g_list;
513: gh->g_list = gp;
514: }
515: return(0);
516: }
517:
518: /*
519: * Sort the passed string vecotor into ascending dictionary
520: * order.
521: */
522: void
523: sort(list)
524: char **list;
525: {
1.10 millert 526: char **ap;
1.1 deraadt 527:
1.7 millert 528: for (ap = list; *ap != NULL; ap++)
1.1 deraadt 529: ;
530: if (ap-list < 2)
531: return;
532: qsort(list, ap-list, sizeof(*list), diction);
533: }
534:
535: /*
536: * Do a dictionary order comparison of the arguments from
537: * qsort.
538: */
1.2 deraadt 539: static int
1.1 deraadt 540: diction(a, b)
541: const void *a, *b;
542: {
543: return(strcmp(*(char **)a, *(char **)b));
544: }
545:
546: /*
547: * The do nothing command for comments.
548: */
549:
550: /*ARGSUSED*/
551: int
1.2 deraadt 552: null(v)
553: void *v;
1.1 deraadt 554: {
1.5 millert 555: return(0);
1.1 deraadt 556: }
557:
558: /*
559: * Change to another file. With no argument, print information about
560: * the current file.
561: */
562: int
1.2 deraadt 563: file(v)
564: void *v;
1.1 deraadt 565: {
1.2 deraadt 566: char **argv = v;
1.1 deraadt 567:
1.7 millert 568: if (argv[0] == NULL) {
1.5 millert 569: newfileinfo(0);
1.11 millert 570: clearnew();
1.5 millert 571: return(0);
1.1 deraadt 572: }
573: if (setfile(*argv) < 0)
1.5 millert 574: return(1);
1.1 deraadt 575: announce();
1.5 millert 576: return(0);
1.1 deraadt 577: }
578:
579: /*
580: * Expand file names like echo
581: */
582: int
1.2 deraadt 583: echo(v)
584: void *v;
1.1 deraadt 585: {
1.2 deraadt 586: char **argv = v;
1.10 millert 587: char **ap, *cp;
1.1 deraadt 588:
1.7 millert 589: for (ap = argv; *ap != NULL; ap++) {
1.1 deraadt 590: cp = *ap;
1.7 millert 591: if ((cp = expand(cp)) != NULL) {
1.1 deraadt 592: if (ap != argv)
593: putchar(' ');
1.5 millert 594: fputs(cp, stdout);
1.1 deraadt 595: }
596: }
597: putchar('\n');
1.5 millert 598: return(0);
1.1 deraadt 599: }
600:
601: int
1.2 deraadt 602: Respond(v)
603: void *v;
1.1 deraadt 604: {
1.2 deraadt 605: int *msgvec = v;
1.7 millert 606: if (value("Replyall") == NULL)
1.5 millert 607: return(_Respond(msgvec));
1.1 deraadt 608: else
1.5 millert 609: return(_respond(msgvec));
1.1 deraadt 610: }
611:
612: /*
613: * Reply to a series of messages by simply mailing to the senders
614: * and not messing around with the To: and Cc: lists as in normal
615: * reply.
616: */
617: int
618: _Respond(msgvec)
619: int msgvec[];
620: {
621: struct header head;
622: struct message *mp;
1.10 millert 623: int *ap;
624: char *cp;
1.1 deraadt 625:
626: head.h_to = NIL;
627: for (ap = msgvec; *ap != 0; ap++) {
628: mp = &message[*ap - 1];
629: touch(mp);
630: dot = mp;
1.7 millert 631: if ((cp = skin(hfield("from", mp))) == NULL)
1.1 deraadt 632: cp = skin(nameof(mp, 2));
633: head.h_to = cat(head.h_to, extract(cp, GTO));
634: }
635: if (head.h_to == NIL)
1.5 millert 636: return(0);
1.1 deraadt 637: mp = &message[msgvec[0] - 1];
1.7 millert 638: if ((head.h_subject = hfield("subject", mp)) == NULL)
1.1 deraadt 639: head.h_subject = hfield("subj", mp);
640: head.h_subject = reedit(head.h_subject);
641: head.h_cc = NIL;
642: head.h_bcc = NIL;
643: head.h_smopts = NIL;
644: mail1(&head, 1);
1.5 millert 645: return(0);
1.1 deraadt 646: }
647:
648: /*
649: * Conditional commands. These allow one to parameterize one's
650: * .mailrc and do some things if sending, others if receiving.
651: */
652: int
1.2 deraadt 653: ifcmd(v)
654: void *v;
1.1 deraadt 655: {
1.2 deraadt 656: char **argv = v;
1.10 millert 657: char *cp;
1.1 deraadt 658:
659: if (cond != CANY) {
1.5 millert 660: puts("Illegal nested \"if\"");
1.1 deraadt 661: return(1);
662: }
663: cond = CANY;
664: cp = argv[0];
665: switch (*cp) {
666: case 'r': case 'R':
667: cond = CRCV;
668: break;
669:
670: case 's': case 'S':
671: cond = CSEND;
672: break;
673:
674: default:
675: printf("Unrecognized if-keyword: \"%s\"\n", cp);
676: return(1);
677: }
678: return(0);
679: }
680:
681: /*
682: * Implement 'else'. This is pretty simple -- we just
683: * flip over the conditional flag.
684: */
685: int
1.2 deraadt 686: elsecmd(v)
687: void *v;
1.1 deraadt 688: {
689:
690: switch (cond) {
691: case CANY:
1.5 millert 692: puts("\"Else\" without matching \"if\"");
1.1 deraadt 693: return(1);
694:
695: case CSEND:
696: cond = CRCV;
697: break;
698:
699: case CRCV:
700: cond = CSEND;
701: break;
702:
703: default:
1.5 millert 704: puts("mail's idea of conditions is screwed up");
1.1 deraadt 705: cond = CANY;
706: break;
707: }
708: return(0);
709: }
710:
711: /*
712: * End of if statement. Just set cond back to anything.
713: */
714: int
1.2 deraadt 715: endifcmd(v)
716: void *v;
1.1 deraadt 717: {
718:
719: if (cond == CANY) {
1.5 millert 720: puts("\"Endif\" without matching \"if\"");
1.1 deraadt 721: return(1);
722: }
723: cond = CANY;
724: return(0);
725: }
726:
727: /*
728: * Set the list of alternate names.
729: */
730: int
1.2 deraadt 731: alternates(v)
732: void *v;
1.1 deraadt 733: {
1.2 deraadt 734: char **namelist = v;
1.10 millert 735: char **ap, **ap2, *cp;
736: int c;
1.1 deraadt 737:
738: c = argcount(namelist) + 1;
739: if (c == 1) {
740: if (altnames == 0)
741: return(0);
742: for (ap = altnames; *ap; ap++)
743: printf("%s ", *ap);
1.5 millert 744: putchar('\n');
1.1 deraadt 745: return(0);
746: }
747: if (altnames != 0)
1.6 millert 748: (void)free(altnames);
749: altnames = (char **)calloc(c, sizeof(char *));
1.1 deraadt 750: for (ap = namelist, ap2 = altnames; *ap; ap++, ap2++) {
1.6 millert 751: cp = (char *)calloc(strlen(*ap) + 1, sizeof(char));
1.1 deraadt 752: strcpy(cp, *ap);
753: *ap2 = cp;
754: }
755: *ap2 = 0;
756: return(0);
757: }