|
|
1.1 root 1: #
2:
3: #include "rcv.h"
4: #include <sys/stat.h>
5:
6: /*
7: * Mail -- a mail program
8: *
9: * Still more user commands.
10: */
11:
12: /*
13: * Process a shell escape by saving signals, ignoring signals,
14: * and forking a sh -c
15: */
16:
17: shell(str)
18: char *str;
19: {
20: int (*sig[2])(), stat[1];
21: register int t;
22: char *Shell;
23:
24: if ((Shell = value("SHELL")) == NOSTR)
25: Shell = SHELL;
26: for (t = 2; t < 4; t++)
27: sig[t-2] = signal(t, SIG_IGN);
28: t = vfork();
29: if (t == 0) {
30: for (t = 2; t < 4; t++)
31: if (sig[t-2] != SIG_IGN)
32: signal(t, SIG_DFL);
33: execl(Shell, Shell, "-c", str, 0);
34: perror(Shell);
35: _exit(1);
36: }
37: while (wait(stat) != t)
38: ;
39: if (t == -1)
40: perror("fork");
41: for (t = 2; t < 4; t++)
42: signal(t, sig[t-2]);
43: printf("!\n");
44: return(0);
45: }
46:
47: /*
48: * Fork an interactive shell.
49: */
50:
51: dosh(str)
52: char *str;
53: {
54: int (*sig[2])(), stat[1];
55: register int t;
56: char *Shell;
57:
58: if ((Shell = value("SHELL")) == NOSTR)
59: Shell = SHELL;
60: for (t = 2; t < 4; t++)
61: sig[t-2] = signal(t, SIG_IGN);
62: t = vfork();
63: if (t == 0) {
64: for (t = 2; t < 4; t++)
65: if (sig[t-2] != SIG_IGN)
66: signal(t, SIG_DFL);
67: execl(Shell, Shell, 0);
68: perror(Shell);
69: _exit(1);
70: }
71: while (wait(stat) != t)
72: ;
73: if (t == -1)
74: perror("fork");
75: for (t = 2; t < 4; t++)
76: signal(t, sig[t-2]);
77: putchar('\n');
78: return(0);
79: }
80:
81: /*
82: * Print out a nice help message from some file or another.
83: */
84:
85: help()
86: {
87: register c;
88: register FILE *f;
89:
90: if ((f = fopen(HELPFILE, "r")) == NULL) {
91: printf("No help just now.\n");
92: return(1);
93: }
94: while ((c = getc(f)) != EOF)
95: putchar(c);
96: fclose(f);
97: return(0);
98: }
99:
100: /*
101: * Change user's working directory.
102: */
103:
104: schdir(str)
105: char *str;
106: {
107: register char *cp;
108:
109: for (cp = str; *cp == ' '; cp++)
110: ;
111: if (*cp == '\0')
112: cp = homedir;
113: else
114: if ((cp = expand(cp)) == NOSTR)
115: return(1);
116: if (chdir(cp) < 0) {
117: perror(cp);
118: return(1);
119: }
120: return(0);
121: }
122:
123: /*
124: * Reply to a list of messages. Extract each name from the
125: * message header and send them off to mail1()
126: */
127:
128: respond(msgvec)
129: int *msgvec;
130: {
131: struct message *mp;
132: char *cp, buf[2 * LINESIZE], *rcv;
133: struct name *np;
134: struct header head;
135: char *netmap();
136:
137: if (msgvec[1] != 0) {
138: printf("Sorry, can't reply to multiple messages at once\n");
139: return(1);
140: }
141: mp = &message[msgvec[0] - 1];
142: rcv = nameof(mp);
143: strcpy(buf, "");
144: cp = hfield("to", mp);
145: if (cp != NOSTR)
146: strcpy(buf, cp);
147: np = elide(extract(buf));
148: mapf(np, rcv);
149: np = delname(np, myname);
150: head.h_seq = 1;
151: cp = detract(np);
152: if (cp != NOSTR) {
153: strcpy(buf, cp);
154: strcat(buf, " ");
155: strcat(buf, rcv);
156: }
157: else
158: strcpy(buf, rcv);
159: head.h_to = buf;
160: head.h_subject = hfield("subject", mp);
161: if (head.h_subject == NOSTR)
162: head.h_subject = hfield("subj", mp);
163: head.h_cc = NOSTR;
164: cp = hfield("cc", mp);
165: if (cp != NOSTR) {
166: np = elide(extract(cp));
167: mapf(np, rcv);
168: np = delname(np, myname);
169: head.h_cc = detract(np);
170: }
171: head.h_bcc = NOSTR;
172: mail1(&head);
173: return(0);
174: }
175:
176: /*
177: * Preserve the named messages, so that they will be sent
178: * back to the system mailbox.
179: */
180:
181: preserve(msgvec)
182: int *msgvec;
183: {
184: register struct message *mp;
185: register int *ip, mesg;
186:
187: if (edit) {
188: printf("Cannot \"preserve\" in edit mode\n");
189: return(1);
190: }
191: for (ip = msgvec; *ip != NULL; ip++) {
192: mesg = *ip;
193: mp = &message[mesg-1];
194: mp->m_flag |= MPRESERVE;
195: dot = mp;
196: }
197: return(0);
198: }
199:
200: /*
201: * Print the size of each message.
202: */
203:
204: messize(msgvec)
205: int *msgvec;
206: {
207: register struct message *mp;
208: register int *ip, mesg;
209:
210: for (ip = msgvec; *ip != NULL; ip++) {
211: mesg = *ip;
212: mp = &message[mesg-1];
213: printf("%d: %d\n", mesg, msize(mp));
214: }
215: return(0);
216: }
217:
218: /*
219: * Quit quickly. If we are sourcing, just pop the input level
220: * by returning an error.
221: */
222:
223: rexit(e)
224: {
225: if (sourcing)
226: return(1);
227: exit(e);
228: }
229:
230: /*
231: * Set or display a variable value. Syntax is similar to that
232: * of csh.
233: */
234:
235: set(arglist)
236: char **arglist;
237: {
238: register struct var *vp;
239: register char *cp, *cp2;
240: char varbuf[BUFSIZ], **ap, **p;
241: int errs, h, s;
242:
243: if (argcount(arglist) == 0) {
244: for (h = 0, s = 1; h < HSHSIZE; h++)
245: for (vp = variables[h]; vp != NOVAR; vp = vp->v_link)
246: s++;
247: ap = (char **) salloc(s * sizeof *ap);
248: for (h = 0, p = ap; h < HSHSIZE; h++)
249: for (vp = variables[h]; vp != NOVAR; vp = vp->v_link)
250: *p++ = vp->v_name;
251: *p = NOSTR;
252: sort(ap);
253: for (p = ap; *p != NOSTR; p++)
254: printf("%s\t%s\n", *p, value(*p));
255: return(0);
256: }
257: errs = 0;
258: for (ap = arglist; *ap != NOSTR; ap++) {
259: cp = *ap;
260: cp2 = varbuf;
261: while (*cp != '=' && *cp != '\0')
262: *cp2++ = *cp++;
263: *cp2 = '\0';
264: if (*cp == '\0')
265: cp = "";
266: else
267: cp++;
268: if (equal(varbuf, "")) {
269: printf("Non-null variable name required\n");
270: errs++;
271: continue;
272: }
273: assign(varbuf, cp);
274: }
275: return(errs);
276: }
277:
278: /*
279: * Unset a bunch of variable values.
280: */
281:
282: unset(arglist)
283: char **arglist;
284: {
285: register struct var *vp, *vp2;
286: register char *cp;
287: int errs, h;
288: char **ap;
289:
290: errs = 0;
291: for (ap = arglist; *ap != NOSTR; ap++) {
292: if ((vp2 = lookup(*ap)) == NOVAR) {
293: if (!sourcing) {
294: printf("\"%s\": undefined variable\n", *ap);
295: errs++;
296: }
297: continue;
298: }
299: h = hash(*ap);
300: if (vp2 == variables[h]) {
301: variables[h] = variables[h]->v_link;
302: vfree(vp2->v_name);
303: vfree(vp2->v_value);
304: cfree(vp2);
305: continue;
306: }
307: for (vp = variables[h]; vp->v_link != vp2; vp = vp->v_link)
308: ;
309: vp->v_link = vp2->v_link;
310: vfree(vp2->v_name);
311: vfree(vp2->v_value);
312: cfree(vp2);
313: }
314: return(errs);
315: }
316:
317: /*
318: * Put add users to a group.
319: */
320:
321: group(argv)
322: char **argv;
323: {
324: register struct grouphead *gh;
325: register struct group *gp;
326: register int h;
327: int s;
328: char **ap, *gname, **p;
329:
330: if (argcount(argv) == 0) {
331: for (h = 0, s = 1; h < HSHSIZE; h++)
332: for (gh = groups[h]; gh != NOGRP; gh = gh->g_link)
333: s++;
334: ap = (char **) salloc(s * sizeof *ap);
335: for (h = 0, p = ap; h < HSHSIZE; h++)
336: for (gh = groups[h]; gh != NOGRP; gh = gh->g_link)
337: *p++ = gh->g_name;
338: *p = NOSTR;
339: sort(ap);
340: for (p = ap; *p != NOSTR; p++)
341: printgroup(*p);
342: return(0);
343: }
344: if (argcount(argv) == 1) {
345: printgroup(*argv);
346: return(0);
347: }
348: gname = *argv;
349: h = hash(gname);
350: if ((gh = findgroup(gname)) == NOGRP) {
351: gh = (struct grouphead *) calloc(sizeof *gh, 1);
352: gh->g_name = vcopy(gname);
353: gh->g_list = NOGE;
354: gh->g_link = groups[h];
355: groups[h] = gh;
356: }
357:
358: /*
359: * Insert names from the command list into the group.
360: * Who cares if there are duplicates? They got tossed
361: * later anyway.
362: */
363:
364: for (ap = argv+1; *ap != NOSTR; ap++) {
365: gp = (struct group *) calloc(sizeof *gp, 1);
366: gp->ge_name = vcopy(*ap);
367: gp->ge_link = gh->g_list;
368: gh->g_list = gp;
369: }
370: return(0);
371: }
372:
373: /*
374: * Sort the passed string vecotor into ascending dictionary
375: * order.
376: */
377:
378: sort(list)
379: char **list;
380: {
381: register char **ap;
382: int diction();
383:
384: for (ap = list; *ap != NOSTR; ap++)
385: ;
386: if (ap-list < 2)
387: return;
388: qsort(list, ap-list, sizeof *list, diction);
389: }
390:
391: /*
392: * Do a dictionary order comparison of the arguments from
393: * qsort.
394: */
395:
396: diction(a, b)
397: register char **a, **b;
398: {
399: return(strcmp(*a, *b));
400: }
401:
402: /*
403: * The do nothing command for comments.
404: */
405:
406: null(e)
407: {
408: return(0);
409: }
410:
411: /*
412: * Print out the current edit file, if we are editting.
413: * Otherwise, print the name of the person who's mail
414: * we are reading.
415: */
416:
417: file(e)
418: {
419: register char *cp;
420:
421: if (edit)
422: printf("Reading \"%s\"\n", editfile);
423: else
424: printf("Reading %s's mail\n", rindex(mailname, '/') + 1);
425: return(0);
426: }
427:
428: /*
429: * Expand file names like echo
430: */
431:
432: echo(argv)
433: char **argv;
434: {
435: register char **ap;
436: register char *cp;
437:
438: for (ap = argv; *ap != NOSTR; ap++) {
439: cp = *ap;
440: if ((cp = expand(cp)) != NOSTR)
441: printf("%s\n", cp);
442: }
443: return(0);
444: }
445:
446: /*
447: * Reply to a series of messages by simply mailing to the senders
448: * and not messing around with the To: and Cc: lists as in normal
449: * reply.
450: */
451:
452: Respond(msgvec)
453: int msgvec[];
454: {
455: struct header head;
456: struct message *mp;
457: register int s, *ap;
458: register char *cp, *subject;
459:
460: for (s = 0, ap = msgvec; *ap != 0; ap++) {
461: mp = &message[*ap - 1];
462: s += strlen(nameof(mp)) + 1;
463: }
464: if (s == 0)
465: return(0);
466: cp = salloc(s + 2);
467: head.h_to = cp;
468: for (ap = msgvec; *ap != 0; ap++) {
469: mp = &message[*ap - 1];
470: cp = copy(nameof(mp), cp);
471: *cp++ = ' ';
472: }
473: *--cp = 0;
474: mp = &message[msgvec[0] - 1];
475: subject = hfield("subject", mp);
476: if (subject == NOSTR)
477: subject = hfield("subj", mp);
478: head.h_subject = subject;
479: head.h_cc = NOSTR;
480: head.h_bcc = NOSTR;
481: head.h_seq = 0;
482: mail1(&head);
483: return(0);
484: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.