If heirloom shell is in /usr/lib/heirloom/5bin/sh, use it to run tests.
[mmh] / docs / historical / mh-6.8.5 / zotnet / mts / mts.c
1 /* mts.c - definitions for the mail transport system */
2 #ifndef lint
3 static char ident[] = "@(#)$Id: mts.c,v 2.20 1994/03/23 23:35:23 jromine Exp $";
4 #endif /* lint */
5
6 /* LINTLIBRARY */
7
8 #undef  NETWORK
9 #if     defined(BSD41A) || defined(BSD42) || defined(SOCKETS)
10 #define NETWORK
11 #endif
12
13 #include "../h/strings.h"
14 #include <ctype.h>
15 #include <stdio.h>
16 #include "mts.h"
17 #ifdef  NETWORK
18 #if     defined(BSD42) || defined(SOCKETS)
19 #include <netdb.h>
20 #endif
21 #else   /* NETWORK */
22 #ifndef SYS5
23 #include <whoami.h>
24 #else
25 #include <sys/utsname.h>
26 #endif /* SYS5 */
27 #endif /* NETWORK */
28 #include <pwd.h>
29
30
31 #define NOTOK   (-1)
32 #define OK      0
33
34 #define NULLCP  ((char *) 0)
35
36 extern int  errno;
37
38 static char   *tailor_value ();
39
40
41 #if defined(SYS5) && !defined(_AIX)
42 #define index   strchr
43 #define rindex  strrchr
44 #endif /* SYS5 */
45
46 #if !defined(__STDC__) && !defined(_AIX) && !defined(_POSIX_SOURCE)
47 char   *index (), *malloc (), *mktemp (), *rindex (), *strcpy ();
48
49 #ifdef  SYS5
50 struct passwd  *getpwuid ();
51 #endif
52 #endif /* !__STDC__ */
53
54 /* \f */
55
56 /*
57    *mmdfldir and *uucpldir are the maildrop directories.  If maildrops
58    are kept in the user's home directory, then these should be empty
59    strings.  In this case, the appropriate ...lfil array should contain
60    the name of the file in the user's home directory.  Usually, this is
61    something like ".mail".
62  */
63
64 static char *mtstailor = "/opt/mh-6.8.5/lib/mtstailor";
65
66 static char    *localname = "";
67 static char    *localdomain = "";
68 static char    *systemname = "";
69 #ifdef  MF
70 static char    *UUCPchan = "";
71 #endif /* MF */
72 char    *mmdfldir = "/var/spool/mail";
73 char    *mmdflfil = "";
74 char    *uucpldir = "/usr/spool/mail";
75 char    *uucplfil = "";
76
77
78 char    *mmdlm1 = "\001\001\001\001\n";
79 char    *mmdlm2 = "\001\001\001\001\n";
80
81
82 static int  MMailids = 0;
83 static char *mmailid = "0";
84
85
86 #ifdef  MF
87 char   *umincproc = "/opt/mh-6.8.5/lib/uminc";
88 #else /* MF */
89 char   *umincproc = NULL;
90 #endif /* MF */
91
92
93 int     lockstyle = LOK_UNIX;
94 static char *lkstyle = "0";
95 char   *lockldir = "";
96
97 /* \f */
98
99 /* MTS specific variables */
100
101 #ifdef  MHMTS
102 char   *Mailqdir = "/usr/spool/netmail";
103 char   *TMailqdir = "/usr/tmp";
104 int     Syscpy = 1;
105 static char *syscpy = "1";
106 char   *Overseer = "root";
107 char   *Mailer = "root";
108 char   *Fromtmp = "/tmp/rml.f.XXXXXX";
109 char   *Msgtmp = "/tmp/rml.m.XXXXXX";
110 char   *Errtmp = "/tmp/rml.e.XXXXXX";
111 int     Tmpmode = 0600;
112 static char *tmpmode = "0600";
113 char   *Okhosts = "/opt/mh-6.8.5/lib/Rmail.OkHosts";
114 char   *Okdests = "/opt/mh-6.8.5/lib/Rmail.OkDests";
115 #endif /* MHMTS */
116
117 #ifdef  MMDFMTS
118 #endif /* MMDFMTS */
119
120 #ifdef  SENDMTS
121 char   *hostable = "/opt/mh-6.8.5/lib/hosts";
122 char   *sendmail = "/usr/lib/sendmail";
123 #endif /* SENDMTS */
124
125
126 /* SMTP/POP stuff */
127
128 char   *clientname = (char *)0;
129 char   *servers = "localhost \01localnet";
130 char   *pophost = "";
131
132
133 /* BBoards-specific variables */
134
135 char   *bb_domain = "";
136
137
138 /* POP BBoards-specific variables */
139
140 #ifdef  BPOP
141 char    *popbbhost = "";
142 char    *popbbuser = "";
143 char    *popbblist = "/opt/mh-6.8.5/lib/hosts.popbb";
144 #endif /* BPOP */
145
146
147 /* MailDelivery */
148
149 char   *maildelivery = "/opt/mh-6.8.5/lib/maildelivery";
150
151
152 /* Aliasing Facility (doesn't belong here) */
153
154 int     Everyone = NOTOK;
155 static char *everyone = "-1";
156 char   *NoShell = "";
157
158 /* \f */
159
160 /* customize the MTS settings for MH by reading /opt/mh-6.8.5/lib/mtstailor */
161
162 static  struct bind {
163     char   *keyword;
164     char  **value;
165 }       binds[] = {
166     "localname", &localname,
167     "localdomain", &localdomain,
168     "systemname", &systemname,
169 #ifdef  MF
170     "uucpchan", &UUCPchan,
171 #endif /* MF */
172     "mmdfldir", &mmdfldir,
173     "mmdflfil", &mmdflfil,
174     "uucpldir", &uucpldir,
175     "uucplfil", &uucplfil,
176     "mmdelim1", &mmdlm1,
177     "mmdelim2", &mmdlm2,
178     "mmailid", &mmailid,
179     "umincproc", &umincproc,
180     "lockstyle", &lkstyle,
181     "lockldir", &lockldir,
182
183 #ifdef  MHMTS
184     "mailqdir", &Mailqdir,
185     "tmailqdir", &TMailqdir,
186     "syscpy", &syscpy,
187     "overseer", &Overseer,
188     "mailer", &Mailer,
189     "fromtmp", &Fromtmp,
190     "msgtmp", &Msgtmp,
191     "errtmp", &Errtmp,
192     "tmpmode", &tmpmode,
193     "okhosts", &Okhosts,
194     "okdests", &Okdests,
195 #endif /* MHMTS */
196
197 #ifdef  MMDFMTS
198 #endif /* MMDFMTS */
199
200 #ifdef  SENDMTS
201     "hostable", &hostable,
202     "sendmail", &sendmail,
203 #endif /* SENDMTS */
204
205     "clientname",  &clientname,
206     "servers", &servers,
207     "pophost", &pophost,
208
209     "bbdomain", &bb_domain,
210
211 #ifdef  BPOP
212     "popbbhost", &popbbhost,
213     "popbbuser", &popbbuser,
214     "popbblist", &popbblist,
215 #endif /* BPOP */
216 #ifdef  NNTP
217     "nntphost", &popbbhost,
218 #endif /* NNTP */
219
220     "maildelivery", &maildelivery,
221
222     "everyone", &everyone,
223     "noshell", &NoShell,
224
225     NULL
226 };
227
228 /* \f */
229
230 /* I'd like to use m_getfld() here, but not all programs loading mts.o may be
231    MH-style programs... */
232
233 /* ARGSUSED */
234
235 mts_init (name)
236 char    *name;
237 {
238     register char  *bp,
239                    *cp;
240     char    buffer[BUFSIZ];
241     register struct bind   *b;
242     register    FILE *fp;
243     static int  inited = 0;
244
245     if (inited++ || (fp = fopen (mtstailor, "r")) == NULL)
246         return;
247
248     while (fgets (buffer, sizeof buffer, fp)) {
249         if ((cp = index (buffer, '\n')) == NULL)
250             break;
251         *cp = 0;
252         if (*buffer == '#' || *buffer == '\0')
253             continue;
254         if ((bp = index (buffer, ':')) == NULL)
255             break;
256         *bp++ = 0;
257         while (isspace (*bp))
258             *bp++ = 0;
259
260         for (b = binds; b -> keyword; b++)
261             if (strcmp (buffer, b -> keyword) == 0)
262                 break;
263         if (b -> keyword && (cp = tailor_value (bp)))
264             *b -> value = cp;
265     }
266
267     (void) fclose (fp);
268
269     MMailids = atoi (mmailid);
270     if ((lockstyle = atoi (lkstyle)) < LOK_UNIX || lockstyle > LOK_MMDF)
271         lockstyle = LOK_UNIX;
272 #ifdef  MHMTS
273     Syscpy = atoi (syscpy);
274     (void) sscanf (tmpmode, "0%o", &Tmpmode);
275 #endif /* MHMTS */
276     Everyone = atoi (everyone);
277 }
278
279 /* \f */
280
281 #define QUOTE   '\\'
282
283 static char *tailor_value (s)
284 register char   *s;
285 {
286     register int    i,
287                     r;
288     register char  *bp;
289     char    buffer[BUFSIZ];
290
291     for (bp = buffer; *s; bp++, s++)
292         if (*s != QUOTE)
293             *bp = *s;
294         else
295             switch (*++s) {
296 #define grot(y,z) case y: *bp = z; break;
297                 grot ('b', '\b');
298                 grot ('f', '\f');
299                 grot ('n', '\n');
300                 grot ('t', '\t');
301 #undef  grot
302
303                 case 0: s--;
304                 case QUOTE: 
305                     *bp = QUOTE;
306                     break;
307
308                 default: 
309                     if (!isdigit (*s)) {
310                         *bp++ = QUOTE;
311                         *bp = *s;
312                     }
313                     r = *s != '0' ? 10 : 8;
314                     for (i = 0; isdigit (*s); s++)
315                         i = i * r + *s - '0';
316                     s--;
317                     *bp = toascii (i);
318                     break;
319             }
320     *bp = 0;
321
322     bp = malloc ((unsigned) (strlen (buffer) + 1));
323     if (bp != NULL)
324         (void) strcpy (bp, buffer);
325
326     return bp;
327 }
328
329 /* \f */
330
331 char   *LocalName () {
332 #ifdef  BSD41A
333     char  *myname;
334 #endif /* BSD41A */
335 #if     defined(BSD42) || defined(SOCKETS)
336     register struct hostent *hp;
337 #endif /* BSD42 or SOCKETS */
338 #if     defined(SYS5) && !defined(NETWORK)
339     struct utsname name;
340 #endif /* SYS5 and not NETWORK */
341     static char buffer[BUFSIZ] = "";
342
343     if (buffer[0])
344         return buffer;
345
346     mts_init ("mts");
347     if (*localname)
348         strcpy (buffer, localname);
349     else {
350
351 #ifdef  locname
352     (void) strcpy (buffer, locname);
353 #else /* not locname */
354 #ifdef  NETWORK
355 #ifdef  BSD41A
356     myname = "myname";
357     if (rhost (&myname) == -1)
358         (void) gethostname (buffer, sizeof buffer);
359     else {
360         (void) strcpy (buffer, myname);
361         free (myname);
362     }
363 #endif /* BSD41A */
364 #if     defined(BSD42) || defined(SOCKETS)
365     (void) gethostname (buffer, sizeof buffer);
366 #ifndef BIND
367     sethostent (1);
368 #endif
369     if (hp = gethostbyname (buffer))
370         (void) strcpy (buffer, hp -> h_name);
371 #endif /* BSD42 or SOCKETS */
372 #else /* not NETWORK */
373 #ifndef SYS5
374     (void) strcpy (buffer, SystemName ());
375 #else /* SYS5 */
376     (void) uname (&name);
377     (void) strcpy (buffer, name.nodename);
378 #endif /* SYS5 */
379 #endif /* not NETWORK */
380 #endif /* not locname */
381     }
382     if (*localdomain) {
383         strcat (buffer, ".");
384         strcat (buffer, localdomain);
385     }
386     return buffer;
387 }
388
389 /* \f */
390
391 char *SystemName () {
392 #if     defined(SYS5) && !defined(NETWORK)
393     struct utsname name;
394 #endif /* SYS5 and not NETWORK */
395     static char buffer[BUFSIZ] = "";
396
397     if (buffer[0])
398         return buffer;
399
400     mts_init ("mts");
401     if (*systemname)
402         return strcpy (buffer, systemname);
403
404 #ifdef  sysname
405     (void) strcpy (buffer, sysname);
406 #else /* sysname */
407 #if     !defined(SYS5) || defined(NETWORK)
408     (void) gethostname (buffer, sizeof buffer);
409 #else /* SYS5 and not NETWORK */
410 #ifdef  SYS5
411     (void) uname (&name);
412     (void) strcpy (buffer, name.nodename);
413 #endif /* SYS5 */
414 #endif /* SYS5 and not NETWORK */
415 #endif /* sysname */
416
417     return buffer;
418 }
419
420 /* \f */
421
422 char   *UucpChan () {
423 #ifdef  MF
424     static char buffer[BUFSIZ] = "";
425 #endif /* MF */
426
427 #ifndef MF
428     return NULL;
429 #else /* MF */
430     if (buffer[0])
431         return buffer;
432
433     mts_init ("mts");
434     if (*UUCPchan)
435         return strcpy (buffer, UUCPchan);
436
437 #ifdef  uucpchan
438     (void) strcpy (buffer, uucpchan);
439 #else /* uucpchan */
440     (void) strcpy (buffer, "uucp");
441 #endif /* uucpchan */
442     return buffer;
443 #endif /* MF */
444 }
445
446 /* \f */
447
448 #ifdef  ALTOS
449 gethostname (name, len)
450 register char   *name;
451 register int     len;
452 {
453     register char  *cp;
454     register FILE  *fp;
455
456     if (fp = fopen ("/etc/systemid", "r")) {
457         if (fgets (name, len, fp)) {
458             if (cp = index (name, '\n'))
459                 *cp = 0;
460             (void) fclose (fp);
461             return OK;
462         }
463         (void) fclose (fp);
464     }
465     (void) strncpy (name, "altos", len);
466
467     return OK;
468 }
469 #endif /* ALTOS */
470
471 /* \f */
472
473 static char username[BUFSIZ];
474 static char fullname[BUFSIZ];
475
476
477 char   *getusr () {
478     register char  *cp,
479                    *np;
480 #ifdef KPOP
481     int uid;
482 #endif /* KPOP */
483     register struct passwd *pw;
484
485     if (username[0])
486         return username;
487
488 #ifndef KPOP
489     if ((pw = getpwuid (getuid ())) == NULL
490             || pw -> pw_name == NULL
491             || *pw -> pw_name == NULL) {
492 #else /* KPOP */
493     uid = getuid ();
494     if (uid == geteuid () && (cp = getenv ("USER")) != NULL
495         && (pw = getpwnam (cp)) != NULL)
496       strcpy (username, cp);
497     else if ((pw = getpwuid (uid)) == NULL
498              || pw -> pw_name == NULL
499              || *pw -> pw_name == '\0') {
500 #endif /* KPOP */
501         (void) strcpy (username, "unknown");
502         (void) sprintf (fullname, "The Unknown User-ID (%d)", getuid ());
503         return username;
504     }
505
506     np = pw -> pw_gecos;
507 #ifndef GCOS_HACK
508     for (cp = fullname; *np && *np != (MMailids ? '<' : ','); *cp++ = *np++)
509         continue;
510 #else
511     for (cp = fullname; *np && *np != (MMailids ? '<' : ','); )
512         if (*np == '&') {       /* blech! */
513             (void) strcpy(cp, pw -> pw_name);
514             *cp = toupper(*cp);
515             while (*cp)
516                 cp++;
517             np++;
518         }
519         else
520             *cp++ = *np++;
521 #endif
522     *cp = '\0';
523     if (MMailids) {
524         if (*np)
525             np++;
526         for (cp = username; *np && *np != '>'; *cp++ = *np++)
527             continue;
528         *cp = '\0';
529     }
530     if (MMailids == 0 || *np == '\0')
531         (void) strcpy (username, pw -> pw_name);
532
533     if ((cp = getenv ("SIGNATURE")) && *cp)
534         (void) strcpy (fullname, cp);
535     if (index(fullname, '.')) {         /*  quote any .'s */
536           char tmp[BUFSIZ];
537       sprintf (tmp, "\"%s\"", fullname);/* should quote "'s too */
538       strcpy (fullname, tmp);
539     }
540
541     return username;
542 }
543
544
545 char   *getfullname () {
546     if (username[0] == '\0')
547         (void) getusr ();
548
549     return fullname;
550 }
551
552 /* \f */
553
554 #ifdef  SYS5
555 #ifndef notdef                  /* Supposedly this works, I prefer the
556                                    recursive solution... */
557
558 #include <fcntl.h>
559
560 int     dup2 (d1, d2)
561 register int    d1,
562                 d2;
563 {
564     int     d;
565
566     if (d1 == d2)
567         return OK;
568
569     (void) close (d2);
570     if ((d = fcntl (d1, F_DUPFD, d2)) == NOTOK)
571         return NOTOK;
572     if (d == d2)
573         return OK;
574
575     errno = 0;
576     return NOTOK;
577 }
578
579 #else /* notdef */
580 int     dup2 (d1, d2)
581 register int    d1,
582                 d2;
583 {
584     if (d1 == d2)
585         return OK;
586
587     (void) close (d2);
588     return dup2aux (d1, d2);
589 }
590
591
592 static int  dup2aux (d1, d2)
593 register int    d1,
594                 d2;
595 {
596     int     d,
597             i,
598             eindex;
599
600     if ((d = dup (d1)) == NOTOK)
601         return NOTOK;
602     if (d == d2)
603         return OK;
604
605     i = dup2aux (d1, d2);
606     eindex = errno;
607     (void) close (d);
608     errno = eindex;
609     return i;
610 }
611 #endif /* notdef */
612 #endif /* SYS5 */