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