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