BSD 3 development
[unix-history] / .ref-BSD-2 / src / Mail / aux.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#include <sgtty.h>
7
8/*
9 * Mail -- a mail program
10 *
11 * Auxiliary functions.
12 */
13
14/*
15 * Return a pointer to a dynamic copy of the argument.
16 */
17
18char *
19savestr(str)
20 char *str;
21{
22 register char *cp, *cp2, *top;
23
24 for (cp = str; *cp; cp++)
25 ;
26 top = salloc(cp-str + 1);
27 if (top == NOSTR)
28 return(NOSTR);
29 for (cp = str, cp2 = top; *cp; cp++)
30 *cp2++ = *cp;
31 *cp2 = 0;
32 return(top);
33}
34
35/*
36 * Copy the name from the passed header line into the passed
37 * name buffer. Null pad the name buffer.
38 */
39
40copyname(linebuf, nbuf)
41 char *linebuf, *nbuf;
42{
43 register char *cp, *cp2;
44
45 for (cp = linebuf + 5, cp2 = nbuf; *cp != ' ' && cp2-nbuf < 8; cp++)
46 *cp2++ = *cp;
47 while (cp2-nbuf < 8)
48 *cp2++ = 0;
49}
50
51/*
52 * Announce a fatal error and die.
53 */
54
55panic(str)
56 char *str;
57{
58 prs("panic: ");
59 prs(str);
60 prs("\n");
61 exit(1);
62}
63
64/*
65 * Catch stdio errors and report them more nicely.
66 */
67
68_error(str)
69 char *str;
70{
71 prs("Stdio Error: ");
72 prs(str);
73 prs("\n");
74 abort();
75}
76
77/*
78 * Print a string on diagnostic output.
79 */
80
81prs(str)
82 char *str;
83{
84 register char *s;
85
86 for (s = str; *s; s++)
87 ;
88 write(2, str, s-str);
89}
90
91/*
92 * Touch the named message by setting its MTOUCH flag.
93 * Touched messages have the effect of not being sent
94 * back to the system mailbox on exit.
95 */
96
97touch(mesg)
98{
99 if (mesg >= 1 && mesg <= msgCount)
100 message[mesg-1].m_flag |= MTOUCH;
101}
102
103/*
104 * Test to see if the passed file name is a directory.
105 * Return true if it is.
106 */
107
108isdir(name)
109 char name[];
110{
111 struct stat sbuf;
112
113 if (stat(name, &sbuf) < 0)
114 return(0);
115 return((sbuf.st_mode & S_IFMT) == S_IFDIR);
116}
117
118/*
119 * Compute the size in characters of the passed message
120 */
121
122unsigned int
123msize(messp)
124 struct message *messp;
125{
126 register struct message *mp;
127
128 mp = messp;
129 return(mp->m_size);
130}
131
132/*
133 * Count the number of arguments in the given string raw list.
134 */
135
136argcount(argv)
137 char **argv;
138{
139 register char **ap;
140
141 for (ap = argv; *ap != NOSTR; ap++)
142 ;
143 return(ap-argv);
144}
145
146/*
147 * Given a file address, determine the
148 * block number it represents.
149 */
150
151blockof(off)
152 off_t off;
153{
154 off_t a;
155
156 a = off >> 9;
157 a &= 077777;
158 return((int) a);
159}
160
161/*
162 * Take a file address, and determine
163 * its offset in the current block.
164 */
165
166offsetof(off)
167 off_t off;
168{
169 off_t a;
170
171 a = off & 0777;
172 return((int) a);
173}
174
175/*
176 * Determine if the passed file is actually a tty, via a call to
177 * gtty. This is not totally reliable, but . . .
178 */
179
180isatty(f)
181{
182 struct sgttyb buf;
183
184 if (gtty(f, &buf) < 0)
185 return(0);
186 return(1);
187}
188
189/*
190 * Return the desired header line from the passed message
191 * pointer (or NOSTR if the desired header field is not available.
192 */
193
194char *
195hfield(field, mp)
196 char field[];
197 struct message *mp;
198{
199 FILE *ibuf;
200 char linebuf[LINESIZE];
201 register char *cp, *cp2;
202 int hfc;
203
204 ibuf = setinput(mp);
205 hfc = 0;
206 while (readline(ibuf, linebuf) > 0 && hfc < HDRFIELDS) {
207 if (equal(linebuf, ""))
208 return(NOSTR);
209 cp = linebuf;
210 cp2 = field;
211 while (raise(*cp++) == raise(*cp2++))
212 ;
213 if (*--cp == ':' && *--cp2 == '\0') {
214 cp++;
215 while (any(*cp, " \t"))
216 cp++;
217 return(savestr(cp));
218 }
219 hfc++;
220 }
221 return(NOSTR);
222}
223
224/*
225 * The following code deals with input stacking to do source
226 * commands. All but the current file pointer are saved on
227 * the stack.
228 */
229
230static int ssp = -1; /* Top of file stack */
231static FILE *sstack[_NFILE]; /* Saved input files */
232
233/*
234 * Pushdown current input file and switch to a new one.
235 * Set the global flag "sourcing" so that others will realize
236 * that they are no longer reading from a tty (in all probability).
237 */
238
239source(name)
240 char name[];
241{
242 register FILE *fi;
243
244 if ((fi = fopen(name, "r")) == NULL) {
245 perror(name);
246 return(1);
247 }
248 if (ssp >= _NFILE-2) {
249 printf("Too much \"sourcing\" going on.\n");
250 fclose(fi);
251 return(1);
252 }
253 sstack[++ssp] = input;
254 input = fi;
255 sourcing++;
256 return(0);
257}
258
259/*
260 * Source a file, but do nothing if the file cannot be opened.
261 */
262
263source1(name)
264 char name[];
265{
266 register int f;
267
268 if ((f = open(name, 0)) < 0)
269 return(0);
270 close(f);
271 source(name);
272}
273
274/*
275 * Pop the current input back to the previous level.
276 * Update the "sourcing" flag as appropriate.
277 */
278
279unstack()
280{
281 if (ssp < 0) {
282 printf("\"Source\" stack over-pop.\n");
283 sourcing = 0;
284 return(1);
285 }
286 fclose(input);
287 input = sstack[ssp--];
288 if (ssp < 0)
289 sourcing = 0;
290 return(0);
291}
292
293/*
294 * Touch the indicated file.
295 * This is nifty for the shell.
296 */
297
298alter(name)
299 char name[];
300{
301 register int pid, f;
302 char w;
303
304 if ((pid = fork()) != 0)
305 return;
306 clrbuf(stdout);
307 clrbuf(stderr);
308 clrbuf(stdin);
309 sleep(1);
310 if ((f = open(name, 0)) < 0)
311 exit(1);
312 read(f, &w, 1);
313 exit(0);
314}
315
316/*
317 * Examine the passed line buffer and
318 * return true if it is all blanks and tabs.
319 */
320
321blankline(linebuf)
322 char linebuf[];
323{
324 register char *cp;
325
326 for (cp = linebuf; *cp; cp++)
327 if (!any(*cp, " \t"))
328 return(0);
329 return(1);
330}
331
332/*
333 * Fetch the sender's name from the passed message.
334 */
335
336char *
337nameof(mp)
338 register struct message *mp;
339{
340 static char namebuf[NAMESIZE];
341 char linebuf[LINESIZE];
342 register char *cp, *cp2;
343 register FILE *ibuf;
344
345 ibuf = setinput(mp);
346 copy("", namebuf);
347 if (readline(ibuf, linebuf) <= 0)
348 return(namebuf);
349 for (cp = linebuf; *cp != ' '; cp++)
350 ;
351 while (any(*cp, " \t"))
352 cp++;
353 for (cp2 = namebuf; *cp && !any(*cp, " \t") &&
354 cp2-namebuf < NAMESIZE-1; *cp2++ = *cp++)
355 ;
356 *cp2 = '\0';
357 return(namebuf);
358}