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