Commit | Line | Data |
---|---|---|
2ae9f53f SL |
1 | #ifndef lint |
2 | static char sccsid[] = "@(#)cmd3.c 2.14 (Berkeley) %G%"; | |
3 | #endif | |
ca6bb034 KS |
4 | |
5 | #include "rcv.h" | |
6 | #include <sys/stat.h> | |
7 | ||
8 | /* | |
9 | * Mail -- a mail program | |
10 | * | |
11 | * Still more user commands. | |
12 | */ | |
13 | ||
ca6bb034 KS |
14 | /* |
15 | * Process a shell escape by saving signals, ignoring signals, | |
16 | * and forking a sh -c | |
17 | */ | |
18 | ||
19 | shell(str) | |
20 | char *str; | |
21 | { | |
22 | int (*sig[2])(), stat[1]; | |
23 | register int t; | |
24 | char *Shell; | |
e8adee6e | 25 | char cmd[BUFSIZ]; |
ca6bb034 | 26 | |
e8adee6e KS |
27 | strcpy(cmd, str); |
28 | if (bangexp(cmd) < 0) | |
29 | return(-1); | |
ca6bb034 KS |
30 | if ((Shell = value("SHELL")) == NOSTR) |
31 | Shell = SHELL; | |
32 | for (t = 2; t < 4; t++) | |
5f38a28f | 33 | sig[t-2] = sigset(t, SIG_IGN); |
ca6bb034 KS |
34 | t = vfork(); |
35 | if (t == 0) { | |
5388d5b8 | 36 | sigchild(); |
ca6bb034 KS |
37 | for (t = 2; t < 4; t++) |
38 | if (sig[t-2] != SIG_IGN) | |
5f38a28f | 39 | sigsys(t, SIG_DFL); |
e8adee6e | 40 | execl(Shell, Shell, "-c", cmd, 0); |
ca6bb034 KS |
41 | perror(Shell); |
42 | _exit(1); | |
43 | } | |
44 | while (wait(stat) != t) | |
45 | ; | |
46 | if (t == -1) | |
47 | perror("fork"); | |
48 | for (t = 2; t < 4; t++) | |
5f38a28f | 49 | sigset(t, sig[t-2]); |
ca6bb034 KS |
50 | printf("!\n"); |
51 | return(0); | |
52 | } | |
53 | ||
54 | /* | |
55 | * Fork an interactive shell. | |
56 | */ | |
57 | ||
58 | dosh(str) | |
59 | char *str; | |
60 | { | |
61 | int (*sig[2])(), stat[1]; | |
62 | register int t; | |
63 | char *Shell; | |
ca6bb034 KS |
64 | if ((Shell = value("SHELL")) == NOSTR) |
65 | Shell = SHELL; | |
66 | for (t = 2; t < 4; t++) | |
5f38a28f | 67 | sig[t-2] = sigset(t, SIG_IGN); |
ca6bb034 KS |
68 | t = vfork(); |
69 | if (t == 0) { | |
5388d5b8 | 70 | sigchild(); |
ca6bb034 KS |
71 | for (t = 2; t < 4; t++) |
72 | if (sig[t-2] != SIG_IGN) | |
5f38a28f | 73 | sigsys(t, SIG_DFL); |
ca6bb034 KS |
74 | execl(Shell, Shell, 0); |
75 | perror(Shell); | |
76 | _exit(1); | |
77 | } | |
78 | while (wait(stat) != t) | |
79 | ; | |
80 | if (t == -1) | |
81 | perror("fork"); | |
82 | for (t = 2; t < 4; t++) | |
5f38a28f | 83 | sigsys(t, sig[t-2]); |
ca6bb034 KS |
84 | putchar('\n'); |
85 | return(0); | |
86 | } | |
87 | ||
e8adee6e KS |
88 | /* |
89 | * Expand the shell escape by expanding unescaped !'s into the | |
90 | * last issued command where possible. | |
91 | */ | |
92 | ||
93 | char lastbang[128]; | |
94 | ||
95 | bangexp(str) | |
96 | char *str; | |
97 | { | |
98 | char bangbuf[BUFSIZ]; | |
99 | register char *cp, *cp2; | |
100 | register int n; | |
101 | int changed = 0; | |
102 | ||
103 | cp = str; | |
104 | cp2 = bangbuf; | |
105 | n = BUFSIZ; | |
106 | while (*cp) { | |
107 | if (*cp == '!') { | |
108 | if (n < strlen(lastbang)) { | |
109 | overf: | |
110 | printf("Command buffer overflow\n"); | |
111 | return(-1); | |
112 | } | |
113 | changed++; | |
114 | strcpy(cp2, lastbang); | |
115 | cp2 += strlen(lastbang); | |
116 | n -= strlen(lastbang); | |
117 | cp++; | |
118 | continue; | |
119 | } | |
120 | if (*cp == '\\' && cp[1] == '!') { | |
121 | if (--n <= 1) | |
122 | goto overf; | |
123 | *cp2++ = '!'; | |
124 | cp += 2; | |
125 | changed++; | |
126 | } | |
127 | if (--n <= 1) | |
128 | goto overf; | |
129 | *cp2++ = *cp++; | |
130 | } | |
131 | *cp2 = 0; | |
132 | if (changed) { | |
133 | printf("!%s\n", bangbuf); | |
134 | fflush(stdout); | |
135 | } | |
136 | strcpy(str, bangbuf); | |
137 | strncpy(lastbang, bangbuf, 128); | |
138 | lastbang[127] = 0; | |
139 | return(0); | |
140 | } | |
141 | ||
ca6bb034 KS |
142 | /* |
143 | * Print out a nice help message from some file or another. | |
144 | */ | |
145 | ||
146 | help() | |
147 | { | |
148 | register c; | |
149 | register FILE *f; | |
150 | ||
151 | if ((f = fopen(HELPFILE, "r")) == NULL) { | |
7949d400 | 152 | perror(HELPFILE); |
ca6bb034 KS |
153 | return(1); |
154 | } | |
155 | while ((c = getc(f)) != EOF) | |
156 | putchar(c); | |
157 | fclose(f); | |
158 | return(0); | |
159 | } | |
160 | ||
161 | /* | |
162 | * Change user's working directory. | |
163 | */ | |
164 | ||
165 | schdir(str) | |
166 | char *str; | |
167 | { | |
168 | register char *cp; | |
169 | ||
170 | for (cp = str; *cp == ' '; cp++) | |
171 | ; | |
172 | if (*cp == '\0') | |
173 | cp = homedir; | |
174 | else | |
175 | if ((cp = expand(cp)) == NOSTR) | |
176 | return(1); | |
177 | if (chdir(cp) < 0) { | |
178 | perror(cp); | |
179 | return(1); | |
180 | } | |
181 | return(0); | |
182 | } | |
183 | ||
184 | /* | |
185 | * Reply to a list of messages. Extract each name from the | |
186 | * message header and send them off to mail1() | |
187 | */ | |
188 | ||
189 | respond(msgvec) | |
190 | int *msgvec; | |
191 | { | |
192 | struct message *mp; | |
7949d400 CL |
193 | char *cp, *cp2, *cp3, *rcv, *replyto; |
194 | char buf[2 * LINESIZE], **ap; | |
ca6bb034 KS |
195 | struct name *np; |
196 | struct header head; | |
ca6bb034 KS |
197 | |
198 | if (msgvec[1] != 0) { | |
199 | printf("Sorry, can't reply to multiple messages at once\n"); | |
200 | return(1); | |
201 | } | |
202 | mp = &message[msgvec[0] - 1]; | |
203 | dot = mp; | |
a0bc099a | 204 | rcv = NOSTR; |
bdad82b3 | 205 | cp = skin(nameof(mp, 1)); |
a0bc099a CL |
206 | if (cp != NOSTR) |
207 | rcv = cp; | |
bdad82b3 | 208 | cp = skin(hfield("from", mp)); |
a0bc099a CL |
209 | if (cp != NOSTR) |
210 | rcv = cp; | |
35bddd51 | 211 | replyto = skin(hfield("reply-to", mp)); |
ca6bb034 | 212 | strcpy(buf, ""); |
52984be9 KS |
213 | if (replyto != NOSTR) |
214 | strcpy(buf, replyto); | |
215 | else { | |
bdad82b3 | 216 | cp = skin(hfield("to", mp)); |
52984be9 KS |
217 | if (cp != NOSTR) |
218 | strcpy(buf, cp); | |
219 | } | |
ca6bb034 KS |
220 | np = elide(extract(buf, GTO)); |
221 | /* rcv = rename(rcv); */ | |
222 | mapf(np, rcv); | |
1c04ff22 KS |
223 | /* |
224 | * Delete my name from the reply list, | |
225 | * and with it, all my alternate names. | |
226 | */ | |
7949d400 CL |
227 | np = delname(np, myname, icequal); |
228 | if (altnames) | |
1c04ff22 | 229 | for (ap = altnames; *ap; ap++) |
7949d400 | 230 | np = delname(np, *ap, icequal); |
ca6bb034 | 231 | head.h_seq = 1; |
bdad82b3 | 232 | cp = detract(np, 0); |
52984be9 | 233 | if (cp != NOSTR && replyto == NOSTR) { |
ca6bb034 | 234 | strcpy(buf, cp); |
bdad82b3 | 235 | strcat(buf, " "); |
ca6bb034 KS |
236 | strcat(buf, rcv); |
237 | } | |
52984be9 KS |
238 | else { |
239 | if (cp == NOSTR && replyto != NOSTR) | |
240 | printf("Empty reply-to field -- replying to author\n"); | |
241 | if (cp == NOSTR) | |
242 | strcpy(buf, rcv); | |
243 | else | |
244 | strcpy(buf, cp); | |
245 | } | |
ca6bb034 KS |
246 | head.h_to = buf; |
247 | head.h_subject = hfield("subject", mp); | |
248 | if (head.h_subject == NOSTR) | |
249 | head.h_subject = hfield("subj", mp); | |
fc8872bb | 250 | head.h_subject = reedit(head.h_subject); |
ca6bb034 | 251 | head.h_cc = NOSTR; |
52984be9 KS |
252 | if (replyto == NOSTR) { |
253 | cp = hfield("cc", mp); | |
254 | if (cp != NOSTR) { | |
255 | np = elide(extract(cp, GCC)); | |
256 | mapf(np, rcv); | |
7949d400 | 257 | np = delname(np, myname, icequal); |
2a8a6697 KS |
258 | if (altnames != 0) |
259 | for (ap = altnames; *ap; ap++) | |
7949d400 | 260 | np = delname(np, *ap, icequal); |
52984be9 KS |
261 | head.h_cc = detract(np, 0); |
262 | } | |
ca6bb034 KS |
263 | } |
264 | head.h_bcc = NOSTR; | |
265 | mail1(&head); | |
266 | return(0); | |
267 | } | |
268 | ||
fc8872bb KS |
269 | /* |
270 | * Modify the subject we are replying to to begin with Re: if | |
271 | * it does not already. | |
272 | */ | |
273 | ||
274 | char * | |
275 | reedit(subj) | |
276 | char *subj; | |
277 | { | |
278 | char sbuf[10]; | |
279 | register char *newsubj; | |
280 | ||
281 | if (subj == NOSTR) | |
282 | return(NOSTR); | |
283 | strncpy(sbuf, subj, 3); | |
284 | sbuf[3] = 0; | |
285 | if (icequal(sbuf, "re:")) | |
286 | return(subj); | |
287 | newsubj = salloc(strlen(subj) + 6); | |
288 | sprintf(newsubj, "Re: %s", subj); | |
289 | return(newsubj); | |
290 | } | |
291 | ||
ca6bb034 KS |
292 | /* |
293 | * Preserve the named messages, so that they will be sent | |
294 | * back to the system mailbox. | |
295 | */ | |
296 | ||
297 | preserve(msgvec) | |
298 | int *msgvec; | |
299 | { | |
300 | register struct message *mp; | |
301 | register int *ip, mesg; | |
302 | ||
303 | if (edit) { | |
304 | printf("Cannot \"preserve\" in edit mode\n"); | |
305 | return(1); | |
306 | } | |
307 | for (ip = msgvec; *ip != NULL; ip++) { | |
308 | mesg = *ip; | |
309 | mp = &message[mesg-1]; | |
310 | mp->m_flag |= MPRESERVE; | |
8fe58892 | 311 | mp->m_flag &= ~MBOX; |
ca6bb034 KS |
312 | dot = mp; |
313 | } | |
314 | return(0); | |
315 | } | |
316 | ||
317 | /* | |
318 | * Print the size of each message. | |
319 | */ | |
320 | ||
321 | messize(msgvec) | |
322 | int *msgvec; | |
323 | { | |
324 | register struct message *mp; | |
325 | register int *ip, mesg; | |
326 | ||
327 | for (ip = msgvec; *ip != NULL; ip++) { | |
328 | mesg = *ip; | |
329 | mp = &message[mesg-1]; | |
7667ac30 | 330 | printf("%d: %ld\n", mesg, mp->m_size); |
ca6bb034 KS |
331 | } |
332 | return(0); | |
333 | } | |
334 | ||
335 | /* | |
336 | * Quit quickly. If we are sourcing, just pop the input level | |
337 | * by returning an error. | |
338 | */ | |
339 | ||
340 | rexit(e) | |
341 | { | |
342 | if (sourcing) | |
343 | return(1); | |
c179b6f2 KS |
344 | if (Tflag != NOSTR) |
345 | close(creat(Tflag, 0600)); | |
ca6bb034 KS |
346 | exit(e); |
347 | } | |
348 | ||
349 | /* | |
350 | * Set or display a variable value. Syntax is similar to that | |
351 | * of csh. | |
352 | */ | |
353 | ||
354 | set(arglist) | |
355 | char **arglist; | |
356 | { | |
357 | register struct var *vp; | |
358 | register char *cp, *cp2; | |
359 | char varbuf[BUFSIZ], **ap, **p; | |
360 | int errs, h, s; | |
361 | ||
362 | if (argcount(arglist) == 0) { | |
363 | for (h = 0, s = 1; h < HSHSIZE; h++) | |
364 | for (vp = variables[h]; vp != NOVAR; vp = vp->v_link) | |
365 | s++; | |
366 | ap = (char **) salloc(s * sizeof *ap); | |
367 | for (h = 0, p = ap; h < HSHSIZE; h++) | |
368 | for (vp = variables[h]; vp != NOVAR; vp = vp->v_link) | |
369 | *p++ = vp->v_name; | |
370 | *p = NOSTR; | |
371 | sort(ap); | |
372 | for (p = ap; *p != NOSTR; p++) | |
373 | printf("%s\t%s\n", *p, value(*p)); | |
374 | return(0); | |
375 | } | |
376 | errs = 0; | |
377 | for (ap = arglist; *ap != NOSTR; ap++) { | |
378 | cp = *ap; | |
379 | cp2 = varbuf; | |
380 | while (*cp != '=' && *cp != '\0') | |
381 | *cp2++ = *cp++; | |
382 | *cp2 = '\0'; | |
383 | if (*cp == '\0') | |
384 | cp = ""; | |
385 | else | |
386 | cp++; | |
387 | if (equal(varbuf, "")) { | |
388 | printf("Non-null variable name required\n"); | |
389 | errs++; | |
390 | continue; | |
391 | } | |
392 | assign(varbuf, cp); | |
393 | } | |
394 | return(errs); | |
395 | } | |
396 | ||
397 | /* | |
398 | * Unset a bunch of variable values. | |
399 | */ | |
400 | ||
401 | unset(arglist) | |
402 | char **arglist; | |
403 | { | |
404 | register struct var *vp, *vp2; | |
405 | register char *cp; | |
406 | int errs, h; | |
407 | char **ap; | |
408 | ||
409 | errs = 0; | |
410 | for (ap = arglist; *ap != NOSTR; ap++) { | |
411 | if ((vp2 = lookup(*ap)) == NOVAR) { | |
412 | if (!sourcing) { | |
413 | printf("\"%s\": undefined variable\n", *ap); | |
414 | errs++; | |
415 | } | |
416 | continue; | |
417 | } | |
418 | h = hash(*ap); | |
419 | if (vp2 == variables[h]) { | |
420 | variables[h] = variables[h]->v_link; | |
421 | vfree(vp2->v_name); | |
422 | vfree(vp2->v_value); | |
423 | cfree(vp2); | |
424 | continue; | |
425 | } | |
426 | for (vp = variables[h]; vp->v_link != vp2; vp = vp->v_link) | |
427 | ; | |
428 | vp->v_link = vp2->v_link; | |
429 | vfree(vp2->v_name); | |
430 | vfree(vp2->v_value); | |
431 | cfree(vp2); | |
432 | } | |
433 | return(errs); | |
434 | } | |
435 | ||
436 | /* | |
437 | * Put add users to a group. | |
438 | */ | |
439 | ||
440 | group(argv) | |
441 | char **argv; | |
442 | { | |
443 | register struct grouphead *gh; | |
444 | register struct group *gp; | |
445 | register int h; | |
446 | int s; | |
447 | char **ap, *gname, **p; | |
448 | ||
449 | if (argcount(argv) == 0) { | |
450 | for (h = 0, s = 1; h < HSHSIZE; h++) | |
451 | for (gh = groups[h]; gh != NOGRP; gh = gh->g_link) | |
452 | s++; | |
453 | ap = (char **) salloc(s * sizeof *ap); | |
454 | for (h = 0, p = ap; h < HSHSIZE; h++) | |
455 | for (gh = groups[h]; gh != NOGRP; gh = gh->g_link) | |
456 | *p++ = gh->g_name; | |
457 | *p = NOSTR; | |
458 | sort(ap); | |
459 | for (p = ap; *p != NOSTR; p++) | |
460 | printgroup(*p); | |
461 | return(0); | |
462 | } | |
463 | if (argcount(argv) == 1) { | |
464 | printgroup(*argv); | |
465 | return(0); | |
466 | } | |
467 | gname = *argv; | |
468 | h = hash(gname); | |
469 | if ((gh = findgroup(gname)) == NOGRP) { | |
470 | gh = (struct grouphead *) calloc(sizeof *gh, 1); | |
471 | gh->g_name = vcopy(gname); | |
472 | gh->g_list = NOGE; | |
473 | gh->g_link = groups[h]; | |
474 | groups[h] = gh; | |
475 | } | |
476 | ||
477 | /* | |
478 | * Insert names from the command list into the group. | |
479 | * Who cares if there are duplicates? They get tossed | |
480 | * later anyway. | |
481 | */ | |
482 | ||
483 | for (ap = argv+1; *ap != NOSTR; ap++) { | |
484 | gp = (struct group *) calloc(sizeof *gp, 1); | |
485 | gp->ge_name = vcopy(*ap); | |
486 | gp->ge_link = gh->g_list; | |
487 | gh->g_list = gp; | |
488 | } | |
489 | return(0); | |
490 | } | |
491 | ||
492 | /* | |
493 | * Sort the passed string vecotor into ascending dictionary | |
494 | * order. | |
495 | */ | |
496 | ||
497 | sort(list) | |
498 | char **list; | |
499 | { | |
500 | register char **ap; | |
501 | int diction(); | |
502 | ||
503 | for (ap = list; *ap != NOSTR; ap++) | |
504 | ; | |
505 | if (ap-list < 2) | |
506 | return; | |
507 | qsort(list, ap-list, sizeof *list, diction); | |
508 | } | |
509 | ||
510 | /* | |
511 | * Do a dictionary order comparison of the arguments from | |
512 | * qsort. | |
513 | */ | |
514 | ||
515 | diction(a, b) | |
516 | register char **a, **b; | |
517 | { | |
518 | return(strcmp(*a, *b)); | |
519 | } | |
520 | ||
521 | /* | |
522 | * The do nothing command for comments. | |
523 | */ | |
524 | ||
525 | null(e) | |
526 | { | |
527 | return(0); | |
528 | } | |
529 | ||
530 | /* | |
1031a04a | 531 | * Print out the current edit file, if we are editing. |
ca6bb034 KS |
532 | * Otherwise, print the name of the person who's mail |
533 | * we are reading. | |
534 | */ | |
535 | ||
1031a04a KS |
536 | file(argv) |
537 | char **argv; | |
ca6bb034 KS |
538 | { |
539 | register char *cp; | |
1031a04a | 540 | char fname[BUFSIZ]; |
84995525 | 541 | int edit; |
ca6bb034 | 542 | |
1031a04a | 543 | if (argv[0] == NOSTR) { |
890194fb | 544 | newfileinfo(); |
1031a04a KS |
545 | return(0); |
546 | } | |
547 | ||
548 | /* | |
549 | * Acker's! Must switch to the new file. | |
550 | * We use a funny interpretation -- | |
551 | * # -- gets the previous file | |
552 | * % -- gets the invoker's post office box | |
553 | * %user -- gets someone else's post office box | |
c953e015 | 554 | * & -- gets invoker's mbox file |
1031a04a KS |
555 | * string -- reads the given file |
556 | */ | |
557 | ||
84995525 | 558 | cp = getfilename(argv[0], &edit); |
1031a04a KS |
559 | if (cp == NOSTR) |
560 | return(-1); | |
f3b6f2ce KS |
561 | if (setfile(cp, edit)) { |
562 | perror(cp); | |
c45bca48 | 563 | return(-1); |
f3b6f2ce | 564 | } |
c45bca48 | 565 | newfileinfo(); |
1031a04a KS |
566 | } |
567 | ||
568 | /* | |
569 | * Evaluate the string given as a new mailbox name. | |
570 | * Ultimately, we want this to support a number of meta characters. | |
571 | * Possibly: | |
572 | * % -- for my system mail box | |
573 | * %user -- for user's system mail box | |
574 | * # -- for previous file | |
c953e015 | 575 | * & -- get's invoker's mbox file |
1031a04a KS |
576 | * file name -- for any other file |
577 | */ | |
578 | ||
d344b00c | 579 | char prevfile[PATHSIZE]; |
c953e015 | 580 | |
1031a04a | 581 | char * |
84995525 | 582 | getfilename(name, aedit) |
1031a04a | 583 | char *name; |
84995525 | 584 | int *aedit; |
1031a04a KS |
585 | { |
586 | register char *cp; | |
c953e015 | 587 | char savename[BUFSIZ]; |
2b6cb640 | 588 | char oldmailname[BUFSIZ]; |
c953e015 | 589 | |
84995525 KS |
590 | /* |
591 | * Assume we will be in "edit file" mode, until | |
592 | * proven wrong. | |
593 | */ | |
594 | *aedit = 1; | |
c953e015 KS |
595 | switch (*name) { |
596 | case '%': | |
84995525 | 597 | *aedit = 0; |
d344b00c | 598 | strcpy(prevfile, mailname); |
c953e015 KS |
599 | if (name[1] != 0) { |
600 | strcpy(savename, myname); | |
2b6cb640 | 601 | strcpy(oldmailname, mailname); |
c953e015 KS |
602 | strncpy(myname, name+1, PATHSIZE-1); |
603 | myname[PATHSIZE-1] = 0; | |
604 | findmail(); | |
2b6cb640 | 605 | cp = savestr(mailname); |
c953e015 | 606 | strcpy(myname, savename); |
2b6cb640 | 607 | strcpy(mailname, oldmailname); |
c953e015 KS |
608 | return(cp); |
609 | } | |
2b6cb640 | 610 | strcpy(oldmailname, mailname); |
c953e015 | 611 | findmail(); |
2b6cb640 KS |
612 | cp = savestr(mailname); |
613 | strcpy(mailname, oldmailname); | |
614 | return(cp); | |
c953e015 KS |
615 | |
616 | case '#': | |
617 | if (name[1] != 0) | |
618 | goto regular; | |
619 | if (prevfile[0] == 0) { | |
620 | printf("No previous file\n"); | |
621 | return(NOSTR); | |
622 | } | |
2b6cb640 | 623 | cp = savestr(prevfile); |
d344b00c | 624 | strcpy(prevfile, mailname); |
2b6cb640 | 625 | return(cp); |
1031a04a | 626 | |
c953e015 | 627 | case '&': |
d344b00c | 628 | strcpy(prevfile, mailname); |
c953e015 KS |
629 | if (name[1] == 0) |
630 | return(mbox); | |
631 | /* Fall into . . . */ | |
632 | ||
633 | default: | |
634 | regular: | |
d344b00c | 635 | strcpy(prevfile, mailname); |
c953e015 KS |
636 | cp = expand(name); |
637 | return(cp); | |
638 | } | |
ca6bb034 KS |
639 | } |
640 | ||
641 | /* | |
642 | * Expand file names like echo | |
643 | */ | |
644 | ||
645 | echo(argv) | |
646 | char **argv; | |
647 | { | |
648 | register char **ap; | |
649 | register char *cp; | |
650 | ||
651 | for (ap = argv; *ap != NOSTR; ap++) { | |
652 | cp = *ap; | |
653 | if ((cp = expand(cp)) != NOSTR) | |
9e60d092 | 654 | printf("%s ", cp); |
ca6bb034 KS |
655 | } |
656 | return(0); | |
657 | } | |
658 | ||
659 | /* | |
660 | * Reply to a series of messages by simply mailing to the senders | |
661 | * and not messing around with the To: and Cc: lists as in normal | |
662 | * reply. | |
663 | */ | |
664 | ||
665 | Respond(msgvec) | |
666 | int msgvec[]; | |
667 | { | |
668 | struct header head; | |
669 | struct message *mp; | |
a0bc099a CL |
670 | register int i, s, *ap; |
671 | register char *cp, *cp2, *subject; | |
ca6bb034 KS |
672 | |
673 | for (s = 0, ap = msgvec; *ap != 0; ap++) { | |
674 | mp = &message[*ap - 1]; | |
675 | dot = mp; | |
bdad82b3 | 676 | if ((cp = skin(hfield("from", mp))) != NOSTR) |
a0bc099a CL |
677 | s+= strlen(cp) + 1; |
678 | else | |
bdad82b3 | 679 | s += strlen(skin(nameof(mp, 2))) + 1; |
ca6bb034 KS |
680 | } |
681 | if (s == 0) | |
682 | return(0); | |
683 | cp = salloc(s + 2); | |
684 | head.h_to = cp; | |
685 | for (ap = msgvec; *ap != 0; ap++) { | |
686 | mp = &message[*ap - 1]; | |
bdad82b3 CL |
687 | if ((cp2 = skin(hfield("from", mp))) == NOSTR) |
688 | cp2 = skin(nameof(mp, 2)); | |
a0bc099a | 689 | cp = copy(cp2, cp); |
ca6bb034 KS |
690 | *cp++ = ' '; |
691 | } | |
692 | *--cp = 0; | |
693 | mp = &message[msgvec[0] - 1]; | |
694 | subject = hfield("subject", mp); | |
695 | head.h_seq = 0; | |
696 | if (subject == NOSTR) | |
697 | subject = hfield("subj", mp); | |
fc8872bb | 698 | head.h_subject = reedit(subject); |
ca6bb034 KS |
699 | if (subject != NOSTR) |
700 | head.h_seq++; | |
701 | head.h_cc = NOSTR; | |
702 | head.h_bcc = NOSTR; | |
703 | mail1(&head); | |
704 | return(0); | |
705 | } | |
d344b00c KS |
706 | |
707 | /* | |
708 | * Conditional commands. These allow one to parameterize one's | |
709 | * .mailrc and do some things if sending, others if receiving. | |
710 | */ | |
711 | ||
712 | ifcmd(argv) | |
713 | char **argv; | |
714 | { | |
715 | register char *cp; | |
716 | ||
717 | if (cond != CANY) { | |
718 | printf("Illegal nested \"if\"\n"); | |
719 | return(1); | |
720 | } | |
721 | cond = CANY; | |
722 | cp = argv[0]; | |
723 | switch (*cp) { | |
724 | case 'r': case 'R': | |
725 | cond = CRCV; | |
726 | break; | |
727 | ||
728 | case 's': case 'S': | |
729 | cond = CSEND; | |
730 | break; | |
731 | ||
732 | default: | |
733 | printf("Unrecognized if-keyword: \"%s\"\n", cp); | |
734 | return(1); | |
735 | } | |
736 | return(0); | |
737 | } | |
738 | ||
739 | /* | |
740 | * Implement 'else'. This is pretty simple -- we just | |
741 | * flip over the conditional flag. | |
742 | */ | |
743 | ||
744 | elsecmd() | |
745 | { | |
746 | ||
747 | switch (cond) { | |
748 | case CANY: | |
749 | printf("\"Else\" without matching \"if\"\n"); | |
750 | return(1); | |
751 | ||
752 | case CSEND: | |
753 | cond = CRCV; | |
754 | break; | |
755 | ||
756 | case CRCV: | |
757 | cond = CSEND; | |
758 | break; | |
759 | ||
760 | default: | |
761 | printf("Mail's idea of conditions is screwed up\n"); | |
762 | cond = CANY; | |
763 | break; | |
764 | } | |
765 | return(0); | |
766 | } | |
767 | ||
768 | /* | |
769 | * End of if statement. Just set cond back to anything. | |
770 | */ | |
771 | ||
772 | endifcmd() | |
773 | { | |
774 | ||
775 | if (cond == CANY) { | |
776 | printf("\"Endif\" without matching \"if\"\n"); | |
777 | return(1); | |
778 | } | |
779 | cond = CANY; | |
780 | return(0); | |
781 | } | |
1c04ff22 KS |
782 | |
783 | /* | |
784 | * Set the list of alternate names. | |
785 | */ | |
786 | alternates(namelist) | |
787 | char **namelist; | |
788 | { | |
789 | register int c; | |
790 | register char **ap, **ap2, *cp; | |
791 | ||
792 | c = argcount(namelist) + 1; | |
793 | if (c == 1) { | |
794 | if (altnames == 0) | |
795 | return(0); | |
796 | for (ap = altnames; *ap; ap++) | |
797 | printf("%s ", *ap); | |
798 | printf("\n"); | |
799 | return(0); | |
800 | } | |
801 | if (altnames != 0) | |
802 | cfree((char *) altnames); | |
803 | altnames = (char **) calloc(c, sizeof (char *)); | |
804 | for (ap = namelist, ap2 = altnames; *ap; ap++, ap2++) { | |
805 | cp = (char *) calloc(strlen(*ap) + 1, sizeof (char)); | |
806 | strcpy(cp, *ap); | |
807 | *ap2 = cp; | |
808 | } | |
809 | *ap2 = 0; | |
810 | return(0); | |
811 | } |