BSD 3 development
[unix-history] / .ref-BSD-2 / src / Mail / cmd3.c
CommitLineData
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
18shell(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
52help()
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
71schdir(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
92respond(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
132preserve(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
155messize(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
174rexit(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
186set(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
233unset(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
270group(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
327sort(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
345diction(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
355null(e)
356{
357 return(0);
358}