source: trunk/third/sendmail/src/envelope.c @ 12554

Revision 12554, 21.7 KB checked in by danw, 26 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r12553, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2 * Copyright (c) 1998 Sendmail, Inc.  All rights reserved.
3 * Copyright (c) 1983, 1995-1997 Eric P. Allman.  All rights reserved.
4 * Copyright (c) 1988, 1993
5 *      The Regents of the University of California.  All rights reserved.
6 *
7 * By using this file, you agree to the terms and conditions set
8 * forth in the LICENSE file which can be found at the top level of
9 * the sendmail distribution.
10 *
11 */
12
13#ifndef lint
14static char sccsid[] = "@(#)envelope.c  8.122 (Berkeley) 1/25/1999";
15#endif /* not lint */
16
17#include "sendmail.h"
18
19/*
20**  NEWENVELOPE -- allocate a new envelope
21**
22**      Supports inheritance.
23**
24**      Parameters:
25**              e -- the new envelope to fill in.
26**              parent -- the envelope to be the parent of e.
27**
28**      Returns:
29**              e.
30**
31**      Side Effects:
32**              none.
33*/
34
35ENVELOPE *
36newenvelope(e, parent)
37        register ENVELOPE *e;
38        register ENVELOPE *parent;
39{
40        if (e == parent && e->e_parent != NULL)
41                parent = e->e_parent;
42        clearenvelope(e, TRUE);
43        if (e == CurEnv)
44                bcopy((char *) &NullAddress, (char *) &e->e_from, sizeof e->e_from);
45        else
46                bcopy((char *) &CurEnv->e_from, (char *) &e->e_from, sizeof e->e_from);
47        e->e_parent = parent;
48        e->e_ctime = curtime();
49        if (parent != NULL)
50                e->e_msgpriority = parent->e_msgsize;
51        e->e_puthdr = putheader;
52        e->e_putbody = putbody;
53        if (CurEnv->e_xfp != NULL)
54                (void) fflush(CurEnv->e_xfp);
55
56        return (e);
57}
58/*
59**  DROPENVELOPE -- deallocate an envelope.
60**
61**      Parameters:
62**              e -- the envelope to deallocate.
63**              fulldrop -- if set, do return receipts.
64**
65**      Returns:
66**              none.
67**
68**      Side Effects:
69**              housekeeping necessary to dispose of an envelope.
70**              Unlocks this queue file.
71*/
72
73void
74dropenvelope(e, fulldrop)
75        register ENVELOPE *e;
76        bool fulldrop;
77{
78        bool queueit = FALSE;
79        bool message_timeout = FALSE;
80        bool failure_return = FALSE;
81        bool delay_return = FALSE;
82        bool success_return = FALSE;
83        register ADDRESS *q;
84        char *id = e->e_id;
85        char buf[MAXLINE];
86
87        if (tTd(50, 1))
88        {
89                extern void printenvflags __P((ENVELOPE *));
90
91                printf("dropenvelope %lx: id=", (u_long) e);
92                xputs(e->e_id);
93                printf(", flags=");
94                printenvflags(e);
95                if (tTd(50, 10))
96                {
97                        printf("sendq=");
98                        printaddr(e->e_sendqueue, TRUE);
99                }
100        }
101
102        if (LogLevel > 84)
103                sm_syslog(LOG_DEBUG, id,
104                        "dropenvelope, e_flags=0x%x, OpMode=%c, pid=%d",
105                        e->e_flags, OpMode, getpid());
106
107        /* we must have an id to remove disk files */
108        if (id == NULL)
109                return;
110
111        /* if verify-only mode, we can skip most of this */
112        if (OpMode == MD_VERIFY)
113                goto simpledrop;
114
115        if (LogLevel > 4 && bitset(EF_LOGSENDER, e->e_flags))
116                logsender(e, NULL);
117        e->e_flags &= ~EF_LOGSENDER;
118
119        /* post statistics */
120        poststats(StatFile);
121
122        /*
123        **  Extract state information from dregs of send list.
124        */
125
126        if (curtime() > e->e_ctime + TimeOuts.to_q_return[e->e_timeoutclass])
127                message_timeout = TRUE;
128
129        e->e_flags &= ~EF_QUEUERUN;
130        for (q = e->e_sendqueue; q != NULL; q = q->q_next)
131        {
132                if (bitset(QQUEUEUP, q->q_flags) &&
133                    bitset(QDONTSEND, q->q_flags))
134                {
135                        /* I'm not sure how this happens..... */
136                        if (tTd(50, 2))
137                        {
138                                printf("Bogus flags: ");
139                                printaddr(q, FALSE);
140                        }
141                        q->q_flags &= ~QDONTSEND;
142                }
143                if (!bitset(QBADADDR|QDONTSEND|QSENT, q->q_flags))
144                        queueit = TRUE;
145#if XDEBUG
146                else if (bitset(QQUEUEUP, q->q_flags))
147                        sm_syslog(LOG_DEBUG, e->e_id,
148                                "dropenvelope: q_flags = %x, paddr = %s",
149                                q->q_flags, q->q_paddr);
150#endif
151
152                /* see if a notification is needed */
153                if (bitset(QPINGONFAILURE, q->q_flags) &&
154                    ((message_timeout && bitset(QQUEUEUP, q->q_flags)) ||
155                     bitset(QBADADDR, q->q_flags)))
156                {
157                        failure_return = TRUE;
158                        if (q->q_owner == NULL && !emptyaddr(&e->e_from))
159                                (void) sendtolist(e->e_from.q_paddr, NULLADDR,
160                                                  &e->e_errorqueue, 0, e);
161                }
162                else if (bitset(QPINGONSUCCESS, q->q_flags) &&
163                         ((bitset(QSENT, q->q_flags) &&
164                           bitnset(M_LOCALMAILER, q->q_mailer->m_flags)) ||
165                          bitset(QRELAYED|QEXPANDED|QDELIVERED, q->q_flags)))
166                {
167                        success_return = TRUE;
168                }
169        }
170
171        if (e->e_class < 0)
172                e->e_flags |= EF_NO_BODY_RETN;
173
174        /*
175        **  See if the message timed out.
176        */
177
178        if (!queueit)
179                /* nothing to do */ ;
180        else if (message_timeout)
181        {
182                if (failure_return)
183                {
184                        (void) snprintf(buf, sizeof buf,
185                                "Cannot send message within %s",
186                                pintvl(TimeOuts.to_q_return[e->e_timeoutclass], FALSE));
187                        if (e->e_message != NULL)
188                                free(e->e_message);
189                        e->e_message = newstr(buf);
190                        message(buf);
191                        e->e_flags |= EF_CLRQUEUE;
192                }
193                fprintf(e->e_xfp, "Message could not be delivered for %s\n",
194                        pintvl(TimeOuts.to_q_return[e->e_timeoutclass], FALSE));
195                fprintf(e->e_xfp, "Message will be deleted from queue\n");
196                for (q = e->e_sendqueue; q != NULL; q = q->q_next)
197                {
198                        if (!bitset(QBADADDR|QDONTSEND|QSENT, q->q_flags))
199                        {
200                                q->q_flags |= QBADADDR;
201                                q->q_status = "4.4.7";
202                        }
203                }
204        }
205        else if (TimeOuts.to_q_warning[e->e_timeoutclass] > 0 &&
206            curtime() > e->e_ctime + TimeOuts.to_q_warning[e->e_timeoutclass])
207        {
208                if (!bitset(EF_WARNING|EF_RESPONSE, e->e_flags) &&
209                    e->e_class >= 0 &&
210                    e->e_from.q_paddr != NULL &&
211                    strcmp(e->e_from.q_paddr, "<>") != 0 &&
212                    strncasecmp(e->e_from.q_paddr, "owner-", 6) != 0 &&
213                    (strlen(e->e_from.q_paddr) <= (SIZE_T) 8 ||
214                     strcasecmp(&e->e_from.q_paddr[strlen(e->e_from.q_paddr) - 8], "-request") != 0))
215                {
216                        for (q = e->e_sendqueue; q != NULL; q = q->q_next)
217                        {
218                                if (bitset(QQUEUEUP, q->q_flags) &&
219                                    bitset(QPINGONDELAY, q->q_flags))
220                                {
221                                        q->q_flags |= QDELAYED;
222                                        delay_return = TRUE;
223                                }
224                        }
225                }
226                if (delay_return)
227                {
228                        (void) snprintf(buf, sizeof buf,
229                                "Warning: could not send message for past %s",
230                                pintvl(TimeOuts.to_q_warning[e->e_timeoutclass], FALSE));
231                        if (e->e_message != NULL)
232                                free(e->e_message);
233                        e->e_message = newstr(buf);
234                        message(buf);
235                        e->e_flags |= EF_WARNING;
236                }
237                fprintf(e->e_xfp,
238                        "Warning: message still undelivered after %s\n",
239                        pintvl(TimeOuts.to_q_warning[e->e_timeoutclass], FALSE));
240                fprintf(e->e_xfp, "Will keep trying until message is %s old\n",
241                        pintvl(TimeOuts.to_q_return[e->e_timeoutclass], FALSE));
242        }
243
244        if (tTd(50, 2))
245                printf("failure_return=%d delay_return=%d success_return=%d queueit=%d\n",
246                        failure_return, delay_return, success_return, queueit);
247
248        /*
249        **  If we had some fatal error, but no addresses are marked as
250        **  bad, mark them _all_ as bad.
251        */
252
253        if (bitset(EF_FATALERRS, e->e_flags) && !failure_return)
254        {
255                for (q = e->e_sendqueue; q != NULL; q = q->q_next)
256                {
257                        if (!bitset(QDONTSEND, q->q_flags) &&
258                            bitset(QPINGONFAILURE, q->q_flags))
259                        {
260                                failure_return = TRUE;
261                                q->q_flags |= QBADADDR;
262                        }
263                }
264        }
265
266        /*
267        **  Send back return receipts as requested.
268        */
269
270        if (success_return && !failure_return && !delay_return && fulldrop &&
271            !bitset(PRIV_NORECEIPTS, PrivacyFlags) &&
272            strcmp(e->e_from.q_paddr, "<>") != 0)
273        {
274                auto ADDRESS *rlist = NULL;
275
276                if (tTd(50, 8))
277                        printf("dropenvelope(%s): sending return receipt\n", id);
278                e->e_flags |= EF_SENDRECEIPT;
279                (void) sendtolist(e->e_from.q_paddr, NULLADDR, &rlist, 0, e);
280                (void) returntosender("Return receipt", rlist, RTSF_NO_BODY, e);
281        }
282        e->e_flags &= ~EF_SENDRECEIPT;
283
284        /*
285        **  Arrange to send error messages if there are fatal errors.
286        */
287
288        if ((failure_return || delay_return) && e->e_errormode != EM_QUIET)
289        {
290                extern void savemail __P((ENVELOPE *, bool));
291
292                if (tTd(50, 8))
293                        printf("dropenvelope(%s): saving mail\n", id);
294                savemail(e, !bitset(EF_NO_BODY_RETN, e->e_flags));
295        }
296
297        /*
298        **  Arrange to send warning messages to postmaster as requested.
299        */
300
301        if ((failure_return || bitset(EF_PM_NOTIFY, e->e_flags)) &&
302            PostMasterCopy != NULL &&
303            !bitset(EF_RESPONSE, e->e_flags) && e->e_class >= 0)
304        {
305                auto ADDRESS *rlist = NULL;
306
307                if (tTd(50, 8))
308                        printf("dropenvelope(%s): sending postmaster copy\n", id);
309                (void) sendtolist(PostMasterCopy, NULLADDR, &rlist, 0, e);
310                (void) returntosender(e->e_message, rlist, RTSF_PM_BOUNCE, e);
311        }
312
313        /*
314        **  Instantiate or deinstantiate the queue.
315        */
316
317simpledrop:
318        if (tTd(50, 8))
319                printf("dropenvelope(%s): at simpledrop, queueit=%d\n",
320                        id, queueit);
321        if (!queueit || bitset(EF_CLRQUEUE, e->e_flags))
322        {
323                if (tTd(50, 1))
324                {
325                        extern void printenvflags __P((ENVELOPE *));
326
327                        printf("\n===== Dropping [dq]f%s... queueit=%d, e_flags=",
328                                e->e_id, queueit);
329                        printenvflags(e);
330                }
331                xunlink(queuename(e, 'd'));
332                xunlink(queuename(e, 'q'));
333
334                if (LogLevel > 10)
335                        sm_syslog(LOG_INFO, id, "done");
336        }
337        else if (queueit || !bitset(EF_INQUEUE, e->e_flags))
338        {
339#if QUEUE
340                queueup(e, FALSE);
341#else /* QUEUE */
342                syserr("554 dropenvelope: queueup");
343#endif /* QUEUE */
344        }
345
346        /* now unlock the job */
347        if (tTd(50, 8))
348                printf("dropenvelope(%s): unlocking job\n", id);
349        closexscript(e);
350        unlockqueue(e);
351
352        /* make sure that this envelope is marked unused */
353        if (e->e_dfp != NULL)
354                (void) xfclose(e->e_dfp, "dropenvelope df", e->e_id);
355        e->e_dfp = NULL;
356        e->e_id = NULL;
357        e->e_flags &= ~EF_HAS_DF;
358}
359/*
360**  CLEARENVELOPE -- clear an envelope without unlocking
361**
362**      This is normally used by a child process to get a clean
363**      envelope without disturbing the parent.
364**
365**      Parameters:
366**              e -- the envelope to clear.
367**              fullclear - if set, the current envelope is total
368**                      garbage and should be ignored; otherwise,
369**                      release any resources it may indicate.
370**
371**      Returns:
372**              none.
373**
374**      Side Effects:
375**              Closes files associated with the envelope.
376**              Marks the envelope as unallocated.
377*/
378
379void
380clearenvelope(e, fullclear)
381        register ENVELOPE *e;
382        bool fullclear;
383{
384        register HDR *bh;
385        register HDR **nhp;
386        extern ENVELOPE BlankEnvelope;
387
388        if (!fullclear)
389        {
390                /* clear out any file information */
391                if (e->e_xfp != NULL)
392                        (void) xfclose(e->e_xfp, "clearenvelope xfp", e->e_id);
393                if (e->e_dfp != NULL)
394                        (void) xfclose(e->e_dfp, "clearenvelope dfp", e->e_id);
395                e->e_xfp = e->e_dfp = NULL;
396        }
397
398        /* now clear out the data */
399        STRUCTCOPY(BlankEnvelope, *e);
400        e->e_message = NULL;
401        if (Verbose)
402                e->e_sendmode = SM_DELIVER;
403        bh = BlankEnvelope.e_header;
404        nhp = &e->e_header;
405        while (bh != NULL)
406        {
407                *nhp = (HDR *) xalloc(sizeof *bh);
408                bcopy((char *) bh, (char *) *nhp, sizeof *bh);
409                bh = bh->h_link;
410                nhp = &(*nhp)->h_link;
411        }
412}
413/*
414**  INITSYS -- initialize instantiation of system
415**
416**      In Daemon mode, this is done in the child.
417**
418**      Parameters:
419**              none.
420**
421**      Returns:
422**              none.
423**
424**      Side Effects:
425**              Initializes the system macros, some global variables,
426**              etc.  In particular, the current time in various
427**              forms is set.
428*/
429
430void
431initsys(e)
432        register ENVELOPE *e;
433{
434        char cbuf[5];                           /* holds hop count */
435        char pbuf[10];                          /* holds pid */
436#ifdef TTYNAME
437        static char ybuf[60];                   /* holds tty id */
438        register char *p;
439        extern char *ttyname();
440#endif /* TTYNAME */
441        extern void settime __P((ENVELOPE *));
442
443        /*
444        **  Give this envelope a reality.
445        **      I.e., an id, a transcript, and a creation time.
446        */
447
448        openxscript(e);
449        e->e_ctime = curtime();
450
451        /*
452        **  Set OutChannel to something useful if stdout isn't it.
453        **      This arranges that any extra stuff the mailer produces
454        **      gets sent back to the user on error (because it is
455        **      tucked away in the transcript).
456        */
457
458        if (OpMode == MD_DAEMON && bitset(EF_QUEUERUN, e->e_flags) &&
459            e->e_xfp != NULL)
460                OutChannel = e->e_xfp;
461
462        /*
463        **  Set up some basic system macros.
464        */
465
466        /* process id */
467        (void) snprintf(pbuf, sizeof pbuf, "%d", getpid());
468        define('p', newstr(pbuf), e);
469
470        /* hop count */
471        (void) snprintf(cbuf, sizeof cbuf, "%d", e->e_hopcount);
472        define('c', newstr(cbuf), e);
473
474        /* time as integer, unix time, arpa time */
475        settime(e);
476
477#ifdef TTYNAME
478        /* tty name */
479        if (macvalue('y', e) == NULL)
480        {
481                p = ttyname(2);
482                if (p != NULL)
483                {
484                        if (strrchr(p, '/') != NULL)
485                                p = strrchr(p, '/') + 1;
486                        snprintf(ybuf, sizeof ybuf, "%s", p);
487                        define('y', ybuf, e);
488                }
489        }
490#endif /* TTYNAME */
491}
492/*
493**  SETTIME -- set the current time.
494**
495**      Parameters:
496**              none.
497**
498**      Returns:
499**              none.
500**
501**      Side Effects:
502**              Sets the various time macros -- $a, $b, $d, $t.
503*/
504
505void
506settime(e)
507        register ENVELOPE *e;
508{
509        register char *p;
510        auto time_t now;
511        char tbuf[20];                          /* holds "current" time */
512        char dbuf[30];                          /* holds ctime(tbuf) */
513        register struct tm *tm;
514        extern struct tm *gmtime();
515
516        now = curtime();
517        tm = gmtime(&now);
518        (void) snprintf(tbuf, sizeof tbuf, "%04d%02d%02d%02d%02d", tm->tm_year + 1900,
519                        tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min);
520        define('t', newstr(tbuf), e);
521        (void) strcpy(dbuf, ctime(&now));
522        p = strchr(dbuf, '\n');
523        if (p != NULL)
524                *p = '\0';
525        define('d', newstr(dbuf), e);
526        p = arpadate(dbuf);
527        p = newstr(p);
528        if (macvalue('a', e) == NULL)
529                define('a', p, e);
530        define('b', p, e);
531}
532/*
533**  OPENXSCRIPT -- Open transcript file
534**
535**      Creates a transcript file for possible eventual mailing or
536**      sending back.
537**
538**      Parameters:
539**              e -- the envelope to create the transcript in/for.
540**
541**      Returns:
542**              none
543**
544**      Side Effects:
545**              Creates the transcript file.
546*/
547
548#ifndef O_APPEND
549#define O_APPEND        0
550#endif
551
552void
553openxscript(e)
554        register ENVELOPE *e;
555{
556        register char *p;
557        int fd;
558
559        if (e->e_xfp != NULL)
560                return;
561        p = queuename(e, 'x');
562        fd = open(p, O_WRONLY|O_CREAT|O_APPEND, FileMode);
563        if (fd < 0)
564        {
565                syserr("Can't create transcript file %s", p);
566                fd = open("/dev/null", O_WRONLY, 0644);
567                if (fd < 0)
568                        syserr("!Can't open /dev/null");
569        }
570        e->e_xfp = fdopen(fd, "a");
571        if (e->e_xfp == NULL)
572                syserr("!Can't create transcript stream %s", p);
573#ifdef HASSETVBUF
574        setvbuf(e->e_xfp, NULL, _IOLBF, 0);
575#else
576        setlinebuf(e->e_xfp);
577#endif
578        if (tTd(46, 9))
579        {
580                printf("openxscript(%s):\n  ", p);
581                dumpfd(fileno(e->e_xfp), TRUE, FALSE);
582        }
583}
584/*
585**  CLOSEXSCRIPT -- close the transcript file.
586**
587**      Parameters:
588**              e -- the envelope containing the transcript to close.
589**
590**      Returns:
591**              none.
592**
593**      Side Effects:
594**              none.
595*/
596
597void
598closexscript(e)
599        register ENVELOPE *e;
600{
601        if (e->e_xfp == NULL)
602                return;
603        (void) xfclose(e->e_xfp, "closexscript", e->e_id);
604        e->e_xfp = NULL;
605}
606/*
607**  SETSENDER -- set the person who this message is from
608**
609**      Under certain circumstances allow the user to say who
610**      s/he is (using -f or -r).  These are:
611**      1.  The user's uid is zero (root).
612**      2.  The user's login name is in an approved list (typically
613**          from a network server).
614**      3.  The address the user is trying to claim has a
615**          "!" character in it (since #2 doesn't do it for
616**          us if we are dialing out for UUCP).
617**      A better check to replace #3 would be if the
618**      effective uid is "UUCP" -- this would require me
619**      to rewrite getpwent to "grab" uucp as it went by,
620**      make getname more nasty, do another passwd file
621**      scan, or compile the UID of "UUCP" into the code,
622**      all of which are reprehensible.
623**
624**      Assuming all of these fail, we figure out something
625**      ourselves.
626**
627**      Parameters:
628**              from -- the person we would like to believe this message
629**                      is from, as specified on the command line.
630**              e -- the envelope in which we would like the sender set.
631**              delimptr -- if non-NULL, set to the location of the
632**                      trailing delimiter.
633**              delimchar -- the character that will delimit the sender
634**                      address.
635**              internal -- set if this address is coming from an internal
636**                      source such as an owner alias.
637**
638**      Returns:
639**              none.
640**
641**      Side Effects:
642**              sets sendmail's notion of who the from person is.
643*/
644
645void
646setsender(from, e, delimptr, delimchar, internal)
647        char *from;
648        register ENVELOPE *e;
649        char **delimptr;
650        int delimchar;
651        bool internal;
652{
653        register char **pvp;
654        char *realname = NULL;
655        register struct passwd *pw;
656        char *bp;
657        char buf[MAXNAME + 2];
658        char pvpbuf[PSBUFSIZE];
659        extern char *FullName;
660
661        if (tTd(45, 1))
662                printf("setsender(%s)\n", from == NULL ? "" : from);
663
664        /*
665        **  Figure out the real user executing us.
666        **      Username can return errno != 0 on non-errors.
667        */
668
669        if (bitset(EF_QUEUERUN, e->e_flags) || OpMode == MD_SMTP ||
670            OpMode == MD_ARPAFTP || OpMode == MD_DAEMON)
671                realname = from;
672        if (realname == NULL || realname[0] == '\0')
673                realname = username();
674
675        if (ConfigLevel < 2)
676                SuprErrs = TRUE;
677
678        e->e_from.q_flags = QBADADDR;
679        if (from == NULL ||
680            parseaddr(from, &e->e_from, RF_COPYALL|RF_SENDERADDR,
681                      delimchar, delimptr, e) == NULL ||
682            bitset(QBADADDR, e->e_from.q_flags) ||
683            e->e_from.q_mailer == ProgMailer ||
684            e->e_from.q_mailer == FileMailer ||
685            e->e_from.q_mailer == InclMailer)
686        {
687                /* log garbage addresses for traceback */
688                if (from != NULL && LogLevel > 2)
689                {
690                        char *p;
691                        char ebuf[MAXNAME * 2 + 2];
692
693                        p = macvalue('_', e);
694                        if (p == NULL)
695                        {
696                                char *host = RealHostName;
697
698                                if (host == NULL)
699                                        host = MyHostName;
700                                (void) snprintf(ebuf, sizeof ebuf, "%.*s@%.*s",
701                                        MAXNAME, realname,
702                                        MAXNAME, host);
703                                p = ebuf;
704                        }
705                        sm_syslog(LOG_NOTICE, e->e_id,
706                                "setsender: %s: invalid or unparseable, received from %s",
707                                shortenstring(from, 83), p);
708                }
709                if (from != NULL)
710                {
711                        if (!bitset(QBADADDR, e->e_from.q_flags))
712                        {
713                                /* it was a bogus mailer in the from addr */
714                                e->e_status = "5.1.7";
715                                usrerr("553 Invalid sender address");
716                        }
717                        SuprErrs = TRUE;
718                }
719                if (from == realname ||
720                    parseaddr(from = newstr(realname), &e->e_from,
721                              RF_COPYALL|RF_SENDERADDR, ' ', NULL, e) == NULL)
722                {
723                        char nbuf[100];
724
725                        SuprErrs = TRUE;
726                        expand("\201n", nbuf, sizeof nbuf, e);
727                        if (parseaddr(from = newstr(nbuf), &e->e_from,
728                                      RF_COPYALL, ' ', NULL, e) == NULL &&
729                            parseaddr(from = "postmaster", &e->e_from,
730                                      RF_COPYALL, ' ', NULL, e) == NULL)
731                                syserr("553 setsender: can't even parse postmaster!");
732                }
733        }
734        else
735                FromFlag = TRUE;
736        e->e_from.q_flags |= QDONTSEND;
737        if (tTd(45, 5))
738        {
739                printf("setsender: QDONTSEND ");
740                printaddr(&e->e_from, FALSE);
741        }
742        SuprErrs = FALSE;
743
744# if USERDB
745        if (bitnset(M_CHECKUDB, e->e_from.q_mailer->m_flags))
746        {
747                register char *p;
748                extern char *udbsender __P((char *));
749
750                p = udbsender(e->e_from.q_user);
751                if (p != NULL)
752                        from = p;
753        }
754# endif /* USERDB */
755
756        if (bitnset(M_HASPWENT, e->e_from.q_mailer->m_flags))
757        {
758                if (!internal)
759                {
760                        /* if the user already given fullname don't redefine */
761                        if (FullName == NULL)
762                                FullName = macvalue('x', e);
763                        if (FullName != NULL && FullName[0] == '\0')
764                                FullName = NULL;
765                }
766
767                if (e->e_from.q_user[0] != '\0' &&
768                    (pw = sm_getpwnam(e->e_from.q_user)) != NULL)
769                {
770                        /*
771                        **  Process passwd file entry.
772                        */
773
774                        /* extract home directory */
775                        if (strcmp(pw->pw_dir, "/") == 0)
776                                e->e_from.q_home = newstr("");
777                        else
778                                e->e_from.q_home = newstr(pw->pw_dir);
779                        define('z', e->e_from.q_home, e);
780
781                        /* extract user and group id */
782                        e->e_from.q_uid = pw->pw_uid;
783                        e->e_from.q_gid = pw->pw_gid;
784                        e->e_from.q_flags |= QGOODUID;
785
786                        /* extract full name from passwd file */
787                        if (FullName == NULL && pw->pw_gecos != NULL &&
788                            strcmp(pw->pw_name, e->e_from.q_user) == 0 &&
789                            !internal)
790                        {
791                                buildfname(pw->pw_gecos, e->e_from.q_user, buf, sizeof buf);
792                                if (buf[0] != '\0')
793                                        FullName = newstr(buf);
794                        }
795                }
796                else
797                {
798                        e->e_from.q_home = "/no/such/directory";
799                }
800                if (FullName != NULL && !internal)
801                        define('x', FullName, e);
802        }
803        else if (!internal && OpMode != MD_DAEMON && OpMode != MD_SMTP)
804        {
805                if (e->e_from.q_home == NULL)
806                {
807                        e->e_from.q_home = getenv("HOME");
808                        if (e->e_from.q_home != NULL &&
809                            strcmp(e->e_from.q_home, "/") == 0)
810                                e->e_from.q_home++;
811                }
812                e->e_from.q_uid = RealUid;
813                e->e_from.q_gid = RealGid;
814                e->e_from.q_flags |= QGOODUID;
815        }
816
817        /*
818        **  Rewrite the from person to dispose of possible implicit
819        **      links in the net.
820        */
821
822        pvp = prescan(from, delimchar, pvpbuf, sizeof pvpbuf, NULL, NULL);
823        if (pvp == NULL)
824        {
825                /* don't need to give error -- prescan did that already */
826                if (LogLevel > 2)
827                        sm_syslog(LOG_NOTICE, e->e_id,
828                                "cannot prescan from (%s)",
829                                shortenstring(from, MAXSHORTSTR));
830                finis(TRUE, ExitStat);
831        }
832        (void) rewrite(pvp, 3, 0, e);
833        (void) rewrite(pvp, 1, 0, e);
834        (void) rewrite(pvp, 4, 0, e);
835        bp = buf + 1;
836        cataddr(pvp, NULL, bp, sizeof buf - 2, '\0');
837        if (*bp == '@' && !bitnset(M_NOBRACKET, e->e_from.q_mailer->m_flags))
838        {
839                /* heuristic: route-addr: add angle brackets */
840                strcat(bp, ">");
841                *--bp = '<';
842        }
843        e->e_sender = newstr(bp);
844        define('f', e->e_sender, e);
845
846        /* save the domain spec if this mailer wants it */
847        if (e->e_from.q_mailer != NULL &&
848            bitnset(M_CANONICAL, e->e_from.q_mailer->m_flags))
849        {
850                char **lastat;
851                extern char **copyplist __P((char **, bool));
852
853                /* get rid of any pesky angle brackets */
854                (void) rewrite(pvp, 3, 0, e);
855                (void) rewrite(pvp, 1, 0, e);
856                (void) rewrite(pvp, 4, 0, e);
857
858                /* strip off to the last "@" sign */
859                for (lastat = NULL; *pvp != NULL; pvp++)
860                        if (strcmp(*pvp, "@") == 0)
861                                lastat = pvp;
862                if (lastat != NULL)
863                {
864                        e->e_fromdomain = copyplist(lastat, TRUE);
865                        if (tTd(45, 3))
866                        {
867                                printf("Saving from domain: ");
868                                printav(e->e_fromdomain);
869                        }
870                }
871        }
872}
873/*
874**  PRINTENVFLAGS -- print envelope flags for debugging
875**
876**      Parameters:
877**              e -- the envelope with the flags to be printed.
878**
879**      Returns:
880**              none.
881*/
882
883struct eflags
884{
885        char    *ef_name;
886        u_long  ef_bit;
887};
888
889struct eflags   EnvelopeFlags[] =
890{
891        { "OLDSTYLE",           EF_OLDSTYLE     },
892        { "INQUEUE",            EF_INQUEUE      },
893        { "NO_BODY_RETN",       EF_NO_BODY_RETN },
894        { "CLRQUEUE",           EF_CLRQUEUE     },
895        { "SENDRECEIPT",        EF_SENDRECEIPT  },
896        { "FATALERRS",          EF_FATALERRS    },
897        { "DELETE_BCC",         EF_DELETE_BCC   },
898        { "RESPONSE",           EF_RESPONSE     },
899        { "RESENT",             EF_RESENT       },
900        { "VRFYONLY",           EF_VRFYONLY     },
901        { "WARNING",            EF_WARNING      },
902        { "QUEUERUN",           EF_QUEUERUN     },
903        { "GLOBALERRS",         EF_GLOBALERRS   },
904        { "PM_NOTIFY",          EF_PM_NOTIFY    },
905        { "METOO",              EF_METOO        },
906        { "LOGSENDER",          EF_LOGSENDER    },
907        { "NORECEIPT",          EF_NORECEIPT    },
908        { "HAS8BIT",            EF_HAS8BIT      },
909        { "NL_NOT_EOL",         EF_NL_NOT_EOL   },
910        { "CRLF_NOT_EOL",       EF_CRLF_NOT_EOL },
911        { "RET_PARAM",          EF_RET_PARAM    },
912        { "HAS_DF",             EF_HAS_DF       },
913        { "IS_MIME",            EF_IS_MIME      },
914        { "DONT_MIME",          EF_DONT_MIME    },
915        { NULL }
916};
917
918void
919printenvflags(e)
920        register ENVELOPE *e;
921{
922        register struct eflags *ef;
923        bool first = TRUE;
924
925        printf("%lx", e->e_flags);
926        for (ef = EnvelopeFlags; ef->ef_name != NULL; ef++)
927        {
928                if (!bitset(ef->ef_bit, e->e_flags))
929                        continue;
930                if (first)
931                        printf("<%s", ef->ef_name);
932                else
933                        printf(",%s", ef->ef_name);
934                first = FALSE;
935        }
936        if (!first)
937                printf(">\n");
938}
Note: See TracBrowser for help on using the repository browser.