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