Commit | Line | Data |
---|---|---|
c9104e93 KS |
1 | /* Copyright (c) 1979 Regents of the University of California */ |
2 | # | |
3 | ||
4 | #include "rcv.h" | |
5 | #include <sys/stat.h> | |
6 | ||
7 | /* | |
8 | * Mail -- a mail program | |
9 | * | |
10 | * Still more user commands. | |
11 | */ | |
12 | ||
13 | /* | |
14 | * Process a shell escape by saving signals, ignoring signals, | |
15 | * and forking a sh -c | |
16 | */ | |
17 | ||
18 | shell(str) | |
19 | char *str; | |
20 | { | |
21 | int (*sig[2])(), stat[1]; | |
22 | register int t; | |
23 | char *Shell; | |
24 | ||
25 | if ((Shell = value("SHELL")) == NOSTR) | |
26 | Shell = "/bin/sh"; | |
27 | for (t = 2; t < 4; t++) | |
28 | sig[t-2] = signal(t, SIG_IGN); | |
29 | t = fork(); | |
30 | if (t == 0) { | |
31 | for (t = 2; t < 4; t++) | |
32 | if (sig[t-2] != SIG_IGN) | |
33 | signal(t, SIG_DFL); | |
34 | execl(Shell, Shell, "-c", str, 0); | |
35 | perror(Shell); | |
36 | exit(1); | |
37 | } | |
38 | while (wait(stat) != t) | |
39 | ; | |
40 | if (t == -1) | |
41 | perror("fork"); | |
42 | for (t = 2; t < 4; t++) | |
43 | signal(t, sig[t-2]); | |
44 | printf("!\n"); | |
45 | return(0); | |
46 | } | |
47 | ||
48 | /* | |
49 | * Print out a nice help message from some file or another. | |
50 | */ | |
51 | ||
52 | help() | |
53 | { | |
54 | register c; | |
55 | register FILE *f; | |
56 | ||
57 | if ((f = fopen(HELPFILE, "r")) == NULL) { | |
58 | printf("No help just now.\n"); | |
59 | return(1); | |
60 | } | |
61 | while ((c = getc(f)) != EOF) | |
62 | putchar(c); | |
63 | fclose(f); | |
64 | return(0); | |
65 | } | |
66 | ||
67 | /* | |
68 | * Change user's working directory. | |
69 | */ | |
70 | ||
71 | schdir(str) | |
72 | char *str; | |
73 | { | |
74 | register char *cp; | |
75 | ||
76 | for (cp = str; *cp == ' '; cp++) | |
77 | ; | |
78 | if (*cp == '\0') | |
79 | cp = homedir; | |
80 | if (chdir(cp) < 0) { | |
81 | perror(cp); | |
82 | return(1); | |
83 | } | |
84 | return(0); | |
85 | } | |
86 | ||
87 | /* | |
88 | * Reply to a list of messages. Extract each name from the | |
89 | * message header and send them off to mail() | |
90 | */ | |
91 | ||
92 | respond(msgvec) | |
93 | int *msgvec; | |
94 | { | |
95 | register struct message *mp; | |
96 | register char **ap; | |
97 | register int *ip; | |
98 | int s; | |
99 | char *cp2, *buf; | |
100 | struct header head; | |
101 | ||
102 | for (ip = msgvec, s = 0; *ip; ip++) { | |
103 | mp = &message[*ip - 1]; | |
104 | s += strlen(nameof(mp))+1; | |
105 | } | |
106 | buf = salloc(s+1); | |
107 | cp2 = buf; | |
108 | for (ip = msgvec; *ip; ip++) { | |
109 | touch(*ip); | |
110 | mp = &message[*ip - 1]; | |
111 | dot = mp; | |
112 | cp2 = copy(nameof(mp), cp2); | |
113 | *cp2++ = ' '; | |
114 | } | |
115 | if (cp2 != buf) | |
116 | cp2--; | |
117 | *cp2 = '\0'; | |
118 | mp = &message[msgvec[0]-1]; | |
119 | head.h_seq = 1; | |
120 | head.h_to = buf; | |
121 | head.h_subj = hfield("subj", mp); | |
122 | head.h_cc = hfield("cc", mp); | |
123 | mail1(&head); | |
124 | return(0); | |
125 | } | |
126 | ||
127 | /* | |
128 | * Preserve the named messages, so that they will be sent | |
129 | * back to the system mailbox. | |
130 | */ | |
131 | ||
132 | preserve(msgvec) | |
133 | int *msgvec; | |
134 | { | |
135 | register struct message *mp; | |
136 | register int *ip, mesg; | |
137 | ||
138 | if (edit) { | |
139 | printf("Cannot \"preserve\" in edit mode\n"); | |
140 | return(1); | |
141 | } | |
142 | for (ip = msgvec; *ip != NULL; ip++) { | |
143 | mesg = *ip; | |
144 | mp = &message[mesg-1]; | |
145 | mp->m_flag |= MPRESERVE; | |
146 | dot = mp; | |
147 | } | |
148 | return(0); | |
149 | } | |
150 | ||
151 | /* | |
152 | * Print the size of each message. | |
153 | */ | |
154 | ||
155 | messize(msgvec) | |
156 | int *msgvec; | |
157 | { | |
158 | register struct message *mp; | |
159 | register int *ip, mesg; | |
160 | ||
161 | for (ip = msgvec; *ip != NULL; ip++) { | |
162 | mesg = *ip; | |
163 | mp = &message[mesg-1]; | |
164 | printf("%d: %d\n", mesg, msize(mp)); | |
165 | } | |
166 | return(0); | |
167 | } | |
168 | ||
169 | /* | |
170 | * Quit quickly. If we are sourcing, just pop the input level | |
171 | * by returning an error. | |
172 | */ | |
173 | ||
174 | rexit(e) | |
175 | { | |
176 | if (sourcing) | |
177 | return(1); | |
178 | exit(e); | |
179 | } | |
180 | ||
181 | /* | |
182 | * Set or display a variable value. Syntax is similar to that | |
183 | * of csh. | |
184 | */ | |
185 | ||
186 | set(arglist) | |
187 | char **arglist; | |
188 | { | |
189 | register struct var *vp; | |
190 | register char *cp, *cp2; | |
191 | char varbuf[BUFSIZ], **ap, **p; | |
192 | int errs, h, s; | |
193 | ||
194 | if (argcount(arglist) == 0) { | |
195 | for (h = 0, s = 1; h < HSHSIZE; h++) | |
196 | for (vp = variables[h]; vp != NOVAR; vp = vp->v_link) | |
197 | s++; | |
198 | ap = (char **) salloc(s * sizeof *ap); | |
199 | for (h = 0, p = ap; h < HSHSIZE; h++) | |
200 | for (vp = variables[h]; vp != NOVAR; vp = vp->v_link) | |
201 | *p++ = vp->v_name; | |
202 | *p = NOSTR; | |
203 | sort(ap); | |
204 | for (p = ap; *p != NOSTR; p++) | |
205 | printf("%s\t%s\n", *p, value(*p)); | |
206 | return(0); | |
207 | } | |
208 | errs = 0; | |
209 | for (ap = arglist; *ap != NOSTR; ap++) { | |
210 | cp = *ap; | |
211 | cp2 = varbuf; | |
212 | while (*cp != '=' && *cp != '\0') | |
213 | *cp2++ = *cp++; | |
214 | *cp2 = '\0'; | |
215 | if (*cp == '\0') | |
216 | cp = ""; | |
217 | else | |
218 | cp++; | |
219 | if (equal(varbuf, "")) { | |
220 | printf("Non-null variable name required\n"); | |
221 | errs++; | |
222 | continue; | |
223 | } | |
224 | assign(varbuf, cp); | |
225 | } | |
226 | return(errs); | |
227 | } | |
228 | ||
229 | /* | |
230 | * Unset a bunch of variable values. | |
231 | */ | |
232 | ||
233 | unset(arglist) | |
234 | char **arglist; | |
235 | { | |
236 | register struct var *vp, *vp2; | |
237 | register char *cp; | |
238 | int errs, h; | |
239 | char **ap; | |
240 | ||
241 | errs = 0; | |
242 | for (ap = arglist; *ap != NOSTR; ap++) { | |
243 | if ((vp2 = lookup(*ap)) == NOVAR) { | |
244 | printf("\"%s\": undefined variable\n", *ap); | |
245 | errs++; | |
246 | continue; | |
247 | } | |
248 | h = hash(*ap); | |
249 | if (vp2 == variables[h]) { | |
250 | variables[h] = variables[h]->v_link; | |
251 | vfree(vp2->v_name); | |
252 | vfree(vp2->v_value); | |
253 | cfree(vp2); | |
254 | continue; | |
255 | } | |
256 | for (vp = variables[h]; vp->v_link != vp2; vp = vp->v_link) | |
257 | ; | |
258 | vp->v_link = vp2->v_link; | |
259 | vfree(vp2->v_name); | |
260 | vfree(vp2->v_value); | |
261 | cfree(vp2); | |
262 | } | |
263 | return(errs); | |
264 | } | |
265 | ||
266 | /* | |
267 | * Put add users to a group. | |
268 | */ | |
269 | ||
270 | group(argv) | |
271 | char **argv; | |
272 | { | |
273 | register struct grouphead *gh; | |
274 | register struct group *gp; | |
275 | register int h; | |
276 | int s; | |
277 | char **ap, *gname, **p; | |
278 | ||
279 | if (argcount(argv) == 0) { | |
280 | for (h = 0, s = 1; h < HSHSIZE; h++) | |
281 | for (gh = groups[h]; gh != NOGRP; gh = gh->g_link) | |
282 | s++; | |
283 | ap = (char **) salloc(s * sizeof *ap); | |
284 | for (h = 0, p = ap; h < HSHSIZE; h++) | |
285 | for (gh = groups[h]; gh != NOGRP; gh = gh->g_link) | |
286 | *p++ = gh->g_name; | |
287 | *p = NOSTR; | |
288 | sort(ap); | |
289 | for (p = ap; *p != NOSTR; p++) | |
290 | printgroup(*p); | |
291 | return(0); | |
292 | } | |
293 | if (argcount(argv) == 1) { | |
294 | printgroup(*argv); | |
295 | return(0); | |
296 | } | |
297 | gname = *argv; | |
298 | h = hash(gname); | |
299 | if ((gh = findgroup(gname)) == NOGRP) { | |
300 | gh = (struct grouphead *) calloc(sizeof *gh, 1); | |
301 | gh->g_name = vcopy(gname); | |
302 | gh->g_list = NOGE; | |
303 | gh->g_link = groups[h]; | |
304 | groups[h] = gh; | |
305 | } | |
306 | ||
307 | /* | |
308 | * Insert names from the command list into the group. | |
309 | * Who cares if there are duplicates? They got tossed | |
310 | * later anyway. | |
311 | */ | |
312 | ||
313 | for (ap = argv+1; *ap != NOSTR; ap++) { | |
314 | gp = (struct group *) calloc(sizeof *gp, 1); | |
315 | gp->ge_name = vcopy(*ap); | |
316 | gp->ge_link = gh->g_list; | |
317 | gh->g_list = gp; | |
318 | } | |
319 | return(0); | |
320 | } | |
321 | ||
322 | /* | |
323 | * Sort the passed string vecotor into ascending dictionary | |
324 | * order. | |
325 | */ | |
326 | ||
327 | sort(list) | |
328 | char **list; | |
329 | { | |
330 | register char **ap; | |
331 | int diction(); | |
332 | ||
333 | for (ap = list; *ap != NOSTR; ap++) | |
334 | ; | |
335 | if (ap-list < 2) | |
336 | return; | |
337 | qsort(list, ap-list, sizeof *list, diction); | |
338 | } | |
339 | ||
340 | /* | |
341 | * Do a dictionary order comparison of the arguments from | |
342 | * qsort. | |
343 | */ | |
344 | ||
345 | diction(a, b) | |
346 | register char **a, **b; | |
347 | { | |
348 | return(strcmp(*a, *b)); | |
349 | } | |
350 | ||
351 | /* | |
352 | * The do nothing command for comments. | |
353 | */ | |
354 | ||
355 | null(e) | |
356 | { | |
357 | return(0); | |
358 | } |