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