|
|
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: dot = mp;
143: rcv = nameof(mp);
144: strcpy(buf, "");
145: cp = hfield("to", mp);
146: if (cp != NOSTR)
147: strcpy(buf, cp);
148: np = elide(extract(buf, GTO));
149: /* rcv = rename(rcv); */
150: mapf(np, rcv);
151: np = delname(np, myname);
152: head.h_seq = 1;
153: cp = detract(np, 0);
154: if (cp != NOSTR) {
155: strcpy(buf, cp);
156: strcat(buf, " ");
157: strcat(buf, rcv);
158: }
159: else
160: strcpy(buf, rcv);
161: head.h_to = buf;
162: head.h_subject = hfield("subject", mp);
163: if (head.h_subject == NOSTR)
164: head.h_subject = hfield("subj", mp);
165: head.h_cc = NOSTR;
166: cp = hfield("cc", mp);
167: if (cp != NOSTR) {
168: np = elide(extract(cp, GCC));
169: mapf(np, rcv);
170: np = delname(np, myname);
171: head.h_cc = detract(np, 0);
172: }
173: head.h_bcc = NOSTR;
174: mail1(&head);
175: return(0);
176: }
177:
178: /*
179: * Preserve the named messages, so that they will be sent
180: * back to the system mailbox.
181: */
182:
183: preserve(msgvec)
184: int *msgvec;
185: {
186: register struct message *mp;
187: register int *ip, mesg;
188:
189: if (edit) {
190: printf("Cannot \"preserve\" in edit mode\n");
191: return(1);
192: }
193: for (ip = msgvec; *ip != NULL; ip++) {
194: mesg = *ip;
195: mp = &message[mesg-1];
196: mp->m_flag |= MPRESERVE;
197: dot = mp;
198: }
199: return(0);
200: }
201:
202: /*
203: * Print the size of each message.
204: */
205:
206: messize(msgvec)
207: int *msgvec;
208: {
209: register struct message *mp;
210: register int *ip, mesg;
211:
212: for (ip = msgvec; *ip != NULL; ip++) {
213: mesg = *ip;
214: mp = &message[mesg-1];
215: printf("%d: %d\n", mesg, msize(mp));
216: }
217: return(0);
218: }
219:
220: /*
221: * Quit quickly. If we are sourcing, just pop the input level
222: * by returning an error.
223: */
224:
225: rexit(e)
226: {
227: if (sourcing)
228: return(1);
229: exit(e);
230: }
231:
232: /*
233: * Set or display a variable value. Syntax is similar to that
234: * of csh.
235: */
236:
237: set(arglist)
238: char **arglist;
239: {
240: register struct var *vp;
241: register char *cp, *cp2;
242: char varbuf[BUFSIZ], **ap, **p;
243: int errs, h, s;
244:
245: if (argcount(arglist) == 0) {
246: for (h = 0, s = 1; h < HSHSIZE; h++)
247: for (vp = variables[h]; vp != NOVAR; vp = vp->v_link)
248: s++;
249: ap = (char **) salloc(s * sizeof *ap);
250: for (h = 0, p = ap; h < HSHSIZE; h++)
251: for (vp = variables[h]; vp != NOVAR; vp = vp->v_link)
252: *p++ = vp->v_name;
253: *p = NOSTR;
254: sort(ap);
255: for (p = ap; *p != NOSTR; p++)
256: printf("%s\t%s\n", *p, value(*p));
257: return(0);
258: }
259: errs = 0;
260: for (ap = arglist; *ap != NOSTR; ap++) {
261: cp = *ap;
262: cp2 = varbuf;
263: while (*cp != '=' && *cp != '\0')
264: *cp2++ = *cp++;
265: *cp2 = '\0';
266: if (*cp == '\0')
267: cp = "";
268: else
269: cp++;
270: if (equal(varbuf, "")) {
271: printf("Non-null variable name required\n");
272: errs++;
273: continue;
274: }
275: assign(varbuf, cp);
276: }
277: return(errs);
278: }
279:
280: /*
281: * Unset a bunch of variable values.
282: */
283:
284: unset(arglist)
285: char **arglist;
286: {
287: register struct var *vp, *vp2;
288: register char *cp;
289: int errs, h;
290: char **ap;
291:
292: errs = 0;
293: for (ap = arglist; *ap != NOSTR; ap++) {
294: if ((vp2 = lookup(*ap)) == NOVAR) {
295: if (!sourcing) {
296: printf("\"%s\": undefined variable\n", *ap);
297: errs++;
298: }
299: continue;
300: }
301: h = hash(*ap);
302: if (vp2 == variables[h]) {
303: variables[h] = variables[h]->v_link;
304: vfree(vp2->v_name);
305: vfree(vp2->v_value);
306: cfree(vp2);
307: continue;
308: }
309: for (vp = variables[h]; vp->v_link != vp2; vp = vp->v_link)
310: ;
311: vp->v_link = vp2->v_link;
312: vfree(vp2->v_name);
313: vfree(vp2->v_value);
314: cfree(vp2);
315: }
316: return(errs);
317: }
318:
319: /*
320: * Put add users to a group.
321: */
322:
323: group(argv)
324: char **argv;
325: {
326: register struct grouphead *gh;
327: register struct group *gp;
328: register int h;
329: int s;
330: char **ap, *gname, **p;
331:
332: if (argcount(argv) == 0) {
333: for (h = 0, s = 1; h < HSHSIZE; h++)
334: for (gh = groups[h]; gh != NOGRP; gh = gh->g_link)
335: s++;
336: ap = (char **) salloc(s * sizeof *ap);
337: for (h = 0, p = ap; h < HSHSIZE; h++)
338: for (gh = groups[h]; gh != NOGRP; gh = gh->g_link)
339: *p++ = gh->g_name;
340: *p = NOSTR;
341: sort(ap);
342: for (p = ap; *p != NOSTR; p++)
343: printgroup(*p);
344: return(0);
345: }
346: if (argcount(argv) == 1) {
347: printgroup(*argv);
348: return(0);
349: }
350: gname = *argv;
351: h = hash(gname);
352: if ((gh = findgroup(gname)) == NOGRP) {
353: gh = (struct grouphead *) calloc(sizeof *gh, 1);
354: gh->g_name = vcopy(gname);
355: gh->g_list = NOGE;
356: gh->g_link = groups[h];
357: groups[h] = gh;
358: }
359:
360: /*
361: * Insert names from the command list into the group.
362: * Who cares if there are duplicates? They get tossed
363: * later anyway.
364: */
365:
366: for (ap = argv+1; *ap != NOSTR; ap++) {
367: gp = (struct group *) calloc(sizeof *gp, 1);
368: gp->ge_name = vcopy(*ap);
369: gp->ge_link = gh->g_list;
370: gh->g_list = gp;
371: }
372: return(0);
373: }
374:
375: /*
376: * Sort the passed string vecotor into ascending dictionary
377: * order.
378: */
379:
380: sort(list)
381: char **list;
382: {
383: register char **ap;
384: int diction();
385:
386: for (ap = list; *ap != NOSTR; ap++)
387: ;
388: if (ap-list < 2)
389: return;
390: qsort(list, ap-list, sizeof *list, diction);
391: }
392:
393: /*
394: * Do a dictionary order comparison of the arguments from
395: * qsort.
396: */
397:
398: diction(a, b)
399: register char **a, **b;
400: {
401: return(strcmp(*a, *b));
402: }
403:
404: /*
405: * The do nothing command for comments.
406: */
407:
408: null(e)
409: {
410: return(0);
411: }
412:
413: /*
414: * Print out the current edit file, if we are editting.
415: * Otherwise, print the name of the person who's mail
416: * we are reading.
417: */
418:
419: file(e)
420: {
421: register char *cp;
422:
423: if (edit)
424: printf("Reading \"%s\"\n", editfile);
425: else
426: printf("Reading %s's mail\n", rindex(mailname, '/') + 1);
427: return(0);
428: }
429:
430: /*
431: * Expand file names like echo
432: */
433:
434: echo(argv)
435: char **argv;
436: {
437: register char **ap;
438: register char *cp;
439:
440: for (ap = argv; *ap != NOSTR; ap++) {
441: cp = *ap;
442: if ((cp = expand(cp)) != NOSTR)
443: printf("%s\n", cp);
444: }
445: return(0);
446: }
447:
448: /*
449: * Reply to a series of messages by simply mailing to the senders
450: * and not messing around with the To: and Cc: lists as in normal
451: * reply.
452: */
453:
454: Respond(msgvec)
455: int msgvec[];
456: {
457: struct header head;
458: struct message *mp;
459: register int s, *ap;
460: register char *cp, *subject;
461:
462: for (s = 0, ap = msgvec; *ap != 0; ap++) {
463: mp = &message[*ap - 1];
464: dot = mp;
465: s += strlen(nameof(mp)) + 1;
466: }
467: if (s == 0)
468: return(0);
469: cp = salloc(s + 2);
470: head.h_to = cp;
471: for (ap = msgvec; *ap != 0; ap++) {
472: mp = &message[*ap - 1];
473: cp = copy(nameof(mp), cp);
474: *cp++ = ' ';
475: }
476: *--cp = 0;
477: mp = &message[msgvec[0] - 1];
478: subject = hfield("subject", mp);
479: head.h_seq = 0;
480: if (subject == NOSTR)
481: subject = hfield("subj", mp);
482: head.h_subject = subject;
483: if (subject != NOSTR)
484: head.h_seq++;
485: head.h_cc = NOSTR;
486: head.h_bcc = NOSTR;
487: mail1(&head);
488: return(0);
489: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.