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