Annotation of src/usr.bin/mail/cmd3.c, Revision 1.27
1.27 ! mmcc 1: /* $OpenBSD: cmd3.c,v 1.26 2015/01/20 16:59:07 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.
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.26 millert 230: head.h_from = NULL;
1.7 millert 231: if ((head.h_subject = hfield("subject", mp)) == NULL)
1.1 deraadt 232: head.h_subject = hfield("subj", mp);
233: head.h_subject = reedit(head.h_subject);
1.7 millert 234: if (replyto == NULL && (cp = skin(hfield("cc", mp))) != NULL) {
1.1 deraadt 235: np = elide(extract(cp, GCC));
236: np = delname(np, myname);
237: if (altnames != 0)
238: for (ap = altnames; *ap; ap++)
239: np = delname(np, *ap);
240: head.h_cc = np;
241: } else
1.17 millert 242: head.h_cc = NULL;
243: head.h_bcc = NULL;
244: head.h_smopts = NULL;
1.1 deraadt 245: mail1(&head, 1);
246: return(0);
247: }
248:
249: /*
250: * Modify the subject we are replying to to begin with Re: if
251: * it does not already.
252: */
253: char *
1.17 millert 254: reedit(char *subj)
1.1 deraadt 255: {
256: char *newsubj;
1.18 millert 257: size_t len;
1.1 deraadt 258:
1.7 millert 259: if (subj == NULL)
260: return(NULL);
1.21 martynas 261: if (strncasecmp(subj, "re:", 3) == 0)
1.5 millert 262: return(subj);
1.18 millert 263: len = strlen(subj) + 5;
264: newsubj = salloc(len);
265: strlcpy(newsubj, "Re: ", len);
266: strlcat(newsubj, subj, len);
1.5 millert 267: return(newsubj);
1.1 deraadt 268: }
269:
270: /*
1.14 millert 271: * Mark new the named messages, so that they will be left in the system
272: * mailbox as unread.
273: */
274: int
1.17 millert 275: marknew(void *v)
1.14 millert 276: {
277: int *msgvec = v;
278: int *ip;
279:
1.25 miod 280: for (ip = msgvec; *ip != 0; ip++) {
1.14 millert 281: dot = &message[*ip-1];
282: dot->m_flag &= ~(MBOX|MREAD|MTOUCH);
283: dot->m_flag |= MNEW|MSTATUS;
284: }
285: return(0);
286: }
287:
288: /*
1.1 deraadt 289: * Preserve the named messages, so that they will be sent
290: * back to the system mailbox.
291: */
292: int
1.17 millert 293: preserve(void *v)
1.1 deraadt 294: {
1.2 deraadt 295: int *msgvec = v;
1.10 millert 296: int *ip, mesg;
297: struct message *mp;
1.1 deraadt 298:
299: if (edit) {
1.5 millert 300: puts("Cannot \"preserve\" in edit mode");
1.1 deraadt 301: return(1);
302: }
1.25 miod 303: for (ip = msgvec; *ip != 0; ip++) {
1.1 deraadt 304: mesg = *ip;
305: mp = &message[mesg-1];
306: mp->m_flag |= MPRESERVE;
307: mp->m_flag &= ~MBOX;
308: dot = mp;
309: }
310: return(0);
311: }
312:
313: /*
314: * Mark all given messages as unread.
315: */
316: int
1.17 millert 317: unread(void *v)
1.1 deraadt 318: {
1.14 millert 319: int *msgvec = v;
1.10 millert 320: int *ip;
1.1 deraadt 321:
1.25 miod 322: for (ip = msgvec; *ip != 0; ip++) {
1.1 deraadt 323: dot = &message[*ip-1];
324: dot->m_flag &= ~(MREAD|MTOUCH);
325: dot->m_flag |= MSTATUS;
326: }
327: return(0);
328: }
329:
330: /*
331: * Print the size of each message.
332: */
333: int
1.17 millert 334: messize(void *v)
1.1 deraadt 335: {
1.2 deraadt 336: int *msgvec = v;
1.10 millert 337: struct message *mp;
338: int *ip, mesg;
1.1 deraadt 339:
1.25 miod 340: for (ip = msgvec; *ip != 0; ip++) {
1.1 deraadt 341: mesg = *ip;
342: mp = &message[mesg-1];
1.3 millert 343: printf("%d: %d/%d\n", mesg, mp->m_lines, mp->m_size);
1.1 deraadt 344: }
345: return(0);
346: }
347:
348: /*
349: * Quit quickly. If we are sourcing, just pop the input level
350: * by returning an error.
351: */
352: int
1.17 millert 353: rexit(void *v)
1.1 deraadt 354: {
1.17 millert 355:
1.1 deraadt 356: if (sourcing)
357: return(1);
1.2 deraadt 358: exit(0);
1.1 deraadt 359: /*NOTREACHED*/
360: }
361:
362: /*
363: * Set or display a variable value. Syntax is similar to that
364: * of csh.
365: */
366: int
1.17 millert 367: set(void *v)
1.1 deraadt 368: {
1.2 deraadt 369: char **arglist = v;
1.10 millert 370: struct var *vp;
371: char *cp, *cp2;
1.1 deraadt 372: char varbuf[BUFSIZ], **ap, **p;
373: int errs, h, s;
374:
1.7 millert 375: if (*arglist == NULL) {
1.1 deraadt 376: for (h = 0, s = 1; h < HSHSIZE; h++)
1.17 millert 377: for (vp = variables[h]; vp != NULL; vp = vp->v_link)
1.1 deraadt 378: s++;
1.6 millert 379: ap = (char **)salloc(s * sizeof(*ap));
1.1 deraadt 380: for (h = 0, p = ap; h < HSHSIZE; h++)
1.17 millert 381: for (vp = variables[h]; vp != NULL; vp = vp->v_link)
1.1 deraadt 382: *p++ = vp->v_name;
1.7 millert 383: *p = NULL;
1.1 deraadt 384: sort(ap);
1.7 millert 385: for (p = ap; *p != NULL; p++)
1.1 deraadt 386: printf("%s\t%s\n", *p, value(*p));
387: return(0);
388: }
389: errs = 0;
1.7 millert 390: for (ap = arglist; *ap != NULL; ap++) {
1.1 deraadt 391: cp = *ap;
392: cp2 = varbuf;
393: while (*cp != '=' && *cp != '\0')
394: *cp2++ = *cp++;
395: *cp2 = '\0';
396: if (*cp == '\0')
397: cp = "";
398: else
399: cp++;
400: if (equal(varbuf, "")) {
1.5 millert 401: puts("Non-null variable name required");
1.1 deraadt 402: errs++;
403: continue;
404: }
405: assign(varbuf, cp);
406: }
407: return(errs);
408: }
409:
410: /*
411: * Unset a bunch of variable values.
412: */
413: int
1.17 millert 414: unset(void *v)
1.1 deraadt 415: {
1.2 deraadt 416: char **arglist = v;
1.10 millert 417: struct var *vp, *vp2;
1.1 deraadt 418: int errs, h;
419: char **ap;
420:
421: errs = 0;
1.7 millert 422: for (ap = arglist; *ap != NULL; ap++) {
1.17 millert 423: if ((vp2 = lookup(*ap)) == NULL) {
1.1 deraadt 424: if (!sourcing) {
425: printf("\"%s\": undefined variable\n", *ap);
426: errs++;
427: }
428: continue;
429: }
430: h = hash(*ap);
431: if (vp2 == variables[h]) {
432: variables[h] = variables[h]->v_link;
433: vfree(vp2->v_name);
434: vfree(vp2->v_value);
1.6 millert 435: (void)free(vp2);
1.1 deraadt 436: continue;
437: }
438: for (vp = variables[h]; vp->v_link != vp2; vp = vp->v_link)
439: ;
440: vp->v_link = vp2->v_link;
441: vfree(vp2->v_name);
442: vfree(vp2->v_value);
1.6 millert 443: (void)free(vp2);
1.1 deraadt 444: }
445: return(errs);
446: }
447:
448: /*
449: * Put add users to a group.
450: */
451: int
1.17 millert 452: group(void *v)
1.1 deraadt 453: {
1.2 deraadt 454: char **argv = v;
1.10 millert 455: struct grouphead *gh;
456: struct group *gp;
1.1 deraadt 457: char **ap, *gname, **p;
1.10 millert 458: int h, s;
1.1 deraadt 459:
1.7 millert 460: if (*argv == NULL) {
1.1 deraadt 461: for (h = 0, s = 1; h < HSHSIZE; h++)
1.17 millert 462: for (gh = groups[h]; gh != NULL; gh = gh->g_link)
1.1 deraadt 463: s++;
1.6 millert 464: ap = (char **)salloc(s * sizeof(*ap));
1.1 deraadt 465: for (h = 0, p = ap; h < HSHSIZE; h++)
1.17 millert 466: for (gh = groups[h]; gh != NULL; gh = gh->g_link)
1.1 deraadt 467: *p++ = gh->g_name;
1.7 millert 468: *p = NULL;
1.1 deraadt 469: sort(ap);
1.7 millert 470: for (p = ap; *p != NULL; p++)
1.1 deraadt 471: printgroup(*p);
472: return(0);
473: }
1.7 millert 474: if (argv[1] == NULL) {
1.1 deraadt 475: printgroup(*argv);
476: return(0);
477: }
478: gname = *argv;
479: h = hash(gname);
1.17 millert 480: if ((gh = findgroup(gname)) == NULL) {
1.27 ! mmcc 481: if ((gh = calloc(1, sizeof(*gh))) == NULL)
! 482: err(1, "calloc");
1.1 deraadt 483: gh->g_name = vcopy(gname);
1.17 millert 484: gh->g_list = NULL;
1.1 deraadt 485: gh->g_link = groups[h];
486: groups[h] = gh;
487: }
488:
489: /*
490: * Insert names from the command list into the group.
491: * Who cares if there are duplicates? They get tossed
492: * later anyway.
493: */
494:
1.7 millert 495: for (ap = argv+1; *ap != NULL; ap++) {
1.27 ! mmcc 496: if ((gp = calloc(1, sizeof(*gp))) == NULL)
! 497: err(1, "calloc");
1.1 deraadt 498: gp->ge_name = vcopy(*ap);
499: gp->ge_link = gh->g_list;
500: gh->g_list = gp;
501: }
502: return(0);
503: }
504:
505: /*
1.23 tobias 506: * Sort the passed string vector into ascending dictionary
1.1 deraadt 507: * order.
508: */
509: void
1.17 millert 510: sort(char **list)
1.1 deraadt 511: {
1.10 millert 512: char **ap;
1.1 deraadt 513:
1.7 millert 514: for (ap = list; *ap != NULL; ap++)
1.1 deraadt 515: ;
516: if (ap-list < 2)
517: return;
518: qsort(list, ap-list, sizeof(*list), diction);
519: }
520:
521: /*
522: * Do a dictionary order comparison of the arguments from
523: * qsort.
524: */
1.2 deraadt 525: static int
1.17 millert 526: diction(const void *a, const void *b)
1.1 deraadt 527: {
1.17 millert 528:
1.1 deraadt 529: return(strcmp(*(char **)a, *(char **)b));
530: }
531:
532: /*
533: * The do nothing command for comments.
534: */
535: /*ARGSUSED*/
536: int
1.17 millert 537: null(void *v)
1.1 deraadt 538: {
1.17 millert 539:
1.5 millert 540: return(0);
1.1 deraadt 541: }
542:
543: /*
544: * Change to another file. With no argument, print information about
545: * the current file.
546: */
547: int
1.17 millert 548: file(void *v)
1.1 deraadt 549: {
1.2 deraadt 550: char **argv = v;
1.1 deraadt 551:
1.7 millert 552: if (argv[0] == NULL) {
1.5 millert 553: newfileinfo(0);
1.11 millert 554: clearnew();
1.5 millert 555: return(0);
1.1 deraadt 556: }
557: if (setfile(*argv) < 0)
1.5 millert 558: return(1);
1.1 deraadt 559: announce();
1.5 millert 560: return(0);
1.1 deraadt 561: }
562:
563: /*
564: * Expand file names like echo
565: */
566: int
1.17 millert 567: echo(void *v)
1.1 deraadt 568: {
1.2 deraadt 569: char **argv = v;
1.10 millert 570: char **ap, *cp;
1.1 deraadt 571:
1.7 millert 572: for (ap = argv; *ap != NULL; ap++) {
1.1 deraadt 573: cp = *ap;
1.7 millert 574: if ((cp = expand(cp)) != NULL) {
1.1 deraadt 575: if (ap != argv)
576: putchar(' ');
1.5 millert 577: fputs(cp, stdout);
1.1 deraadt 578: }
579: }
580: putchar('\n');
1.5 millert 581: return(0);
1.1 deraadt 582: }
583:
584: int
1.17 millert 585: Respond(void *v)
1.1 deraadt 586: {
1.2 deraadt 587: int *msgvec = v;
1.17 millert 588:
1.7 millert 589: if (value("Replyall") == NULL)
1.5 millert 590: return(_Respond(msgvec));
1.1 deraadt 591: else
1.5 millert 592: return(_respond(msgvec));
1.1 deraadt 593: }
594:
595: /*
596: * Reply to a series of messages by simply mailing to the senders
597: * and not messing around with the To: and Cc: lists as in normal
598: * reply.
599: */
600: int
1.17 millert 601: _Respond(int *msgvec)
1.1 deraadt 602: {
603: struct header head;
604: struct message *mp;
1.10 millert 605: int *ap;
606: char *cp;
1.1 deraadt 607:
1.17 millert 608: head.h_to = NULL;
1.1 deraadt 609: for (ap = msgvec; *ap != 0; ap++) {
610: mp = &message[*ap - 1];
611: touch(mp);
612: dot = mp;
1.7 millert 613: if ((cp = skin(hfield("from", mp))) == NULL)
1.1 deraadt 614: cp = skin(nameof(mp, 2));
615: head.h_to = cat(head.h_to, extract(cp, GTO));
616: }
1.17 millert 617: if (head.h_to == NULL)
1.5 millert 618: return(0);
1.1 deraadt 619: mp = &message[msgvec[0] - 1];
1.7 millert 620: if ((head.h_subject = hfield("subject", mp)) == NULL)
1.1 deraadt 621: head.h_subject = hfield("subj", mp);
622: head.h_subject = reedit(head.h_subject);
1.26 millert 623: head.h_from = NULL;
1.17 millert 624: head.h_cc = NULL;
625: head.h_bcc = NULL;
626: head.h_smopts = NULL;
1.1 deraadt 627: mail1(&head, 1);
1.5 millert 628: return(0);
1.1 deraadt 629: }
630:
631: /*
632: * Conditional commands. These allow one to parameterize one's
633: * .mailrc and do some things if sending, others if receiving.
634: */
635: int
1.17 millert 636: ifcmd(void *v)
1.1 deraadt 637: {
1.2 deraadt 638: char **argv = v;
1.10 millert 639: char *cp;
1.1 deraadt 640:
641: if (cond != CANY) {
1.5 millert 642: puts("Illegal nested \"if\"");
1.1 deraadt 643: return(1);
644: }
645: cond = CANY;
646: cp = argv[0];
647: switch (*cp) {
648: case 'r': case 'R':
649: cond = CRCV;
650: break;
651:
652: case 's': case 'S':
653: cond = CSEND;
654: break;
655:
656: default:
657: printf("Unrecognized if-keyword: \"%s\"\n", cp);
658: return(1);
659: }
660: return(0);
661: }
662:
663: /*
664: * Implement 'else'. This is pretty simple -- we just
665: * flip over the conditional flag.
666: */
667: int
1.17 millert 668: elsecmd(void *v)
1.1 deraadt 669: {
670:
671: switch (cond) {
672: case CANY:
1.5 millert 673: puts("\"Else\" without matching \"if\"");
1.1 deraadt 674: return(1);
675:
676: case CSEND:
677: cond = CRCV;
678: break;
679:
680: case CRCV:
681: cond = CSEND;
682: break;
683:
684: default:
1.5 millert 685: puts("mail's idea of conditions is screwed up");
1.1 deraadt 686: cond = CANY;
687: break;
688: }
689: return(0);
690: }
691:
692: /*
693: * End of if statement. Just set cond back to anything.
694: */
695: int
1.17 millert 696: endifcmd(void *v)
1.1 deraadt 697: {
698:
699: if (cond == CANY) {
1.5 millert 700: puts("\"Endif\" without matching \"if\"");
1.1 deraadt 701: return(1);
702: }
703: cond = CANY;
704: return(0);
705: }
706:
707: /*
708: * Set the list of alternate names.
709: */
710: int
1.17 millert 711: alternates(void *v)
1.1 deraadt 712: {
1.2 deraadt 713: char **namelist = v;
1.18 millert 714: char **ap, **ap2;
1.10 millert 715: int c;
1.1 deraadt 716:
717: c = argcount(namelist) + 1;
718: if (c == 1) {
719: if (altnames == 0)
720: return(0);
721: for (ap = altnames; *ap; ap++)
722: printf("%s ", *ap);
1.5 millert 723: putchar('\n');
1.1 deraadt 724: return(0);
725: }
726: if (altnames != 0)
1.6 millert 727: (void)free(altnames);
1.27 ! mmcc 728: if ((altnames = calloc(c, sizeof(char *))) == NULL)
! 729: err(1, "calloc");
1.1 deraadt 730: for (ap = namelist, ap2 = altnames; *ap; ap++, ap2++) {
1.18 millert 731: if ((*ap2 = strdup(*ap)) == NULL)
1.27 ! mmcc 732: err(1, "strdup");
1.1 deraadt 733: }
734: *ap2 = 0;
735: return(0);
736: }