0
|
1 /* slocal.c - MH style mailer to write to a local user's mailbox */
|
|
2 #ifndef lint
|
12
|
3 static char ident[] = "@(#)$Id: slocal.c,v 1.1.1.1 2005/04/18 14:46:07 kono Exp $";
|
0
|
4 #endif /* lint */
|
|
5
|
|
6 /* This program implements mail delivery in the MH/MMDF style.
|
|
7
|
|
8 Under SendMail, users should add the line
|
|
9
|
|
10 "| /usr/local/lib/mh/slocal"
|
|
11
|
|
12 to their $HOME/.forward file.
|
|
13
|
|
14 Under MMDF-I, users should (symbolically) link /usr/local/lib/mh/slocal
|
|
15 to $HOME/bin/rcvmail.
|
|
16
|
|
17 Under stand-alone MH, post will automatically run this during local
|
|
18 delivery.
|
|
19
|
|
20 This program should be used ONLY if you have "mts sendmail" or "mts mh"
|
|
21 or "mts mmdf1" set in your MH configuration.
|
|
22 */
|
|
23
|
|
24 /* */
|
13
|
25 #include <unistd.h>
|
0
|
26 #include "../h/mh.h"
|
|
27 #include "../h/dropsbr.h"
|
|
28 #include "../h/rcvmail.h"
|
|
29 #include "../zotnet/tws.h"
|
|
30 #include "../zotnet/mts.h"
|
|
31 #include <pwd.h>
|
|
32 #include <signal.h>
|
|
33 #ifndef V7
|
|
34 #ifndef NOIOCTLH
|
|
35 #include <sys/ioctl.h>
|
|
36 #endif /* NOIOCTLH */
|
|
37 #endif /* not V7 */
|
|
38 #include <sys/stat.h>
|
|
39 #include <utmp.h>
|
|
40 #ifndef UTMP_FILENAME
|
|
41 #ifdef UTMP_FILE
|
|
42 #define UTMP_FILENAME UTMP_FILE
|
|
43 #else
|
|
44 #ifdef _PATH_UTMP
|
|
45 #define UTMP_FILENAME _PATH_UTMP
|
|
46 #else
|
|
47 #define UTMP_FILENAME "/etc/utmp"
|
|
48 #endif
|
|
49 #endif
|
|
50 #endif /* UTMP_FILENAME */
|
|
51 #ifdef LOCALE
|
|
52 #include <locale.h>
|
|
53 #endif
|
|
54
|
|
55
|
|
56 #ifdef MSGID
|
|
57 static int check_msgid (int, char *);
|
|
58
|
|
59 #undef DBM /* used by ndbm.h */
|
|
60 #include <ndbm.h>
|
|
61 #ifdef DBM_SUFFIX
|
|
62 #undef dbm_pagfno
|
|
63 #define dbm_pagfno dbm_dirfno
|
|
64 #endif /* DBM_SUFFIX */
|
|
65
|
|
66 #include <stdio.h>
|
|
67 #include <sys/types.h>
|
|
68 #include <sys/file.h>
|
|
69 #ifdef SYS5
|
|
70 #include <fcntl.h>
|
|
71 #endif
|
12
|
72 //#ifdef UNISTD
|
0
|
73 #include <unistd.h>
|
12
|
74 //#endif
|
0
|
75 #if defined(LOCKF) && !defined(F_ULOCK)
|
|
76 #include <sys/fcntl.h>
|
|
77 #endif /* LOCKF */
|
|
78
|
|
79 #endif
|
|
80
|
|
81
|
|
82 #define NVEC 100
|
|
83
|
|
84 /* */
|
|
85
|
|
86 static struct swit switches[] = {
|
|
87 #define ADDRSW 0
|
|
88 "addr address", 0,
|
|
89 #define USERSW 1
|
|
90 "user name", 0,
|
|
91 #define FILESW 2
|
|
92 "file file", 0,
|
|
93 #define SENDSW 3
|
|
94 "sender address", 0,
|
|
95 #define MBOXSW 4
|
|
96 "mailbox file", 0,
|
|
97 #define HOMESW 5
|
|
98 "home directory", -4,
|
|
99 #define INFOSW 6
|
|
100 "info data", 0,
|
|
101
|
|
102 #define MAILSW 7
|
|
103 "maildelivery file", 0,
|
|
104
|
|
105 #define VERBSW 8
|
|
106 "verbose", 0,
|
|
107 #define NVERBSW 9
|
|
108 "noverbose", 0,
|
|
109
|
|
110 #define DEBUGSW 10
|
|
111 "debug", 0,
|
|
112
|
|
113 #define HELPSW 11
|
|
114 "help", 4,
|
|
115
|
|
116 NULL, 0
|
|
117 };
|
|
118
|
|
119 /* */
|
|
120
|
|
121 static int debug = 0;
|
|
122 static int globbed = 0;
|
|
123 static int parsed = 0;
|
|
124 static int utmped = 0;
|
|
125 static int verbose = 0;
|
|
126 #ifdef SETMG
|
|
127 static gid_t mailgroup;
|
|
128 #endif /* SETMG */
|
|
129
|
|
130 static char *addr = NULLCP;
|
|
131 static char *user = NULLCP;
|
|
132 static char *info = NULLCP;
|
|
133 static char *file = NULLCP;
|
|
134 static char *sender = NULLCP;
|
|
135 static char *unixfrom = NULLCP;
|
|
136 static char *mbox = NULLCP;
|
|
137 static char *home = NULLCP;
|
|
138
|
|
139
|
|
140 static struct passwd *pw;
|
|
141
|
|
142
|
|
143 static char ddate[BUFSIZ];
|
|
144
|
|
145 struct tws *now;
|
|
146
|
|
147
|
|
148 static jmp_buf myctx;
|
|
149
|
|
150 /* */
|
|
151
|
|
152 struct pair {
|
|
153 char *p_name;
|
|
154 char *p_value;
|
|
155
|
|
156 char p_flags;
|
|
157 #define P_NIL 0x00
|
|
158 #define P_ADR 0x01
|
|
159 #define P_HID 0x02
|
|
160 #define P_CHK 0x04
|
|
161 };
|
|
162
|
|
163 static struct pair *lookup ();
|
|
164
|
|
165
|
|
166 static struct pair hdrs[NVEC + 1] = {
|
|
167 "source", NULL, P_HID,
|
|
168 "addr", NULL, P_HID,
|
|
169
|
|
170 "Return-Path", NULL, P_ADR,
|
|
171 "Reply-To", NULL, P_ADR,
|
|
172 "From", NULL, P_ADR,
|
|
173 "Sender", NULL, P_ADR,
|
|
174 "To", NULL, P_ADR,
|
|
175 "cc", NULL, P_ADR,
|
|
176 "Resent-Reply-To", NULL, P_ADR,
|
|
177 "Resent-From", NULL, P_ADR,
|
|
178 "Resent-Sender", NULL, P_ADR,
|
|
179 "Resent-To", NULL, P_ADR,
|
|
180 "Resent-cc", NULL, P_ADR,
|
|
181
|
|
182 NULL
|
|
183 };
|
|
184
|
|
185
|
|
186 static struct pair vars[] = {
|
|
187 "sender", NULL, P_NIL,
|
|
188 "address", NULL, P_NIL,
|
|
189 "size", NULL, P_NIL,
|
|
190 "reply-to", NULL, P_CHK,
|
|
191 "info", NULL, P_NIL,
|
|
192
|
|
193 NULL
|
|
194 };
|
|
195
|
|
196 static char *rcvstore;
|
|
197
|
|
198 /* */
|
|
199
|
|
200 extern char **environ;
|
|
201
|
|
202 static void adorn ();
|
|
203 static TYPESIG alrmser ();
|
|
204
|
|
205
|
|
206 off_t lseek ();
|
|
207 #ifndef __STDC__
|
|
208 #ifdef SYS5
|
|
209 struct passwd *getpwnam ();
|
|
210 #endif /* SYS5 */
|
|
211 #endif
|
|
212 static int localmail(), usr_delivery(), split(), parse(), logged_in();
|
|
213 static int timely(), usr_file(), usr_pipe(), copyfile();
|
|
214 static expand(), glob(), copyinfo();
|
|
215
|
|
216 /* */
|
|
217
|
|
218 /* ARGSUSED */
|
|
219
|
|
220 main (argc, argv, envp)
|
|
221 int argc;
|
|
222 char **argv,
|
|
223 **envp;
|
|
224 {
|
|
225 int fd;
|
|
226 FILE *fp = stdin;
|
|
227 char *cp,
|
|
228 *mdlvr = NULL,
|
|
229 buf[100],
|
|
230 from[BUFSIZ],
|
|
231 mailbox[BUFSIZ],
|
|
232 tmpfil[BUFSIZ],
|
|
233 **argp = argv + 1;
|
|
234
|
|
235 #ifdef LOCALE
|
|
236 setlocale(LC_ALL, "");
|
|
237 #endif
|
|
238 #ifdef JAPAN
|
|
239 ml_init();
|
|
240 #endif
|
|
241 invo_name = r1bindex (*argv, '/');
|
|
242 m_foil (NULLCP);
|
|
243 mts_init (invo_name);
|
|
244
|
|
245 /* */
|
|
246
|
|
247 while (cp = *argp++) {
|
|
248 if (*cp == '-')
|
|
249 switch (smatch (++cp, switches)) {
|
|
250 case AMBIGSW:
|
|
251 ambigsw (cp, switches);
|
|
252 done (1);
|
|
253 case UNKWNSW:
|
|
254 adios (NULLCP, "-%s unknown", cp);
|
|
255 case HELPSW:
|
|
256 (void) sprintf (buf, "%s [switches] [address info sender]",
|
|
257 invo_name);
|
|
258 help (buf, switches);
|
|
259 done (1);
|
|
260
|
|
261 case ADDRSW:
|
|
262 if (!(addr = *argp++))/* allow -xyz arguments */
|
|
263 adios (NULLCP, "missing argument to %s", argp[-2]);
|
|
264 continue;
|
|
265 case INFOSW:
|
|
266 if (!(info = *argp++))/* allow -xyz arguments */
|
|
267 adios (NULLCP, "missing argument to %s", argp[-2]);
|
|
268 continue;
|
|
269 case USERSW:
|
|
270 if (!(user = *argp++))/* allow -xyz arguments */
|
|
271 adios (NULLCP, "missing argument to %s", argp[-2]);
|
|
272 continue;
|
|
273 case FILESW:
|
|
274 if (!(file = *argp++) || *file == '-')
|
|
275 adios (NULLCP, "missing argument to %s", argp[-2]);
|
|
276 continue;
|
|
277 case SENDSW:
|
|
278 if (!(sender = *argp++))/* allow -xyz arguments */
|
|
279 adios (NULLCP, "missing argument to %s", argp[-2]);
|
|
280 continue;
|
|
281 case MBOXSW:
|
|
282 if (!(mbox = *argp++) || *mbox == '-')
|
|
283 adios (NULLCP, "missing argument to %s", argp[-2]);
|
|
284 continue;
|
|
285 case HOMESW:
|
|
286 if (!(home = *argp++) || *home == '-')
|
|
287 adios (NULLCP, "missing argument to %s", argp[-2]);
|
|
288 continue;
|
|
289
|
|
290 case MAILSW:
|
|
291 if (!(cp = *argp++) || *cp == '-')
|
|
292 adios (NULLCP, "missing argument to %s", argp[-2]);
|
|
293 if (mdlvr)
|
|
294 adios (NULLCP, "only one maildelivery file at a time!");
|
|
295 mdlvr = cp;
|
|
296 continue;
|
|
297
|
|
298 case VERBSW:
|
|
299 verbose++;
|
|
300 continue;
|
|
301 case NVERBSW:
|
|
302 verbose = 0;
|
|
303 continue;
|
|
304
|
|
305 case DEBUGSW:
|
|
306 debug++;
|
|
307 continue;
|
|
308 }
|
|
309
|
|
310 switch (argp - (argv + 1)) {
|
|
311 case 1:
|
|
312 addr = cp;
|
|
313 break;
|
|
314
|
|
315 case 2:
|
|
316 info = cp;
|
|
317 break;
|
|
318
|
|
319 case 3:
|
|
320 sender = cp;
|
|
321 break;
|
|
322 }
|
|
323 }
|
|
324
|
|
325 /* */
|
|
326
|
|
327 rcvstore = getcpy(libpath("rcvstore"));
|
|
328
|
|
329 if (addr == NULL)
|
|
330 addr = getusr ();
|
|
331 if (user == NULL)
|
|
332 user = (cp = index (addr, '.')) ? ++cp : addr;
|
|
333 if ((pw = getpwnam (user)) == NULL)
|
|
334 adios (NULLCP, "no such local user as %s", user);
|
|
335
|
|
336 if (chdir (pw -> pw_dir) == NOTOK)
|
|
337 (void) chdir ("/");
|
|
338 (void) umask (0077);
|
|
339
|
|
340 if (geteuid () == 0) {
|
|
341 #ifdef BSD41A
|
|
342 (void) inigrp (pw -> pw_name, pw -> pw_gid);
|
|
343 #endif /* BSD41A */
|
|
344 (void) setgid (pw -> pw_gid);
|
|
345 #if defined(BSD42) || defined(SVR4)
|
|
346 (void) initgroups (pw -> pw_name, pw -> pw_gid);
|
|
347 #endif /* BSD42 || SVR4 */
|
|
348 (void) setuid (pw -> pw_uid);
|
|
349 }
|
|
350 #ifdef SETMG
|
|
351 mailgroup = getegid();
|
|
352 setgid(getgid());
|
|
353 #endif /* SETMG */
|
|
354
|
|
355 if (info == NULL)
|
|
356 info = "";
|
|
357
|
|
358 setbuf (stdin, NULLCP);
|
|
359
|
|
360 if (file == NULL) {
|
|
361 if (debug)
|
|
362 fprintf (stderr, "retrieving message from stdin\n");
|
|
363 if ((fd = copyfile (fileno (stdin), file = tmpfil, 1)) == NOTOK)
|
|
364 adios (NULLCP, "unable to create temporary file");
|
|
365 } else {
|
|
366 int tmpfd;
|
|
367 if ((tmpfd = open (file, 0)) == NOTOK)
|
|
368 adios(file, "unable to open");
|
|
369 if (debug)
|
|
370 fprintf (stderr, "retrieving message from file \"%s\"\n", file);
|
|
371 if ((fd = copyfile (tmpfd, tmpfil, 1)) == NOTOK)
|
|
372 adios (NULL, "unable to create temporary file");
|
|
373 close (tmpfd);
|
|
374 }
|
|
375 if (debug)
|
|
376 fprintf (stderr, "temporary file \"%s\" selected\n", tmpfil);
|
|
377 else
|
|
378 (void) unlink (tmpfil);
|
|
379 if ((fp = fdopen (fd, "r+")) == NULL)
|
|
380 adios (NULLCP, "unable to access temporary file");
|
|
381
|
|
382 from[0] = 0;
|
|
383 if (sender == NULL) {
|
|
384 sender = "";
|
|
385 copyinfo (fp, from);
|
|
386 }
|
|
387
|
|
388 if (mbox == NULL) {
|
|
389 (void) sprintf (mailbox, "%s/%s",
|
|
390 mmdfldir[0] ? mmdfldir : pw -> pw_dir,
|
|
391 mmdflfil[0] ? mmdflfil : pw -> pw_name);
|
|
392 mbox = mailbox;
|
|
393 }
|
|
394 if (home == NULL)
|
|
395 home = pw -> pw_dir;
|
|
396
|
|
397 if ((now = dtwstime ()) == NULL)
|
|
398 adios (NULLCP, "unable to ascertain local time");
|
|
399 (void) sprintf (ddate, "Delivery-Date: %s\n", dtimenow ());
|
|
400
|
|
401 if (debug) {
|
|
402 fprintf (stderr, "addr=\"%s\" user=\"%s\" info=\"%s\" file=\"%s\"\n",
|
|
403 addr, user, info, file);
|
|
404 fprintf (stderr, "sender=\"%s\" mbox=\"%s\" home=\"%s\" from=\"%s\"\n",
|
|
405 sender, mbox, home, from);
|
|
406 fprintf (stderr, "ddate=\"%s\" now=%02d:%02d\n",
|
|
407 ddate, now -> tw_hour, now -> tw_min);
|
|
408 }
|
|
409
|
|
410 done (localmail (fd, from, mdlvr) != NOTOK ? RCV_MOK : RCV_MBX);
|
|
411 }
|
|
412
|
|
413 /* */
|
|
414
|
|
415 static int localmail (fd, from, mdlvr)
|
|
416 int fd;
|
|
417 char *from,
|
|
418 *mdlvr;
|
|
419 {
|
|
420 #ifdef MSGID
|
|
421 struct stat st;
|
|
422 static int first = 1;
|
|
423 #ifdef DBM_SUFFIX
|
|
424 char buf[32];
|
|
425
|
|
426 (void) sprintf(buf, ".maildelivery%s", DBM_SUFFIX);
|
|
427 if (stat (buf, &st) != NOTOK) {
|
|
428 #else /* DBM_SUFFIX */
|
|
429 if (stat (".maildelivery.pag", &st) != NOTOK) {
|
|
430 #endif /* DBM_SUFFIX */
|
|
431 /*
|
|
432 * Allow a user to trigger the database by creating an
|
|
433 * empty database file. That gets us here, now we need
|
|
434 * to remove it so DBM will create and initialize it properly.
|
|
435 */
|
|
436 if (st.st_size == 0 && first) {
|
|
437 first = 0;
|
|
438 #ifdef DBM_SUFFIX
|
|
439 (void) unlink(buf);
|
|
440 #else /* DBM_SUFFIX */
|
|
441 (void) unlink(".maildelivery.pag");
|
|
442 #endif /* DBM_SUFFIX */
|
|
443 }
|
|
444 if (check_msgid (fd, ".maildelivery") == DONE)
|
|
445 return OK;
|
|
446 }
|
|
447 #endif
|
|
448
|
|
449 if (usr_delivery (fd, mdlvr ? mdlvr : ".maildelivery", 0, from) != NOTOK)
|
|
450 return OK;
|
|
451
|
|
452 if (usr_delivery (fd, maildelivery, 1, from) != NOTOK)
|
|
453 return OK;
|
|
454
|
|
455 #ifdef notdef
|
|
456 if (verbose)
|
|
457 printf ("(invoking hook)\n");
|
|
458 if (usr_hook (fd, mbox) != NOTOK)
|
|
459 return OK;
|
|
460 #endif /* notdef */
|
|
461
|
|
462 if (verbose)
|
|
463 printf ("(trying normal delivery)\n");
|
|
464 return usr_file (fd, mbox, from);
|
|
465 }
|
|
466
|
|
467 /* */
|
|
468
|
|
469 #ifdef JAPAN
|
|
470 int matches (p1, p2)
|
|
471 register char *p1,
|
|
472 *p2;
|
|
473 {
|
|
474 register char *p;
|
|
475
|
|
476 if (p1 == 0 || p2 == 0) return 0; /* XXX */
|
|
477
|
|
478 for (p = p1; *p; p++) {
|
|
479 if (uprf (p, p2))
|
|
480 return 1;
|
|
481 if (ml_ismlptr (p))
|
|
482 p++;
|
|
483 }
|
|
484 return 0;
|
|
485 }
|
|
486 #else /* JAPAN */
|
|
487 #define matches(a,b) (stringdex (b, a) >= 0)
|
|
488 #endif /* JAPAN */
|
|
489
|
|
490 static int usr_delivery (fd, delivery, su, from)
|
|
491 int fd,
|
|
492 su;
|
|
493 char *delivery,
|
|
494 *from;
|
|
495 {
|
|
496 int i,
|
|
497 accept,
|
|
498 status,
|
|
499 won,
|
|
500 vecp,
|
|
501 next;
|
|
502 register char *cp,
|
|
503 *action,
|
|
504 *field,
|
|
505 *pattern,
|
|
506 *string;
|
|
507 char buffer[BUFSIZ],
|
|
508 tmpbuf[BUFSIZ],
|
|
509 *vec[NVEC];
|
|
510 struct stat st;
|
|
511 register struct pair *p;
|
|
512 register FILE *fp;
|
|
513
|
|
514 if ((fp = fopen (delivery, "r")) == NULL)
|
|
515 return NOTOK;
|
|
516 if (fstat (fileno (fp), &st) == NOTOK
|
|
517 || (st.st_uid != 0 && (su || st.st_uid != pw -> pw_uid))
|
|
518 || st.st_mode & 0022) {
|
|
519 if (verbose) {
|
|
520 printf ("%s: ownership/modes bad (%d, %d,%d,0%o)\n",
|
|
521 delivery, su, pw -> pw_uid, st.st_uid, st.st_mode);
|
|
522 (void) fflush (stdout);
|
|
523 }
|
|
524 return NOTOK;
|
|
525 }
|
|
526
|
|
527 won = 0;
|
|
528 next = 1;
|
|
529 while (fgets (buffer, sizeof buffer, fp) != NULL) {
|
|
530 if (*buffer == '#' || *buffer == '\n')
|
|
531 continue;
|
|
532 if (cp = index (buffer, '\n'))
|
|
533 *cp = 0;
|
|
534 #ifdef JAPAN
|
|
535 ml_conv(buffer);
|
|
536 #endif /* JAPAN */
|
|
537 if ((vecp = split (buffer, vec)) < 5) {
|
|
538 if (debug)
|
|
539 fprintf(stderr,
|
|
540 "WARNING: entry with only %d fields, skipping ...\n",
|
|
541 vecp);
|
|
542 continue;
|
|
543 }
|
|
544 if (debug)
|
|
545 for (i = 0; vec[i]; i++)
|
|
546 fprintf (stderr, "vec[%d]: \"%s\"\n", i, vec[i]);
|
|
547
|
|
548 field = vec[0];
|
|
549 pattern = vec[1];
|
|
550 action = vec[2];
|
|
551
|
|
552 switch (vec[3][0]) {
|
|
553 case 'N':
|
|
554 case 'n':
|
|
555 if (! next)
|
|
556 continue; /* if previous condition failed, don't
|
|
557 do this - else fall through */
|
|
558
|
|
559 case '?':
|
|
560 if (won)
|
|
561 continue; /* else fall */
|
|
562 case 'A':
|
|
563 case 'a':
|
|
564 accept = 1;
|
|
565 break;
|
|
566
|
|
567 case 'R':
|
|
568 case 'r':
|
|
569 default:
|
|
570 accept = 0;
|
|
571 break;
|
|
572 }
|
|
573
|
|
574 string = vec[4];
|
|
575
|
|
576 if (vecp > 5) {
|
|
577 if (uleq (vec[5], "select")) {
|
|
578 if (logged_in () != NOTOK)
|
|
579 continue;
|
|
580 if (vecp > 7 && timely (vec[6], vec[7]) == NOTOK)
|
|
581 continue;
|
|
582 }
|
|
583 }
|
|
584
|
|
585 switch (*field) {
|
|
586 case '*':
|
|
587 break;
|
|
588
|
|
589 case 'd':
|
|
590 if (uleq (field, "default")) {
|
|
591 if (won)
|
|
592 continue;
|
|
593 break;
|
|
594 } /* else fall */
|
|
595
|
|
596 default:
|
|
597 if (!parsed && parse (fd) == NOTOK) {
|
|
598 (void) fclose (fp);
|
|
599 return NOTOK;
|
|
600 }
|
|
601 if ((p = lookup (hdrs, field)) == NULL
|
|
602 || (p->p_value == NULL) /* XXX */
|
|
603 || !matches (p -> p_value, pattern)) {
|
|
604 next = 0;
|
|
605 continue;
|
|
606 }
|
|
607 else
|
|
608 next = 1;
|
|
609 break;
|
|
610 }
|
|
611
|
|
612 switch (*action) {
|
|
613 case 'q':
|
|
614 if (!uleq (action, "qpipe"))
|
|
615 continue; /* else fall */
|
|
616 case '^':
|
|
617 expand (tmpbuf, string, fd);
|
|
618 if (split (tmpbuf, vec) < 1)
|
|
619 continue;
|
|
620 status = usr_pipe (fd, tmpbuf, vec[0], vec);
|
|
621 break;
|
|
622
|
|
623 case 'p':
|
|
624 if (!uleq (action, "pipe"))
|
|
625 continue; /* else fall */
|
|
626 case '|':
|
|
627 vec[2] = "sh";
|
|
628 vec[3] = "-c";
|
|
629 expand (tmpbuf, string, fd);
|
|
630 vec[4] = tmpbuf;
|
|
631 vec[5] = NULL;
|
|
632 status = usr_pipe (fd, tmpbuf, "/bin/sh", vec + 2);
|
|
633 break;
|
|
634
|
|
635 case '+':
|
|
636 dofolder:
|
|
637 if (*string == '+')
|
|
638 strcpy(tmpbuf, string);
|
|
639 else
|
|
640 sprintf(tmpbuf, "+%s", string);
|
|
641 vec[2] = "rcvstore";
|
|
642 vec[3] = tmpbuf;
|
|
643 vec[4] = NULL;
|
|
644 if (verbose)
|
|
645 printf("rcvstore %s", vec[3]);
|
|
646 status = usr_pipe(fd, "rcvstore", rcvstore, vec + 2);
|
|
647 break;
|
|
648
|
|
649 case 'f':
|
|
650 if (uleq(action, "folder"))
|
|
651 goto dofolder;
|
|
652 if (!uleq (action, "file"))
|
|
653 continue; /* else fall */
|
|
654 case '>':
|
|
655 #ifdef RPATHS
|
|
656 status = usr_file (fd, string, from); /* UUCP format? */
|
|
657 #else
|
|
658 status = usr_file (fd, string, NULLCP);
|
|
659 #endif
|
|
660 break;
|
|
661
|
|
662 case 'm':
|
|
663 if (!uleq (action, "mbox"))
|
|
664 continue;
|
|
665 status = usr_file (fd, string, NULLCP);
|
|
666 break;
|
|
667
|
|
668 case 'd':
|
|
669 if (!uleq (action, "destroy"))
|
|
670 continue;
|
|
671 status = OK;
|
|
672 #ifdef REALLY_DESTROY
|
|
673 if (verbose)
|
|
674 printf ("\tdestroying message\n");
|
|
675 if (accept)
|
|
676 won++;
|
|
677 goto finish;
|
|
678 #endif /* REALLY_DESTROY */
|
|
679 break;
|
|
680 }
|
|
681
|
|
682 if (status == OK) { /* next is already 1. */
|
|
683 if (accept)
|
|
684 won++;
|
|
685 } else { /* overload the next variable */
|
|
686 next = 0; /* to indicate that action failed */
|
|
687 }
|
|
688 }
|
|
689
|
|
690 finish:
|
|
691 (void) fclose (fp);
|
|
692 return (won ? OK : NOTOK);
|
|
693 }
|
|
694
|
|
695 /* */
|
|
696
|
|
697 #define QUOTE '\\'
|
|
698
|
|
699 static int split (cp, vec)
|
|
700 char *cp,
|
|
701 **vec;
|
|
702 {
|
|
703 register int i;
|
|
704 register char *s;
|
|
705
|
|
706 for (i = 0, s = cp; i <= NVEC;) {
|
|
707 vec[i] = NULL;
|
|
708 while (isspace (*s) || *s == ',')
|
|
709 *s++ = 0;
|
|
710 if (*s == 0)
|
|
711 break;
|
|
712
|
|
713 if (*s == '"') {
|
|
714 for (vec[i++] = ++s; *s != 0 && *s != '"'; s++)
|
|
715 if (*s == QUOTE) {
|
|
716 if (*++s == '"')
|
|
717 (void) strcpy (s - 1, s);
|
|
718 s--;
|
|
719 }
|
|
720 if (*s == '"')
|
|
721 *s++ = 0;
|
|
722 continue;
|
|
723 }
|
|
724 if (*s == QUOTE && *++s != '"')
|
|
725 s--;
|
|
726 vec[i++] = s++;
|
|
727
|
|
728 while (*s != 0 && !isspace (*s) && *s != ',')
|
|
729 s++;
|
|
730 }
|
|
731 vec[i] = NULL;
|
|
732
|
|
733 return i;
|
|
734 }
|
|
735
|
|
736 /* */
|
|
737
|
|
738 static int parse (fd)
|
|
739 register int fd;
|
|
740 {
|
|
741 register int i,
|
|
742 state;
|
|
743 int fd1;
|
|
744 register char *cp,
|
|
745 *dp,
|
|
746 *lp;
|
|
747 char name[NAMESZ],
|
|
748 field[BUFSIZ];
|
|
749 register struct pair *p,
|
|
750 *q;
|
|
751 register FILE *in;
|
|
752
|
|
753 if (parsed++)
|
|
754 return OK;
|
|
755
|
|
756 if ((fd1 = dup (fd)) == NOTOK)
|
|
757 return NOTOK;
|
|
758 if ((in = fdopen (fd1, "r")) == NULL) {
|
|
759 (void) close (fd1);
|
|
760 return NOTOK;
|
|
761 }
|
|
762 rewind (in);
|
|
763
|
|
764 if (p = lookup (hdrs, "source"))
|
|
765 p -> p_value = getcpy (sender);
|
|
766 if (p = lookup (hdrs, "addr"))
|
|
767 p -> p_value = getcpy (addr);
|
|
768
|
|
769 for (i = 0, state = FLD;;) {
|
|
770 switch (state = m_getfld (state, name, field, sizeof field, in)) {
|
|
771 case FLD:
|
|
772 case FLDEOF:
|
|
773 case FLDPLUS:
|
|
774 lp = add (field, NULLCP);
|
|
775 while (state == FLDPLUS) {
|
|
776 state = m_getfld (state, name, field, sizeof field, in);
|
|
777 lp = add (field, lp);
|
|
778 }
|
|
779 for (p = hdrs; p -> p_name; p++)
|
|
780 if (uleq (p -> p_name, name)) {
|
|
781 if (!(p -> p_flags & P_HID)) {
|
|
782 if (cp = p -> p_value)
|
|
783 if (p -> p_flags & P_ADR) {
|
|
784 dp = cp + strlen (cp) - 1;
|
|
785 if (*dp == '\n')
|
|
786 *dp = 0;
|
|
787 cp = add (",\n\t", cp);
|
|
788 }
|
|
789 else
|
|
790 cp = add ("\t", cp);
|
|
791 p -> p_value = add (lp, cp);
|
|
792 }
|
|
793 free (lp);
|
|
794 break;
|
|
795 }
|
|
796 if (p -> p_name == NULL && i < NVEC) {
|
|
797 p -> p_name = getcpy (name);
|
|
798 p -> p_value = lp;
|
|
799 p -> p_flags = P_NIL;
|
|
800 p++, i++;
|
|
801 p -> p_name = NULL;
|
|
802 }
|
|
803 if (state != FLDEOF)
|
|
804 continue;
|
|
805 break;
|
|
806
|
|
807 case BODY:
|
|
808 case BODYEOF:
|
|
809 case FILEEOF:
|
|
810 break;
|
|
811
|
|
812 case LENERR:
|
|
813 case FMTERR:
|
|
814 advise (NULLCP, "format error in message");
|
|
815 break;
|
|
816
|
|
817 default:
|
|
818 advise (NULLCP, "internal error");
|
|
819 (void) fclose (in);
|
|
820 return NOTOK;
|
|
821 }
|
|
822 break;
|
|
823 }
|
|
824 (void) fclose (in);
|
|
825
|
|
826 if (p = lookup (vars, "reply-to")) {
|
|
827 if ((q = lookup (hdrs, "reply-to")) == NULL || q -> p_value == NULL)
|
|
828 q = lookup (hdrs, "from");
|
|
829 p -> p_value = getcpy (q ? q -> p_value : "");
|
|
830 p -> p_flags &= ~P_CHK;
|
|
831 if (debug)
|
|
832 fprintf (stderr, "vars[%d]: name=\"%s\" value=\"%s\"\n",
|
12
|
833 (int)(p - vars), p -> p_name, p -> p_value);
|
0
|
834 }
|
|
835 #define empty(s) ((s) ? (s) : "")
|
|
836 if (debug)
|
|
837 for (p = hdrs; p -> p_name; p++)
|
|
838 fprintf (stderr, "hdrs[%d]: name=\"%s\" value=\"%s\"\n",
|
12
|
839 (int)(p - hdrs), p -> p_name, empty(p -> p_value));
|
0
|
840 #undef empty
|
|
841
|
|
842 #ifdef MIME_HEADERS
|
|
843 for (p = hdrs; p -> p_name; p++) {
|
|
844 char *tmpbuf;
|
|
845 if (! p -> p_value)
|
|
846 continue;
|
|
847 tmpbuf = getcpy(p -> p_value);
|
|
848 exthdr_decode(tmpbuf, p -> p_value);
|
|
849 free(tmpbuf);
|
|
850 }
|
|
851 #endif /* MIME_HEADERS */
|
|
852 return OK;
|
|
853 }
|
|
854
|
|
855 /* */
|
|
856
|
|
857 #define LPAREN '('
|
|
858 #define RPAREN ')'
|
|
859
|
|
860 static expand (s1, s2, fd)
|
|
861 register char *s1,
|
|
862 *s2;
|
|
863 int fd;
|
|
864 {
|
|
865 register char c,
|
|
866 *cp;
|
|
867 register struct pair *p;
|
|
868
|
|
869 if (!globbed)
|
|
870 glob (fd);
|
|
871
|
|
872 while (c = *s2++)
|
|
873 if (c != '$' || *s2 != LPAREN)
|
|
874 *s1++ = c;
|
|
875 else {
|
|
876 for (cp = ++s2; *s2 && *s2 != RPAREN; s2++)
|
|
877 continue;
|
|
878 if (*s2 != RPAREN) {
|
|
879 s2 = --cp;
|
|
880 continue;
|
|
881 }
|
|
882 *s2++ = 0;
|
|
883 if (p = lookup (vars, cp)) {
|
|
884 if (!parsed && (p -> p_flags & P_CHK))
|
|
885 (void) parse (fd);
|
|
886
|
|
887 (void) strcpy (s1, p -> p_value);
|
|
888 s1 += strlen (s1);
|
|
889 }
|
|
890 }
|
|
891 *s1 = 0;
|
|
892 }
|
|
893
|
|
894 /* */
|
|
895
|
|
896 static glob (fd)
|
|
897 register int fd;
|
|
898 {
|
|
899 char buffer[BUFSIZ];
|
|
900 struct stat st;
|
|
901 register struct pair *p;
|
|
902
|
|
903 if (globbed++)
|
|
904 return;
|
|
905
|
|
906 if (p = lookup (vars, "sender"))
|
|
907 p -> p_value = getcpy (sender);
|
|
908 if (p = lookup (vars, "address"))
|
|
909 p -> p_value = getcpy (addr);
|
|
910 if (p = lookup (vars, "size")) {
|
|
911 (void) sprintf (buffer, "%d",
|
|
912 fstat (fd, &st) != NOTOK ? (int) st.st_size : 0);
|
|
913 p -> p_value = getcpy (buffer);
|
|
914 }
|
|
915 if (p = lookup (vars, "info"))
|
|
916 p -> p_value = getcpy (info);
|
|
917
|
|
918 if (debug)
|
|
919 for (p = vars; p -> p_name; p++)
|
|
920 fprintf (stderr, "vars[%d]: name=\"%s\" value=\"%s\"\n",
|
12
|
921 (int)(p - vars), p -> p_name, p -> p_value);
|
0
|
922 }
|
|
923
|
|
924 /* */
|
|
925
|
|
926 static struct pair *lookup (pairs, key)
|
|
927 register struct pair *pairs;
|
|
928 register char *key;
|
|
929 {
|
|
930 register char *cp;
|
|
931
|
|
932 for (; cp = pairs -> p_name; pairs++)
|
|
933 if (uleq (cp, key))
|
|
934 return pairs;
|
|
935
|
|
936 return NULL;
|
|
937 }
|
|
938
|
|
939 /* */
|
|
940
|
|
941 static int logged_in () {
|
|
942 struct utmp ut;
|
|
943 register FILE *uf;
|
|
944
|
|
945 if (utmped)
|
|
946 return utmped;
|
|
947
|
|
948 if ((uf = fopen (UTMP_FILENAME, "r")) == NULL)
|
|
949 return NOTOK;
|
|
950
|
|
951 while (fread ((char *) &ut, sizeof ut, 1, uf) == 1)
|
|
952 if (ut.ut_name[0] != 0
|
|
953 #ifdef UTMAXTYPE
|
|
954 && ut.ut_type == USER_PROCESS
|
|
955 #endif
|
|
956 && strncmp (user, ut.ut_name, sizeof ut.ut_name) == 0) {
|
|
957 if (debug)
|
|
958 continue;
|
|
959 (void) fclose (uf);
|
|
960 return (utmped = DONE);
|
|
961 }
|
|
962
|
|
963 (void) fclose (uf);
|
|
964 return (utmped = NOTOK);
|
|
965 }
|
|
966
|
|
967
|
|
968 static int timely (t1, t2)
|
|
969 char *t1,
|
|
970 *t2;
|
|
971 {
|
|
972 #define check(t,a,b) if (t < a || t > b) return NOTOK
|
|
973 #define cmpar(h1,m1,h2,m2) if (h1 < h2 || (h1 == h2 && m1 < m2)) return OK
|
|
974
|
|
975 int t1hours,
|
|
976 t1mins,
|
|
977 t2hours,
|
|
978 t2mins;
|
|
979
|
|
980 if (sscanf (t1, "%d:%d", &t1hours, &t1mins) != 2)
|
|
981 return NOTOK;
|
|
982 check (t1hours, 0, 23);
|
|
983 check (t1mins, 0, 59);
|
|
984
|
|
985 if (sscanf (t2, "%d:%d", &t2hours, &t2mins) != 2)
|
|
986 return NOTOK;
|
|
987 check (t2hours, 0, 23);
|
|
988 check (t2mins, 0, 59);
|
|
989
|
|
990 cmpar (now -> tw_hour, now -> tw_min, t1hours, t1mins);
|
|
991 cmpar (t2hours, t2mins, now -> tw_hour, now -> tw_min);
|
|
992
|
|
993 return NOTOK;
|
|
994 }
|
|
995
|
|
996 /* */
|
|
997
|
|
998 static int usr_file (fd, mailbox, from)
|
|
999 int fd;
|
|
1000 char *mailbox,
|
|
1001 *from;
|
|
1002 {
|
|
1003 int md,
|
|
1004 mapping;
|
|
1005 register char *bp;
|
|
1006 char buffer[BUFSIZ];
|
|
1007 gid_t mail_gid;
|
|
1008 int file_mode;
|
|
1009
|
|
1010 if (verbose)
|
|
1011 printf ("\tdelivering to file \"%s\"", mailbox);
|
|
1012 if (from && *from) {
|
|
1013 (void) mbx_uucp ();
|
|
1014 if (verbose)
|
|
1015 printf (" (uucp style)");
|
|
1016 (void) sprintf (buffer, "%s%s", from, ddate);
|
|
1017 bp = buffer;
|
|
1018 mapping = 0;
|
|
1019 }
|
|
1020 else {
|
|
1021 bp = ddate;
|
|
1022 mapping = 1;
|
|
1023 }
|
|
1024 if (verbose)
|
|
1025 (void) fflush (stdout);
|
|
1026
|
|
1027 /*
|
|
1028 * for SYS5 systems
|
|
1029 * (maildrop: gid = mail (660))
|
|
1030 * Attention!! This routine may open a security hole...
|
|
1031 * by hayashi@kuic.kyoto-u.ac.jp
|
|
1032 */
|
|
1033
|
|
1034 #ifdef SETMG
|
|
1035 if (strcmp(mailbox, mbox) == 0) {
|
|
1036 mail_gid = mailgroup;
|
|
1037 file_mode = 0660;
|
|
1038 setgid(mailgroup);
|
|
1039 } else {
|
|
1040 mail_gid = pw -> pw_gid;
|
|
1041 file_mode = m_gmprot();
|
|
1042 }
|
|
1043 #else /* SETMG */
|
|
1044 mail_gid = pw -> pw_gid;
|
|
1045 file_mode = m_gmprot();
|
|
1046 #endif /* SETMG */
|
|
1047
|
|
1048 if ((md = mbx_open (mailbox, pw -> pw_uid, mail_gid, file_mode))
|
|
1049 == NOTOK) {
|
|
1050 #ifdef SETMG
|
|
1051 setgid(getgid());
|
|
1052 #endif /* SETMG */
|
|
1053 adorn ("", "unable to open:");
|
|
1054 return NOTOK;
|
|
1055 }
|
|
1056
|
|
1057 (void) lseek (fd, (off_t)0, 0);
|
|
1058 if (mbx_copy (mailbox, md, fd, mapping, bp, verbose) == NOTOK) {
|
|
1059 #ifdef SETMG
|
|
1060 setgid(getgid());
|
|
1061 #endif /* SETMG */
|
|
1062 adorn ("", "error writing to:");
|
|
1063 return NOTOK;
|
|
1064 }
|
|
1065
|
|
1066 (void) mbx_close (mailbox, md);
|
|
1067 #ifdef SETMG
|
|
1068 setgid(getgid());
|
|
1069 #endif /* SETMG */
|
|
1070 if (verbose) {
|
|
1071 printf (", done.\n");
|
|
1072 (void) fflush (stdout);
|
|
1073 }
|
|
1074 return OK;
|
|
1075 }
|
|
1076
|
|
1077 /* */
|
|
1078
|
|
1079 #ifdef notdef
|
|
1080 static int usr_hook (fd, mailbox)
|
|
1081 int fd;
|
|
1082 char *mailbox;
|
|
1083 {
|
|
1084 int i,
|
|
1085 vecp;
|
|
1086 char receive[BUFSIZ],
|
|
1087 tmpfil[BUFSIZ],
|
|
1088 *vec[NVEC];
|
|
1089
|
|
1090 if ((fd = copyfile (fd, tmpfil, 0)) == NOTOK) {
|
|
1091 if (verbose)
|
|
1092 adorn ("unable to copy message; skipping hook\n");
|
|
1093 return NOTOK;
|
|
1094 }
|
|
1095 (void) chown (tmpfil, pw -> pw_uid, pw -> pw_gid);
|
|
1096
|
|
1097 vecp = 1;
|
|
1098 (void) sprintf (receive, "%s/.mh_receive", pw -> pw_dir);
|
|
1099 switch (access (receive, 01)) {
|
|
1100 case NOTOK:
|
|
1101 (void) sprintf (receive, "%s/bin/rcvmail", pw -> pw_dir);
|
|
1102 if (access (receive, 01) == NOTOK) {
|
|
1103 (void) unlink (tmpfil);
|
|
1104 if (verbose) {
|
|
1105 printf ("\tnot present\n");
|
|
1106 (void) fflush (stdout);
|
|
1107 }
|
|
1108 return NOTOK;
|
|
1109 }
|
|
1110 vec[vecp++] = addr;
|
|
1111 vec[vecp++] = tmpfil;
|
|
1112 vec[vecp++] = sender;
|
|
1113 break;
|
|
1114
|
|
1115 default:
|
|
1116 vec[vecp++] = tmpfil;
|
|
1117 vec[vecp++] = mailbox;
|
|
1118 vec[vecp++] = home;
|
|
1119 vec[vecp++] = addr;
|
|
1120 vec[vecp++] = sender;
|
|
1121 break;
|
|
1122 }
|
|
1123 vec[0] = r1bindex (receive, '/');
|
|
1124 vec[vecp] = NULL;
|
|
1125
|
|
1126 i = usr_pipe (fd, "rcvmail", receive, vec);
|
|
1127 (void) unlink (tmpfil);
|
|
1128
|
|
1129 return i;
|
|
1130 }
|
|
1131 #endif /* notdef */
|
|
1132
|
|
1133 /* */
|
|
1134
|
|
1135 static int usr_pipe (fd, cmd, pgm, vec)
|
|
1136 int fd;
|
|
1137 char *cmd,
|
|
1138 *pgm,
|
|
1139 **vec;
|
|
1140 {
|
|
1141 int bytes,
|
|
1142 i,
|
|
1143 child_id,
|
|
1144 status;
|
|
1145 struct stat st;
|
|
1146
|
|
1147 if (verbose) {
|
|
1148 printf ("\tdelivering to pipe \"%s\"", cmd);
|
|
1149 (void) fflush (stdout);
|
|
1150 }
|
|
1151 (void) lseek (fd, (off_t)0, 0);
|
|
1152
|
|
1153 for (i = 0; (child_id = fork ()) == NOTOK && i < 5; i++)
|
|
1154 sleep (5);
|
|
1155 switch (child_id) {
|
|
1156 case NOTOK:
|
|
1157 adorn ("fork", "unable to");
|
|
1158 return NOTOK;
|
|
1159
|
|
1160 case OK:
|
|
1161 if (fd != 0)
|
|
1162 (void) dup2 (fd, 0);
|
|
1163 (void) freopen ("/dev/null", "w", stdout);
|
|
1164 (void) freopen ("/dev/null", "w", stderr);
|
|
1165 if (fd != 3)
|
|
1166 (void) dup2 (fd, 3);
|
|
1167 closefds (4);
|
|
1168 #ifdef TIOCNOTTY
|
|
1169 if ((fd = open ("/dev/tty", 2)) != NOTOK) {
|
|
1170 (void) ioctl (fd, TIOCNOTTY, NULLCP);
|
|
1171 (void) close (fd);
|
|
1172 }
|
|
1173 #endif /* TIOCNOTTY */
|
|
1174 #ifdef BSD42
|
13
|
1175 (void) setpgrp (); // (void) setpgrp (0, getpid ());
|
0
|
1176 #endif /* BSD42 */
|
|
1177
|
|
1178 *environ = NULL;
|
|
1179 (void) m_putenv ("USER", pw -> pw_name);
|
|
1180 (void) m_putenv ("HOME", pw -> pw_dir);
|
|
1181 (void) m_putenv ("SHELL", pw -> pw_shell);
|
|
1182
|
|
1183 execvp (pgm, vec);
|
|
1184 _exit (-1);
|
|
1185
|
|
1186 default:
|
|
1187 switch (setjmp (myctx)) {
|
|
1188 case OK:
|
|
1189 (void) signal (SIGALRM, alrmser);
|
|
1190 bytes = fstat (fd, &st) != NOTOK ? (int) st.st_size : 100;
|
|
1191 if (bytes <= 0)
|
|
1192 bytes = 100;
|
|
1193 (void) alarm ((unsigned) (bytes * 60 + 300));
|
|
1194
|
|
1195 status = pidwait (child_id, OK);
|
|
1196
|
|
1197 (void) alarm (0);
|
|
1198 #ifdef MMDFI
|
|
1199 if (status == RP_MOK || status == RP_OK)
|
|
1200 status = 0;
|
|
1201 #endif /* MMDFI */
|
|
1202 if (verbose) {
|
|
1203 if (status == 0)
|
|
1204 printf (", wins.\n");
|
|
1205 else
|
|
1206 if ((status & 0xff00) == 0xff00)
|
|
1207 printf (", system error\n");
|
|
1208 else
|
|
1209 (void) pidstatus (status, stdout, ", loses");
|
|
1210 (void) fflush (stdout);
|
|
1211 }
|
|
1212 return (status == 0 ? OK : NOTOK);
|
|
1213
|
|
1214 default:
|
|
1215 #ifndef BSD42
|
|
1216 (void) kill (child_id, SIGKILL);
|
|
1217 #else /* BSD42 */
|
|
1218 (void) killpg (child_id, SIGKILL);
|
|
1219 #endif /* BSD42 */
|
|
1220 if (verbose) {
|
|
1221 printf (", timed-out; terminated\n");
|
|
1222 (void) fflush (stdout);
|
|
1223 }
|
|
1224 return NOTOK;
|
|
1225 }
|
|
1226 }
|
|
1227 }
|
|
1228
|
|
1229 /* */
|
|
1230
|
|
1231 /* ARGSUSED */
|
|
1232
|
|
1233 static TYPESIG alrmser (i)
|
|
1234 int i;
|
|
1235 {
|
|
1236 longjmp (myctx, DONE);
|
|
1237 }
|
|
1238
|
|
1239 /* */
|
|
1240
|
|
1241 static copyinfo (fp, from)
|
|
1242 register FILE *fp;
|
|
1243 char *from;
|
|
1244 {
|
|
1245 int i;
|
|
1246 register char *cp;
|
|
1247 static char buffer[BUFSIZ];
|
|
1248
|
|
1249 if (unixfrom) /* interface from copyfile */
|
|
1250 strcpy (from, unixfrom);
|
|
1251 else if (fgets (from, BUFSIZ, fp) == NULL)
|
|
1252 adios (NULLCP, "no message");
|
|
1253
|
|
1254 if (strncmp (from, "From ", i = strlen ("From "))) {
|
|
1255 rewind (fp);
|
|
1256 *from = 0;
|
|
1257 return;
|
|
1258 }
|
|
1259
|
|
1260 (void) strcpy (buffer, from + i);
|
|
1261 if (cp = index (buffer, '\n')) {
|
|
1262 *cp = 0;
|
|
1263 cp -= 24;
|
|
1264 if (cp < buffer)
|
|
1265 cp = buffer;
|
|
1266 }
|
|
1267 else
|
|
1268 cp = buffer;
|
|
1269 *cp = 0;
|
|
1270
|
|
1271 for (cp = buffer + strlen (buffer) - 1; cp >= buffer; cp--)
|
|
1272 if (isspace (*cp))
|
|
1273 *cp = 0;
|
|
1274 else
|
|
1275 break;
|
|
1276 sender = buffer;
|
|
1277 rewind (fp);
|
|
1278 }
|
|
1279
|
|
1280 /* */
|
|
1281
|
|
1282 static int copyfile (qd, tmpfil, fold)
|
|
1283 int qd,
|
|
1284 fold;
|
|
1285 register char *tmpfil;
|
|
1286 {
|
|
1287 register int i,
|
|
1288 first = 0,
|
|
1289 fd1,
|
|
1290 fd2;
|
|
1291 char buffer[BUFSIZ];
|
|
1292 register FILE *qfp,
|
|
1293 *ffp;
|
|
1294
|
|
1295 (void) strcpy (tmpfil, m_tmpfil (invo_name));
|
|
1296 if ((fd1 = creat (tmpfil, 0600)) == NOTOK)
|
|
1297 return NOTOK;
|
|
1298 (void) close (fd1);
|
|
1299 if ((fd1 = open (tmpfil, 2)) == NOTOK)
|
|
1300 return NOTOK;
|
|
1301
|
|
1302 if (!fold) {
|
|
1303 while ((i = read (qd, buffer, sizeof buffer)) > 0)
|
|
1304 if (write (fd1, buffer, i) != i) {
|
|
1305 you_lose: ;
|
|
1306 (void) close (fd1);
|
|
1307 (void) unlink (tmpfil);
|
|
1308 return NOTOK;
|
|
1309 }
|
|
1310 if (i == NOTOK)
|
|
1311 goto you_lose;
|
|
1312 (void) lseek (fd1, (off_t)0, 0);
|
|
1313 return fd1;
|
|
1314 }
|
|
1315
|
|
1316 if ((fd2 = dup (qd)) == NOTOK) {
|
|
1317 (void) close (fd1);
|
|
1318 return NOTOK;
|
|
1319 }
|
|
1320 if ((qfp = fdopen (fd2, "r")) == NULL) {
|
|
1321 (void) close (fd1);
|
|
1322 (void) close (fd2);
|
|
1323 return NOTOK;
|
|
1324 }
|
|
1325
|
|
1326 if ((fd2 = dup (fd1)) == NOTOK) {
|
|
1327 (void) close (fd1);
|
|
1328 (void) fclose (qfp);
|
|
1329 return NOTOK;
|
|
1330 }
|
|
1331 if ((ffp = fdopen (fd2, "r+")) == NULL) {
|
|
1332 (void) close (fd1);
|
|
1333 (void) close (fd2);
|
|
1334 (void) fclose (qfp);
|
|
1335 return NOTOK;
|
|
1336 }
|
|
1337
|
|
1338 i = strlen ("From ");
|
|
1339 while (fgets (buffer, sizeof buffer, qfp)) {
|
|
1340 if (!strncmp (buffer, "From ", i))
|
|
1341 if (first == 0) {
|
|
1342 #ifdef RPATHS
|
|
1343 register char *fp, *cp, *hp, *ep;
|
|
1344 #endif
|
|
1345 unixfrom = getcpy (buffer); /* save for later */
|
|
1346 #ifndef RPATHS
|
|
1347 continue; /* but don't put in file */
|
|
1348 #else
|
|
1349 hp = cp = index (fp = unixfrom + i, ' ');
|
|
1350 while (hp = index (++hp, 'r'))
|
|
1351 if (uprf (hp, "remote from")) {
|
|
1352 hp = rindex (hp, ' ');
|
|
1353 break;
|
|
1354 }
|
|
1355 if (hp) {
|
|
1356 ep = rindex (++hp, '\n');
|
|
1357 sprintf (buffer, "Return-Path: %.*s!%.*s\n",
|
13
|
1358 (int)(ep - hp), hp,
|
|
1359 (int)(cp - fp), fp);
|
0
|
1360 }
|
|
1361 else
|
|
1362 sprintf (buffer, "Return-Path: %.*s\n",
|
13
|
1363 (int)(cp - fp), fp);
|
0
|
1364 #endif
|
|
1365 }
|
|
1366 #ifdef notdef /* mbx_copy does this */
|
|
1367 else
|
|
1368 putc ('>', ffp);
|
|
1369 #endif /* notdef */
|
|
1370 first++;
|
|
1371 fputs (buffer, ffp);
|
|
1372 if (ferror (ffp)) {
|
|
1373 (void) close (fd1);
|
|
1374 (void) fclose (ffp);
|
|
1375 (void) fclose (qfp);
|
|
1376 return NOTOK;
|
|
1377 }
|
|
1378 }
|
|
1379
|
|
1380 (void) fclose (ffp);
|
|
1381 if (ferror (qfp)) {
|
|
1382 (void) close (fd1);
|
|
1383 (void) fclose (qfp);
|
|
1384 return NOTOK;
|
|
1385 }
|
|
1386 (void) fclose (qfp);
|
|
1387
|
|
1388 (void) lseek (fd1, (off_t)0, 0);
|
|
1389
|
|
1390 return fd1;
|
|
1391 }
|
|
1392
|
|
1393 /* */
|
|
1394
|
|
1395 /* VARARGS2 */
|
|
1396
|
|
1397 static void adorn (what, fmt, a, b, c, d, e, f)
|
|
1398 char *what,
|
|
1399 *fmt,
|
|
1400 *a,
|
|
1401 *b,
|
|
1402 *c,
|
|
1403 *d,
|
|
1404 *e,
|
|
1405 *f;
|
|
1406 {
|
|
1407 char *cp = invo_name;
|
|
1408
|
|
1409 if (!verbose)
|
|
1410 return;
|
|
1411 printf (", ");
|
|
1412
|
|
1413 invo_name = NULL;
|
|
1414 advise (what, fmt, a, b, c, d, e, f);
|
|
1415 invo_name = cp;
|
|
1416 }
|
|
1417
|
|
1418 /* */
|
|
1419
|
|
1420 #ifdef MSGID
|
|
1421
|
|
1422 static int check_msgid (fd, file)
|
|
1423 int fd;
|
|
1424 char *file;
|
|
1425 {
|
|
1426 int fd1,
|
|
1427 state;
|
|
1428 char *cp,
|
|
1429 buf[BUFSIZ],
|
|
1430 name[NAMESZ];
|
|
1431 datum key,
|
|
1432 value;
|
|
1433 DBM *db;
|
|
1434 FILE *in;
|
|
1435
|
|
1436 if ((fd1 = dup (fd)) == NOTOK)
|
|
1437 return NOTOK;
|
|
1438 if ((in = fdopen (fd1, "r")) == NULL) {
|
|
1439 (void) close (fd1);
|
|
1440 return NOTOK;
|
|
1441 }
|
|
1442 rewind (in);
|
|
1443
|
|
1444 for (state = FLD;;) {
|
|
1445 switch (state = m_getfld (state, name, buf, sizeof buf, in)) {
|
|
1446 case FLD:
|
|
1447 case FLDPLUS:
|
|
1448 case FLDEOF:
|
|
1449 if (!uleq (name, "Message-ID")) {
|
|
1450 while (state == FLDPLUS)
|
|
1451 state = m_getfld (state, name, buf, sizeof buf, in);
|
|
1452 continue;
|
|
1453 }
|
|
1454
|
|
1455 cp = add (buf, NULLCP);
|
|
1456 while (state == FLDPLUS) {
|
|
1457 state = m_getfld (state, name, buf, sizeof buf, in);
|
|
1458 cp = add (buf, cp);
|
|
1459 }
|
|
1460 key.dsize = strlen (key.dptr = trimcpy (cp)) + 1;
|
|
1461 free (cp);
|
|
1462 cp = key.dptr;
|
|
1463
|
|
1464 if ((db = dbm_open (file, O_RDWR | O_CREAT, 0600)) == NULL) {
|
|
1465 advise (file, "unable to perform dbm_open on");
|
|
1466 out: ;
|
|
1467 free (cp);
|
|
1468 (void) fclose (in);
|
|
1469 return NOTOK;
|
|
1470 }
|
|
1471 #ifdef LOCKF
|
|
1472 if (lockf (dbm_pagfno (db), F_LOCK, 0) == NOTOK) {
|
|
1473 advise (file, "unable to perform lockf on");
|
|
1474 goto out;
|
|
1475 }
|
|
1476 #else
|
|
1477 #ifdef FCNTL
|
|
1478 {
|
|
1479 struct flock fl;
|
|
1480
|
|
1481 fl.l_type = F_WRLCK;
|
|
1482 fl.l_whence = 0;
|
|
1483 fl.l_start = 0;
|
|
1484 fl.l_len = 0;
|
|
1485 if (fcntl (dbm_pagfno (db), F_SETLK, &fl) == -1) {
|
|
1486 advise (file, "unable to perform flock on");
|
|
1487 goto out;
|
|
1488 }
|
|
1489 }
|
|
1490 #else
|
|
1491 if (flock (dbm_pagfno (db), LOCK_EX) == NOTOK) {
|
|
1492 advise (file, "unable to perform flock on");
|
|
1493 goto out;
|
|
1494 }
|
|
1495 #endif
|
|
1496 #endif
|
|
1497
|
|
1498 value = dbm_fetch (db, key);
|
|
1499 if (value.dptr != NULL) {
|
|
1500 if (debug)
|
|
1501 advise (NULLCP,
|
|
1502 "Message-ID: %s already received on\n\tDate: %s",
|
|
1503 cp, value.dptr);
|
|
1504 free (cp);
|
|
1505 (void) fclose (in);
|
|
1506 return DONE;
|
|
1507 }
|
|
1508
|
|
1509 value.dsize = strlen (value.dptr =
|
|
1510 ddate + sizeof "Delivery-Date:") + 1;
|
|
1511
|
|
1512 if (dbm_store (db, key, value, DBM_INSERT))
|
|
1513 advise (file, "possibly corrupt file");
|
|
1514
|
|
1515 dbm_close (db);
|
|
1516
|
|
1517 free (cp);
|
|
1518 break;
|
|
1519
|
|
1520 case BODY:
|
|
1521 case BODYEOF:
|
|
1522 case FILEEOF:
|
|
1523 break;
|
|
1524
|
|
1525 case LENERR:
|
|
1526 case FMTERR:
|
|
1527 default:
|
|
1528 break;
|
|
1529 }
|
|
1530
|
|
1531 break;
|
|
1532 }
|
|
1533
|
|
1534 (void) fclose (in);
|
|
1535 return OK;
|
|
1536 }
|
|
1537 #endif
|