Annotation of src/usr.bin/mail/cmd3.c, Revision 1.8
1.8 ! millert 1: /* $OpenBSD: cmd3.c,v 1.7 1997/07/14 00:24:25 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.8 ! millert 41: static char rcsid[] = "$OpenBSD: cmd3.c,v 1.7 1997/07/14 00:24:25 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.1 deraadt 110: register char *cp, *cp2;
111: register int n;
112: int changed = 0;
113:
114: cp = str;
115: cp2 = bangbuf;
116: n = BUFSIZ;
117: while (*cp) {
118: if (*cp == '!') {
119: if (n < strlen(lastbang)) {
120: overf:
1.5 millert 121: puts("Command buffer overflow");
1.1 deraadt 122: return(-1);
123: }
124: changed++;
125: strcpy(cp2, lastbang);
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: {
162: register c;
163: register FILE *f;
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)
278: register char *subj;
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.1 deraadt 303: register struct message *mp;
304: register int *ip, mesg;
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.1 deraadt 328: register int *ip;
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.1 deraadt 346: register struct message *mp;
347: register int *ip, mesg;
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.1 deraadt 380: register struct var *vp;
381: register char *cp, *cp2;
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.1 deraadt 428: register struct var *vp, *vp2;
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.1 deraadt 467: register struct grouphead *gh;
468: register struct group *gp;
469: register int h;
470: int s;
471: char **ap, *gname, **p;
472:
1.7 millert 473: if (*argv == NULL) {
1.1 deraadt 474: for (h = 0, s = 1; h < HSHSIZE; h++)
475: for (gh = groups[h]; gh != NOGRP; gh = gh->g_link)
476: s++;
1.6 millert 477: ap = (char **)salloc(s * sizeof(*ap));
1.1 deraadt 478: for (h = 0, p = ap; h < HSHSIZE; h++)
479: for (gh = groups[h]; gh != NOGRP; gh = gh->g_link)
480: *p++ = gh->g_name;
1.7 millert 481: *p = NULL;
1.1 deraadt 482: sort(ap);
1.7 millert 483: for (p = ap; *p != NULL; p++)
1.1 deraadt 484: printgroup(*p);
485: return(0);
486: }
1.7 millert 487: if (argv[1] == NULL) {
1.1 deraadt 488: printgroup(*argv);
489: return(0);
490: }
491: gname = *argv;
492: h = hash(gname);
493: if ((gh = findgroup(gname)) == NOGRP) {
1.6 millert 494: gh = (struct grouphead *)calloc(sizeof(*gh), 1);
1.1 deraadt 495: gh->g_name = vcopy(gname);
496: gh->g_list = NOGE;
497: gh->g_link = groups[h];
498: groups[h] = gh;
499: }
500:
501: /*
502: * Insert names from the command list into the group.
503: * Who cares if there are duplicates? They get tossed
504: * later anyway.
505: */
506:
1.7 millert 507: for (ap = argv+1; *ap != NULL; ap++) {
1.6 millert 508: gp = (struct group *)calloc(sizeof(*gp), 1);
1.1 deraadt 509: gp->ge_name = vcopy(*ap);
510: gp->ge_link = gh->g_list;
511: gh->g_list = gp;
512: }
513: return(0);
514: }
515:
516: /*
517: * Sort the passed string vecotor into ascending dictionary
518: * order.
519: */
520: void
521: sort(list)
522: char **list;
523: {
524: register char **ap;
525:
1.7 millert 526: for (ap = list; *ap != NULL; ap++)
1.1 deraadt 527: ;
528: if (ap-list < 2)
529: return;
530: qsort(list, ap-list, sizeof(*list), diction);
531: }
532:
533: /*
534: * Do a dictionary order comparison of the arguments from
535: * qsort.
536: */
1.2 deraadt 537: static int
1.1 deraadt 538: diction(a, b)
539: const void *a, *b;
540: {
541: return(strcmp(*(char **)a, *(char **)b));
542: }
543:
544: /*
545: * The do nothing command for comments.
546: */
547:
548: /*ARGSUSED*/
549: int
1.2 deraadt 550: null(v)
551: void *v;
1.1 deraadt 552: {
1.5 millert 553: return(0);
1.1 deraadt 554: }
555:
556: /*
557: * Change to another file. With no argument, print information about
558: * the current file.
559: */
560: int
1.2 deraadt 561: file(v)
562: void *v;
1.1 deraadt 563: {
1.2 deraadt 564: char **argv = v;
1.1 deraadt 565:
1.7 millert 566: if (argv[0] == NULL) {
1.5 millert 567: newfileinfo(0);
568: return(0);
1.1 deraadt 569: }
570: if (setfile(*argv) < 0)
1.5 millert 571: return(1);
1.1 deraadt 572: announce();
1.5 millert 573: return(0);
1.1 deraadt 574: }
575:
576: /*
577: * Expand file names like echo
578: */
579: int
1.2 deraadt 580: echo(v)
581: void *v;
1.1 deraadt 582: {
1.2 deraadt 583: char **argv = v;
1.1 deraadt 584: register char **ap;
585: register char *cp;
586:
1.7 millert 587: for (ap = argv; *ap != NULL; ap++) {
1.1 deraadt 588: cp = *ap;
1.7 millert 589: if ((cp = expand(cp)) != NULL) {
1.1 deraadt 590: if (ap != argv)
591: putchar(' ');
1.5 millert 592: fputs(cp, stdout);
1.1 deraadt 593: }
594: }
595: putchar('\n');
1.5 millert 596: return(0);
1.1 deraadt 597: }
598:
599: int
1.2 deraadt 600: Respond(v)
601: void *v;
1.1 deraadt 602: {
1.2 deraadt 603: int *msgvec = v;
1.7 millert 604: if (value("Replyall") == NULL)
1.5 millert 605: return(_Respond(msgvec));
1.1 deraadt 606: else
1.5 millert 607: return(_respond(msgvec));
1.1 deraadt 608: }
609:
610: /*
611: * Reply to a series of messages by simply mailing to the senders
612: * and not messing around with the To: and Cc: lists as in normal
613: * reply.
614: */
615: int
616: _Respond(msgvec)
617: int msgvec[];
618: {
619: struct header head;
620: struct message *mp;
621: register int *ap;
622: register char *cp;
623:
624: head.h_to = NIL;
625: for (ap = msgvec; *ap != 0; ap++) {
626: mp = &message[*ap - 1];
627: touch(mp);
628: dot = mp;
1.7 millert 629: if ((cp = skin(hfield("from", mp))) == NULL)
1.1 deraadt 630: cp = skin(nameof(mp, 2));
631: head.h_to = cat(head.h_to, extract(cp, GTO));
632: }
633: if (head.h_to == NIL)
1.5 millert 634: return(0);
1.1 deraadt 635: mp = &message[msgvec[0] - 1];
1.7 millert 636: if ((head.h_subject = hfield("subject", mp)) == NULL)
1.1 deraadt 637: head.h_subject = hfield("subj", mp);
638: head.h_subject = reedit(head.h_subject);
639: head.h_cc = NIL;
640: head.h_bcc = NIL;
641: head.h_smopts = NIL;
642: mail1(&head, 1);
1.5 millert 643: return(0);
1.1 deraadt 644: }
645:
646: /*
647: * Conditional commands. These allow one to parameterize one's
648: * .mailrc and do some things if sending, others if receiving.
649: */
650: int
1.2 deraadt 651: ifcmd(v)
652: void *v;
1.1 deraadt 653: {
1.2 deraadt 654: char **argv = v;
1.1 deraadt 655: register char *cp;
656:
657: if (cond != CANY) {
1.5 millert 658: puts("Illegal nested \"if\"");
1.1 deraadt 659: return(1);
660: }
661: cond = CANY;
662: cp = argv[0];
663: switch (*cp) {
664: case 'r': case 'R':
665: cond = CRCV;
666: break;
667:
668: case 's': case 'S':
669: cond = CSEND;
670: break;
671:
672: default:
673: printf("Unrecognized if-keyword: \"%s\"\n", cp);
674: return(1);
675: }
676: return(0);
677: }
678:
679: /*
680: * Implement 'else'. This is pretty simple -- we just
681: * flip over the conditional flag.
682: */
683: int
1.2 deraadt 684: elsecmd(v)
685: void *v;
1.1 deraadt 686: {
687:
688: switch (cond) {
689: case CANY:
1.5 millert 690: puts("\"Else\" without matching \"if\"");
1.1 deraadt 691: return(1);
692:
693: case CSEND:
694: cond = CRCV;
695: break;
696:
697: case CRCV:
698: cond = CSEND;
699: break;
700:
701: default:
1.5 millert 702: puts("mail's idea of conditions is screwed up");
1.1 deraadt 703: cond = CANY;
704: break;
705: }
706: return(0);
707: }
708:
709: /*
710: * End of if statement. Just set cond back to anything.
711: */
712: int
1.2 deraadt 713: endifcmd(v)
714: void *v;
1.1 deraadt 715: {
716:
717: if (cond == CANY) {
1.5 millert 718: puts("\"Endif\" without matching \"if\"");
1.1 deraadt 719: return(1);
720: }
721: cond = CANY;
722: return(0);
723: }
724:
725: /*
726: * Set the list of alternate names.
727: */
728: int
1.2 deraadt 729: alternates(v)
730: void *v;
1.1 deraadt 731: {
1.2 deraadt 732: char **namelist = v;
1.1 deraadt 733: register int c;
734: register char **ap, **ap2, *cp;
735:
736: c = argcount(namelist) + 1;
737: if (c == 1) {
738: if (altnames == 0)
739: return(0);
740: for (ap = altnames; *ap; ap++)
741: printf("%s ", *ap);
1.5 millert 742: putchar('\n');
1.1 deraadt 743: return(0);
744: }
745: if (altnames != 0)
1.6 millert 746: (void)free(altnames);
747: altnames = (char **)calloc(c, sizeof(char *));
1.1 deraadt 748: for (ap = namelist, ap2 = altnames; *ap; ap++, ap2++) {
1.6 millert 749: cp = (char *)calloc(strlen(*ap) + 1, sizeof(char));
1.1 deraadt 750: strcpy(cp, *ap);
751: *ap2 = cp;
752: }
753: *ap2 = 0;
754: return(0);
755: }