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