1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
|
/*
* Copyright (c) 1998 Sendmail, Inc. All rights reserved.
* Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the sendmail distribution.
*
*
* @(#)sendmail.h 8.280 (Berkeley) 6/5/98
*/
/*
** SENDMAIL.H -- Global definitions for sendmail.
*/
# ifdef _DEFINE
# define EXTERN
# ifndef lint
static char SmailSccsId[] = "@(#)sendmail.h 8.280 6/5/98";
# endif
# else /* _DEFINE */
# define EXTERN extern
# endif /* _DEFINE */
# include <unistd.h>
# include <stddef.h>
# include <stdlib.h>
# include <stdio.h>
# include <ctype.h>
# include <setjmp.h>
# include <string.h>
# include <time.h>
# include <errno.h>
# ifdef EX_OK
# undef EX_OK /* for SVr4.2 SMP */
# endif
# include <sysexits.h>
# include "conf.h"
# include "useful.h"
# ifdef LOG
# include <syslog.h>
# endif /* LOG */
# if NETINET || NETUNIX || NETISO || NETNS || NETX25
# include <sys/socket.h>
# endif
# if NETUNIX
# include <sys/un.h>
# endif
# if NETINET
# include <netinet/in.h>
# endif
# if NETISO
# include <netiso/iso.h>
# endif
# if NETNS
# include <netns/ns.h>
# endif
# if NETX25
# include <netccitt/x25.h>
# endif
#if NAMED_BIND
# include <arpa/nameser.h>
# ifdef NOERROR
# undef NOERROR /* avoid <sys/streams.h> conflict */
# endif
#endif
#ifdef HESIOD
# include <hesiod.h>
# if !defined(HES_ER_OK) || defined(HESIOD_INTERFACES)
# define HESIOD_INIT /* support for the new interface */
EXTERN void *HesiodContext;
# endif
#endif
/*
** Following are "sort of" configuration constants, but they should
** be pretty solid on most architectures today. They have to be
** defined after <arpa/nameser.h> because some versions of that
** file also define them. In all cases, we can't use sizeof because
** some systems (e.g., Crays) always treat everything as being at
** least 64 bits.
*/
#ifndef INADDRSZ
# define INADDRSZ 4 /* size of an IPv4 address in bytes */
#endif
#ifndef INT16SZ
# define INT16SZ 2 /* size of a 16 bit integer in bytes */
#endif
#ifndef INT32SZ
# define INT32SZ 4 /* size of a 32 bit integer in bytes */
#endif
/* forward references for prototypes */
typedef struct envelope ENVELOPE;
typedef struct mailer MAILER;
/*
** Data structure for bit maps.
**
** Each bit in this map can be referenced by an ascii character.
** This is 256 possible bits, or 32 8-bit bytes.
*/
#define BITMAPBYTES 32 /* number of bytes in a bit map */
#define BYTEBITS 8 /* number of bits in a byte */
/* internal macros */
#define _BITWORD(bit) ((bit) / (BYTEBITS * sizeof (int)))
#define _BITBIT(bit) (1 << ((bit) % (BYTEBITS * sizeof (int))))
typedef int BITMAP[BITMAPBYTES / sizeof (int)];
/* test bit number N */
#define bitnset(bit, map) ((map)[_BITWORD(bit)] & _BITBIT(bit))
/* set bit number N */
#define setbitn(bit, map) (map)[_BITWORD(bit)] |= _BITBIT(bit)
/* clear bit number N */
#define clrbitn(bit, map) (map)[_BITWORD(bit)] &= ~_BITBIT(bit)
/* clear an entire bit map */
#define clrbitmap(map) bzero((char *) map, BITMAPBYTES)
/*
** Utility macros
*/
/* return number of bytes left in a buffer */
#define SPACELEFT(buf, ptr) (sizeof buf - ((ptr) - buf))
/*
** Address structure.
** Addresses are stored internally in this structure.
*/
struct address
{
char *q_paddr; /* the printname for the address */
char *q_user; /* user name */
char *q_ruser; /* real user name, or NULL if q_user */
char *q_host; /* host name */
struct mailer *q_mailer; /* mailer to use */
u_long q_flags; /* status flags, see below */
uid_t q_uid; /* user-id of receiver (if known) */
gid_t q_gid; /* group-id of receiver (if known) */
char *q_home; /* home dir (local mailer only) */
char *q_fullname; /* full name if known */
struct address *q_next; /* chain */
struct address *q_alias; /* address this results from */
char *q_owner; /* owner of q_alias */
struct address *q_tchain; /* temporary use chain */
char *q_orcpt; /* ORCPT parameter from RCPT TO: line */
char *q_status; /* status code for DSNs */
char *q_rstatus; /* remote status message for DSNs */
time_t q_statdate; /* date of status messages */
char *q_statmta; /* MTA generating q_rstatus */
short q_specificity; /* how "specific" this address is */
};
typedef struct address ADDRESS;
# define QDONTSEND 0x00000001 /* don't send to this address */
# define QBADADDR 0x00000002 /* this address is verified bad */
# define QGOODUID 0x00000004 /* the q_uid q_gid fields are good */
# define QPRIMARY 0x00000008 /* set from RCPT or argv */
# define QQUEUEUP 0x00000010 /* queue for later transmission */
# define QSENT 0x00000020 /* has been successfully delivered */
# define QNOTREMOTE 0x00000040 /* address not for remote forwarding */
# define QSELFREF 0x00000080 /* this address references itself */
# define QVERIFIED 0x00000100 /* verified, but not expanded */
# define QBOGUSSHELL 0x00000400 /* user has no valid shell listed */
# define QUNSAFEADDR 0x00000800 /* address aquired via unsafe path */
# define QPINGONSUCCESS 0x00001000 /* give return on successful delivery */
# define QPINGONFAILURE 0x00002000 /* give return on failure */
# define QPINGONDELAY 0x00004000 /* give return on message delay */
# define QHASNOTIFY 0x00008000 /* propogate notify parameter */
# define QRELAYED 0x00010000 /* DSN: relayed to non-DSN aware sys */
# define QEXPANDED 0x00020000 /* DSN: undergone list expansion */
# define QDELIVERED 0x00040000 /* DSN: successful final delivery */
# define QDELAYED 0x00080000 /* DSN: message delayed */
# define QTHISPASS 0x40000000 /* temp: address set this pass */
# define QRCPTOK 0x80000000 /* recipient() processed address */
# define Q_PINGFLAGS (QPINGONSUCCESS|QPINGONFAILURE|QPINGONDELAY)
# define NULLADDR ((ADDRESS *) NULL)
/* functions */
extern ADDRESS *parseaddr __P((char *, ADDRESS *, int, int, char **, ENVELOPE *));
extern ADDRESS *buildaddr __P((char **, ADDRESS *, int, ENVELOPE *));
extern ADDRESS *recipient __P((ADDRESS *, ADDRESS **, int, ENVELOPE *));
extern char **prescan __P((char *, int, char[], int, char **, u_char *));
extern int rewrite __P((char **, int, int, ENVELOPE *));
extern char *remotename __P((char *, MAILER *, int, int *, ENVELOPE *));
extern ADDRESS *getctladdr __P((ADDRESS *));
extern bool sameaddr __P((ADDRESS *, ADDRESS *));
extern bool emptyaddr __P((ADDRESS *));
extern void printaddr __P((ADDRESS *, bool));
extern void cataddr __P((char **, char **, char *, int, int));
extern int sendtolist __P((char *, ADDRESS *, ADDRESS **, int, ENVELOPE *));
/*
** Mailer definition structure.
** Every mailer known to the system is declared in this
** structure. It defines the pathname of the mailer, some
** flags associated with it, and the argument vector to
** pass to it. The flags are defined in conf.c
**
** The argument vector is expanded before actual use. All
** words except the first are passed through the macro
** processor.
*/
struct mailer
{
char *m_name; /* symbolic name of this mailer */
char *m_mailer; /* pathname of the mailer to use */
char *m_mtatype; /* type of this MTA */
char *m_addrtype; /* type for addresses */
char *m_diagtype; /* type for diagnostics */
BITMAP m_flags; /* status flags, see below */
short m_mno; /* mailer number internally */
short m_nice; /* niceness to run at (mostly for prog) */
char **m_argv; /* template argument vector */
short m_sh_rwset; /* rewrite set: sender header addresses */
short m_se_rwset; /* rewrite set: sender envelope addresses */
short m_rh_rwset; /* rewrite set: recipient header addresses */
short m_re_rwset; /* rewrite set: recipient envelope addresses */
char *m_eol; /* end of line string */
long m_maxsize; /* size limit on message to this mailer */
int m_linelimit; /* max # characters per line */
char *m_execdir; /* directory to chdir to before execv */
uid_t m_uid; /* UID to run as */
gid_t m_gid; /* GID to run as */
char *m_defcharset; /* default character set */
};
/* bits for m_flags */
# define M_ESMTP 'a' /* run Extended SMTP protocol */
# define M_ALIASABLE 'A' /* user can be LHS of an alias */
# define M_BLANKEND 'b' /* ensure blank line at end of message */
# define M_NOCOMMENT 'c' /* don't include comment part of address */
# define M_CANONICAL 'C' /* make addresses canonical "u@dom" */
# define M_NOBRACKET 'd' /* never angle bracket envelope route-addrs */
/* 'D' CF: include Date: */
# define M_EXPENSIVE 'e' /* it costs to use this mailer.... */
# define M_ESCFROM 'E' /* escape From lines to >From */
# define M_FOPT 'f' /* mailer takes picky -f flag */
/* 'F' CF: include From: or Resent-From: */
# define M_NO_NULL_FROM 'g' /* sender of errors should be $g */
# define M_HST_UPPER 'h' /* preserve host case distinction */
# define M_PREHEAD 'H' /* MAIL11V3: preview headers */
# define M_UDBENVELOPE 'i' /* do udbsender rewriting on envelope */
# define M_INTERNAL 'I' /* SMTP to another sendmail site */
# define M_UDBRECIPIENT 'j' /* do udbsender rewriting on recipient lines */
# define M_NOLOOPCHECK 'k' /* don't check for loops in HELO command */
# define M_CHUNKING 'K' /* CHUNKING: reserved for future use */
# define M_LOCALMAILER 'l' /* delivery is to this host */
# define M_LIMITS 'L' /* must enforce SMTP line limits */
# define M_MUSER 'm' /* can handle multiple users at once */
/* 'M' CF: include Message-Id: */
# define M_NHDR 'n' /* don't insert From line */
# define M_MANYSTATUS 'N' /* MAIL11V3: DATA returns multi-status */
# define M_RUNASRCPT 'o' /* always run mailer as recipient */
# define M_FROMPATH 'p' /* use reverse-path in MAIL FROM: */
/* 'P' CF: include Return-Path: */
# define M_VRFY250 'q' /* VRFY command returns 250 instead of 252 */
# define M_ROPT 'r' /* mailer takes picky -r flag */
# define M_SECURE_PORT 'R' /* try to send on a reserved TCP port */
# define M_STRIPQ 's' /* strip quote chars from user/host */
# define M_SPECIFIC_UID 'S' /* run as specific uid/gid */
# define M_USR_UPPER 'u' /* preserve user case distinction */
# define M_UGLYUUCP 'U' /* this wants an ugly UUCP from line */
# define M_CONTENT_LEN 'v' /* add Content-Length: header (SVr4) */
/* 'V' UIUC: !-relativize all addresses */
# define M_HASPWENT 'w' /* check for /etc/passwd entry */
/* 'x' CF: include Full-Name: */
# define M_XDOT 'X' /* use hidden-dot algorithm */
# define M_LMTP 'z' /* run Local Mail Transport Protocol */
# define M_NOMX '0' /* turn off MX lookups */
# define M_NONULLS '1' /* don't send null bytes */
# define M_EBCDIC '3' /* extend Q-P encoding for EBCDIC */
# define M_TRYRULESET5 '5' /* use ruleset 5 after local aliasing */
# define M_7BITHDRS '6' /* strip headers to 7 bits even in 8 bit path */
# define M_7BITS '7' /* use 7-bit path */
# define M_8BITS '8' /* force "just send 8" behaviour */
# define M_MAKE8BIT '9' /* convert 7 -> 8 bit if appropriate */
# define M_CHECKINCLUDE ':' /* check for :include: files */
# define M_CHECKPROG '|' /* check for |program addresses */
# define M_CHECKFILE '/' /* check for /file addresses */
# define M_CHECKUDB '@' /* user can be user database key */
# define M_CHECKHDIR '~' /* SGI: check for valid home directory */
EXTERN MAILER *Mailer[MAXMAILERS+1];
EXTERN MAILER *LocalMailer; /* ptr to local mailer */
EXTERN MAILER *ProgMailer; /* ptr to program mailer */
EXTERN MAILER *FileMailer; /* ptr to *file* mailer */
EXTERN MAILER *InclMailer; /* ptr to *include* mailer */
/*
** Information about currently open connections to mailers, or to
** hosts that we have looked up recently.
*/
# define MCI struct mailer_con_info
MCI
{
short mci_flags; /* flag bits, see below */
short mci_errno; /* error number on last connection */
short mci_herrno; /* h_errno from last DNS lookup */
short mci_exitstat; /* exit status from last connection */
short mci_state; /* SMTP state */
off_t mci_contentlen; /* body length for Content-Length: */
long mci_maxsize; /* max size this server will accept */
FILE *mci_in; /* input side of connection */
FILE *mci_out; /* output side of connection */
pid_t mci_pid; /* process id of subordinate proc */
char *mci_phase; /* SMTP phase string */
struct mailer *mci_mailer; /* ptr to the mailer for this conn */
char *mci_host; /* host name */
char *mci_status; /* DSN status to be copied to addrs */
char *mci_rstatus; /* SMTP status to be copied to addrs */
time_t mci_lastuse; /* last usage time */
FILE *mci_statfile; /* long term status file */
};
/* flag bits */
#define MCIF_VALID 0x0001 /* this entry is valid */
#define MCIF_TEMP 0x0002 /* don't cache this connection */
#define MCIF_CACHED 0x0004 /* currently in open cache */
#define MCIF_ESMTP 0x0008 /* this host speaks ESMTP */
#define MCIF_EXPN 0x0010 /* EXPN command supported */
#define MCIF_SIZE 0x0020 /* SIZE option supported */
#define MCIF_8BITMIME 0x0040 /* BODY=8BITMIME supported */
#define MCIF_7BIT 0x0080 /* strip this message to 7 bits */
#define MCIF_MULTSTAT 0x0100 /* MAIL11V3: handles MULT status */
#define MCIF_INHEADER 0x0200 /* currently outputing header */
#define MCIF_CVT8TO7 0x0400 /* convert from 8 to 7 bits */
#define MCIF_DSN 0x0800 /* DSN extension supported */
#define MCIF_8BITOK 0x1000 /* OK to send 8 bit characters */
#define MCIF_CVT7TO8 0x2000 /* convert from 7 to 8 bits */
#define MCIF_INMIME 0x4000 /* currently reading MIME header */
/* states */
#define MCIS_CLOSED 0 /* no traffic on this connection */
#define MCIS_OPENING 1 /* sending initial protocol */
#define MCIS_OPEN 2 /* open, initial protocol sent */
#define MCIS_ACTIVE 3 /* message being sent */
#define MCIS_QUITING 4 /* running quit protocol */
#define MCIS_SSD 5 /* service shutting down */
#define MCIS_ERROR 6 /* I/O error on connection */
/* functions */
extern MCI *mci_get __P((char *, MAILER *));
extern void mci_cache __P((MCI *));
extern void mci_flush __P((bool, MCI *));
extern void mci_dump __P((MCI *, bool));
extern void mci_dump_all __P((bool));
extern MCI **mci_scan __P((MCI *));
extern int mci_traverse_persistent __P((int (*)(), char *));
extern int mci_print_persistent __P((char *, char *));
extern int mci_purge_persistent __P((char *, char *));
extern int mci_lock_host __P((MCI *));
extern void mci_unlock_host __P((MCI *));
extern int mci_lock_host_statfile __P((MCI *));
extern void mci_store_persistent __P((MCI *));
extern int mci_read_persistent __P((FILE *, MCI *));
/*
** Header structure.
** This structure is used internally to store header items.
*/
struct header
{
char *h_field; /* the name of the field */
char *h_value; /* the value of that field */
struct header *h_link; /* the next header */
u_short h_flags; /* status bits, see below */
BITMAP h_mflags; /* m_flags bits needed */
};
typedef struct header HDR;
/*
** Header information structure.
** Defined in conf.c, this struct declares the header fields
** that have some magic meaning.
*/
struct hdrinfo
{
char *hi_field; /* the name of the field */
u_short hi_flags; /* status bits, see below */
char *hi_ruleset; /* validity check ruleset */
};
extern struct hdrinfo HdrInfo[];
/* bits for h_flags and hi_flags */
# define H_EOH 0x0001 /* this field terminates header */
# define H_RCPT 0x0002 /* contains recipient addresses */
# define H_DEFAULT 0x0004 /* if another value is found, drop this */
# define H_RESENT 0x0008 /* this address is a "Resent-..." address */
# define H_CHECK 0x0010 /* check h_mflags against m_flags */
# define H_ACHECK 0x0020 /* ditto, but always (not just default) */
# define H_FORCE 0x0040 /* force this field, even if default */
# define H_TRACE 0x0080 /* this field contains trace information */
# define H_FROM 0x0100 /* this is a from-type field */
# define H_VALID 0x0200 /* this field has a validated value */
# define H_RECEIPTTO 0x0400 /* this field has return receipt info */
# define H_ERRORSTO 0x0800 /* this field has error address info */
# define H_CTE 0x1000 /* this field is a content-transfer-encoding */
# define H_CTYPE 0x2000 /* this is a content-type field */
# define H_BCC 0x4000 /* Bcc: header: strip value or delete */
# define H_ENCODABLE 0x8000 /* field can be RFC 1522 encoded */
/* functions */
extern void addheader __P((char *, char *, HDR **));
extern char *hvalue __P((char *, HDR *));
extern void commaize __P((HDR *, char *, bool, MCI *, ENVELOPE *));
extern void put_vanilla_header __P((HDR *, char *, MCI *));
extern void eatheader __P((ENVELOPE *, bool));
extern int chompheader __P((char *, bool, HDR **, ENVELOPE *));
/*
** Envelope structure.
** This structure defines the message itself. There is usually
** only one of these -- for the message that we originally read
** and which is our primary interest -- but other envelopes can
** be generated during processing. For example, error messages
** will have their own envelope.
*/
struct envelope
{
HDR *e_header; /* head of header list */
long e_msgpriority; /* adjusted priority of this message */
time_t e_ctime; /* time message appeared in the queue */
char *e_to; /* the target person */
ADDRESS e_from; /* the person it is from */
char *e_sender; /* e_from.q_paddr w comments stripped */
char **e_fromdomain; /* the domain part of the sender */
ADDRESS *e_sendqueue; /* list of message recipients */
ADDRESS *e_errorqueue; /* the queue for error responses */
long e_msgsize; /* size of the message in bytes */
long e_flags; /* flags, see below */
int e_nrcpts; /* number of recipients */
short e_class; /* msg class (priority, junk, etc.) */
short e_hopcount; /* number of times processed */
short e_nsent; /* number of sends since checkpoint */
short e_sendmode; /* message send mode */
short e_errormode; /* error return mode */
short e_timeoutclass; /* message timeout class */
void (*e_puthdr)__P((MCI *, HDR *, ENVELOPE *));
/* function to put header of message */
void (*e_putbody)__P((MCI *, ENVELOPE *, char *));
/* function to put body of message */
struct envelope *e_parent; /* the message this one encloses */
struct envelope *e_sibling; /* the next envelope of interest */
char *e_bodytype; /* type of message body */
FILE *e_dfp; /* temporary file */
char *e_id; /* code for this entry in queue */
FILE *e_xfp; /* transcript file */
FILE *e_lockfp; /* the lock file for this message */
char *e_message; /* error message */
char *e_statmsg; /* stat msg (changes per delivery) */
char *e_msgboundary; /* MIME-style message part boundary */
char *e_origrcpt; /* original recipient (one only) */
char *e_envid; /* envelope id from MAIL FROM: line */
char *e_status; /* DSN status for this message */
time_t e_dtime; /* time of last delivery attempt */
int e_ntries; /* number of delivery attempts */
dev_t e_dfdev; /* df file's device, for crash recov */
ino_t e_dfino; /* df file's ino, for crash recovery */
char *e_macro[256]; /* macro definitions */
};
/* values for e_flags */
#define EF_OLDSTYLE 0x0000001 /* use spaces (not commas) in hdrs */
#define EF_INQUEUE 0x0000002 /* this message is fully queued */
#define EF_NO_BODY_RETN 0x0000004 /* omit message body on error */
#define EF_CLRQUEUE 0x0000008 /* disk copy is no longer needed */
#define EF_SENDRECEIPT 0x0000010 /* send a return receipt */
#define EF_FATALERRS 0x0000020 /* fatal errors occured */
#define EF_DELETE_BCC 0x0000040 /* delete Bcc: headers entirely */
#define EF_RESPONSE 0x0000080 /* this is an error or return receipt */
#define EF_RESENT 0x0000100 /* this message is being forwarded */
#define EF_VRFYONLY 0x0000200 /* verify only (don't expand aliases) */
#define EF_WARNING 0x0000400 /* warning message has been sent */
#define EF_QUEUERUN 0x0000800 /* this envelope is from queue */
#define EF_GLOBALERRS 0x0001000 /* treat errors as global */
#define EF_PM_NOTIFY 0x0002000 /* send return mail to postmaster */
#define EF_METOO 0x0004000 /* send to me too */
#define EF_LOGSENDER 0x0008000 /* need to log the sender */
#define EF_NORECEIPT 0x0010000 /* suppress all return-receipts */
#define EF_HAS8BIT 0x0020000 /* at least one 8-bit char in body */
#define EF_NL_NOT_EOL 0x0040000 /* don't accept raw NL as EOLine */
#define EF_CRLF_NOT_EOL 0x0080000 /* don't accept CR-LF as EOLine */
#define EF_RET_PARAM 0x0100000 /* RCPT command had RET argument */
#define EF_HAS_DF 0x0200000 /* set when df file is instantiated */
#define EF_IS_MIME 0x0400000 /* really is a MIME message */
#define EF_DONT_MIME 0x0800000 /* never MIME this message */
#define EF_DISCARD 0x1000000 /* discard the message */
EXTERN ENVELOPE *CurEnv; /* envelope currently being processed */
/* functions */
extern ENVELOPE *newenvelope __P((ENVELOPE *, ENVELOPE *));
extern void dropenvelope __P((ENVELOPE *, bool));
extern void clearenvelope __P((ENVELOPE *, bool));
extern void putheader __P((MCI *, HDR *, ENVELOPE *));
extern void putbody __P((MCI *, ENVELOPE *, char *));
/*
** Message priority classes.
**
** The message class is read directly from the Priority: header
** field in the message.
**
** CurEnv->e_msgpriority is the number of bytes in the message plus
** the creation time (so that jobs ``tend'' to be ordered correctly),
** adjusted by the message class, the number of recipients, and the
** amount of time the message has been sitting around. This number
** is used to order the queue. Higher values mean LOWER priority.
**
** Each priority class point is worth WkClassFact priority points;
** each recipient is worth WkRecipFact priority points. Each time
** we reprocess a message the priority is adjusted by WkTimeFact.
** WkTimeFact should normally decrease the priority so that jobs
** that have historically failed will be run later; thanks go to
** Jay Lepreau at Utah for pointing out the error in my thinking.
**
** The "class" is this number, unadjusted by the age or size of
** this message. Classes with negative representations will have
** error messages thrown away if they are not local.
*/
struct priority
{
char *pri_name; /* external name of priority */
int pri_val; /* internal value for same */
};
EXTERN struct priority Priorities[MAXPRIORITIES];
EXTERN int NumPriorities; /* pointer into Priorities */
/*
** Rewrite rules.
*/
struct rewrite
{
char **r_lhs; /* pattern match */
char **r_rhs; /* substitution value */
struct rewrite *r_next;/* next in chain */
};
EXTERN struct rewrite *RewriteRules[MAXRWSETS];
/*
** Special characters in rewriting rules.
** These are used internally only.
** The COND* rules are actually used in macros rather than in
** rewriting rules, but are given here because they
** cannot conflict.
*/
/* left hand side items */
# define MATCHZANY ((u_char)0220) /* match zero or more tokens */
# define MATCHANY ((u_char)0221) /* match one or more tokens */
# define MATCHONE ((u_char)0222) /* match exactly one token */
# define MATCHCLASS ((u_char)0223) /* match one token in a class */
# define MATCHNCLASS ((u_char)0224) /* match anything not in class */
# define MATCHREPL ((u_char)0225) /* replacement on RHS for above */
/* right hand side items */
# define CANONNET ((u_char)0226) /* canonical net, next token */
# define CANONHOST ((u_char)0227) /* canonical host, next token */
# define CANONUSER ((u_char)0230) /* canonical user, next N tokens */
# define CALLSUBR ((u_char)0231) /* call another rewriting set */
/* conditionals in macros */
# define CONDIF ((u_char)0232) /* conditional if-then */
# define CONDELSE ((u_char)0233) /* conditional else */
# define CONDFI ((u_char)0234) /* conditional fi */
/* bracket characters for host name lookup */
# define HOSTBEGIN ((u_char)0235) /* hostname lookup begin */
# define HOSTEND ((u_char)0236) /* hostname lookup end */
/* bracket characters for generalized lookup */
# define LOOKUPBEGIN ((u_char)0205) /* generalized lookup begin */
# define LOOKUPEND ((u_char)0206) /* generalized lookup end */
/* macro substitution character */
# define MACROEXPAND ((u_char)0201) /* macro expansion */
# define MACRODEXPAND ((u_char)0202) /* deferred macro expansion */
/* to make the code clearer */
# define MATCHZERO CANONHOST
/* external <==> internal mapping table */
struct metamac
{
char metaname; /* external code (after $) */
u_char metaval; /* internal code (as above) */
};
/* values for macros with external names only */
# define MID_OPMODE 0202 /* operation mode */
/* functions */
extern void expand __P((char *, char *, size_t, ENVELOPE *));
extern void define __P((int, char *, ENVELOPE *));
extern char *macvalue __P((int, ENVELOPE *));
extern char *macname __P((int));
extern int macid __P((char *, char **));
/*
** Name canonification short circuit.
**
** If the name server for a host is down, the process of trying to
** canonify the name can hang. This is similar to (but alas, not
** identical to) looking up the name for delivery. This stab type
** caches the result of the name server lookup so we don't hang
** multiple times.
*/
#define NAMECANON struct _namecanon
NAMECANON
{
short nc_errno; /* cached errno */
short nc_herrno; /* cached h_errno */
short nc_stat; /* cached exit status code */
short nc_flags; /* flag bits */
char *nc_cname; /* the canonical name */
};
/* values for nc_flags */
#define NCF_VALID 0x0001 /* entry valid */
/*
** Mapping functions
**
** These allow arbitrary mappings in the config file. The idea
** (albeit not the implementation) comes from IDA sendmail.
*/
# define MAPCLASS struct _mapclass
# define MAP struct _map
# define MAXMAPACTIONS 3 /* size of map_actions array */
/*
** An actual map.
*/
MAP
{
MAPCLASS *map_class; /* the class of this map */
char *map_mname; /* name of this map */
long map_mflags; /* flags, see below */
char *map_file; /* the (nominal) filename */
ARBPTR_T map_db1; /* the open database ptr */
ARBPTR_T map_db2; /* an "extra" database pointer */
char *map_keycolnm; /* key column name */
char *map_valcolnm; /* value column name */
u_char map_keycolno; /* key column number */
u_char map_valcolno; /* value column number */
char map_coldelim; /* column delimiter */
char *map_app; /* to append to successful matches */
char *map_tapp; /* to append to "tempfail" matches */
char *map_domain; /* the (nominal) NIS domain */
char *map_rebuild; /* program to run to do auto-rebuild */
time_t map_mtime; /* last database modification time */
int map_lockfd; /* auxiliary lock file descriptor */
short map_specificity; /* specificity of aliases */
MAP *map_stack[MAXMAPSTACK]; /* list for stacked maps */
short map_return[MAXMAPACTIONS]; /* return bitmaps for stacked maps */
};
/* bit values for map_mflags */
# define MF_VALID 0x00000001 /* this entry is valid */
# define MF_INCLNULL 0x00000002 /* include null byte in key */
# define MF_OPTIONAL 0x00000004 /* don't complain if map not found */
# define MF_NOFOLDCASE 0x00000008 /* don't fold case in keys */
# define MF_MATCHONLY 0x00000010 /* don't use the map value */
# define MF_OPEN 0x00000020 /* this entry is open */
# define MF_WRITABLE 0x00000040 /* open for writing */
# define MF_ALIAS 0x00000080 /* this is an alias file */
# define MF_TRY0NULL 0x00000100 /* try with no null byte */
# define MF_TRY1NULL 0x00000200 /* try with the null byte */
# define MF_LOCKED 0x00000400 /* this map is currently locked */
# define MF_ALIASWAIT 0x00000800 /* alias map in aliaswait state */
# define MF_IMPL_HASH 0x00001000 /* implicit: underlying hash database */
# define MF_IMPL_NDBM 0x00002000 /* implicit: underlying NDBM database */
# define MF_UNSAFEDB 0x00004000 /* this map is world writable */
# define MF_APPEND 0x00008000 /* append new entry on rebuiled */
# define MF_KEEPQUOTES 0x00010000 /* don't dequote key before lookup */
# define MF_NODEFER 0x00020000 /* don't defer if map lookup fails */
# define MF_REGEX_NOT 0x00040000 /* regular expression negation */
/* indices for map_actions */
# define MA_NOTFOUND 0 /* member map returned "not found" */
# define MA_UNAVAIL 1 /* member map is not available */
# define MA_TRYAGAIN 2 /* member map returns temp failure */
/*
** The class of a map -- essentially the functions to call
*/
MAPCLASS
{
char *map_cname; /* name of this map class */
char *map_ext; /* extension for database file */
short map_cflags; /* flag bits, see below */
bool (*map_parse)__P((MAP *, char *));
/* argument parsing function */
char *(*map_lookup)__P((MAP *, char *, char **, int *));
/* lookup function */
void (*map_store)__P((MAP *, char *, char *));
/* store function */
bool (*map_open)__P((MAP *, int));
/* open function */
void (*map_close)__P((MAP *));
/* close function */
};
/* bit values for map_cflags */
#define MCF_ALIASOK 0x0001 /* can be used for aliases */
#define MCF_ALIASONLY 0x0002 /* usable only for aliases */
#define MCF_REBUILDABLE 0x0004 /* can rebuild alias files */
#define MCF_OPTFILE 0x0008 /* file name is optional */
/* functions */
extern char *map_rewrite __P((MAP *, const char *, size_t, char **));
extern MAP *makemapentry __P((char *));
extern void initmaps __P((bool, ENVELOPE *));
/*
** Symbol table definitions
*/
struct symtab
{
char *s_name; /* name to be entered */
short s_type; /* general type (see below) */
short s_len; /* length of this entry */
struct symtab *s_next; /* pointer to next in chain */
union
{
BITMAP sv_class; /* bit-map of word classes */
ADDRESS *sv_addr; /* pointer to address header */
MAILER *sv_mailer; /* pointer to mailer */
char *sv_alias; /* alias */
MAPCLASS sv_mapclass; /* mapping function class */
MAP sv_map; /* mapping function */
char *sv_hostsig; /* host signature */
MCI sv_mci; /* mailer connection info */
NAMECANON sv_namecanon; /* canonical name cache */
int sv_macro; /* macro name => id mapping */
int sv_ruleset; /* ruleset index */
struct hdrinfo sv_header; /* header metainfo */
char *sv_service[MAXMAPSTACK]; /* service switch */
} s_value;
};
typedef struct symtab STAB;
/* symbol types */
# define ST_UNDEF 0 /* undefined type */
# define ST_CLASS 1 /* class map */
# define ST_ADDRESS 2 /* an address in parsed format */
# define ST_MAILER 3 /* a mailer header */
# define ST_ALIAS 4 /* an alias */
# define ST_MAPCLASS 5 /* mapping function class */
# define ST_MAP 6 /* mapping function */
# define ST_HOSTSIG 7 /* host signature */
# define ST_NAMECANON 8 /* cached canonical name */
# define ST_MACRO 9 /* macro name to id mapping */
# define ST_RULESET 10 /* ruleset index */
# define ST_SERVICE 11 /* service switch entry */
# define ST_HEADER 12 /* special header flags */
# define ST_MCI 16 /* mailer connection info (offset) */
# define s_class s_value.sv_class
# define s_address s_value.sv_addr
# define s_mailer s_value.sv_mailer
# define s_alias s_value.sv_alias
# define s_mci s_value.sv_mci
# define s_mapclass s_value.sv_mapclass
# define s_hostsig s_value.sv_hostsig
# define s_map s_value.sv_map
# define s_namecanon s_value.sv_namecanon
# define s_macro s_value.sv_macro
# define s_ruleset s_value.sv_ruleset
# define s_service s_value.sv_service
# define s_header s_value.sv_header
extern STAB *stab __P((char *, int, int));
extern void stabapply __P((void (*)(STAB *, int), int));
/* opcodes to stab */
# define ST_FIND 0 /* find entry */
# define ST_ENTER 1 /* enter if not there */
/*
** STRUCT EVENT -- event queue.
**
** Maintained in sorted order.
**
** We store the pid of the process that set this event to insure
** that when we fork we will not take events intended for the parent.
*/
struct event
{
time_t ev_time; /* time of the function call */
void (*ev_func)__P((int));
/* function to call */
int ev_arg; /* argument to ev_func */
int ev_pid; /* pid that set this event */
struct event *ev_link; /* link to next item */
};
typedef struct event EVENT;
EXTERN EVENT *EventQueue; /* head of event queue */
/* functions */
extern EVENT *setevent __P((time_t, void(*)(), int));
extern void clrevent __P((EVENT *));
/*
** Operation, send, error, and MIME modes
**
** The operation mode describes the basic operation of sendmail.
** This can be set from the command line, and is "send mail" by
** default.
**
** The send mode tells how to send mail. It can be set in the
** configuration file. It's setting determines how quickly the
** mail will be delivered versus the load on your system. If the
** -v (verbose) flag is given, it will be forced to SM_DELIVER
** mode.
**
** The error mode tells how to return errors.
*/
EXTERN char OpMode; /* operation mode, see below */
#define MD_DELIVER 'm' /* be a mail sender */
#define MD_SMTP 's' /* run SMTP on standard input */
#define MD_ARPAFTP 'a' /* obsolete ARPANET mode (Grey Book) */
#define MD_DAEMON 'd' /* run as a daemon */
#define MD_FGDAEMON 'D' /* run daemon in foreground */
#define MD_VERIFY 'v' /* verify: don't collect or deliver */
#define MD_TEST 't' /* test mode: resolve addrs only */
#define MD_INITALIAS 'i' /* initialize alias database */
#define MD_PRINT 'p' /* print the queue */
#define MD_FREEZE 'z' /* freeze the configuration file */
#define MD_HOSTSTAT 'h' /* print persistent host stat info */
#define MD_PURGESTAT 'H' /* purge persistent host stat info */
/* values for e_sendmode -- send modes */
#define SM_DELIVER 'i' /* interactive delivery */
#define SM_FORK 'b' /* deliver in background */
#define SM_QUEUE 'q' /* queue, don't deliver */
#define SM_DEFER 'd' /* defer map lookups as well as queue */
#define SM_VERIFY 'v' /* verify only (used internally) */
/* used only as a parameter to sendall */
#define SM_DEFAULT '\0' /* unspecified, use SendMode */
/* values for e_errormode -- error handling modes */
#define EM_PRINT 'p' /* print errors */
#define EM_MAIL 'm' /* mail back errors */
#define EM_WRITE 'w' /* write back errors */
#define EM_BERKNET 'e' /* special berknet processing */
#define EM_QUIET 'q' /* don't print messages (stat only) */
/* MIME processing mode */
EXTERN int MimeMode;
/* bit values for MimeMode */
#define MM_CVTMIME 0x0001 /* convert 8 to 7 bit MIME */
#define MM_PASS8BIT 0x0002 /* just send 8 bit data blind */
#define MM_MIME8BIT 0x0004 /* convert 8-bit data to MIME */
/* queue sorting order algorithm */
EXTERN int QueueSortOrder;
#define QS_BYPRIORITY 0 /* sort by message priority */
#define QS_BYHOST 1 /* sort by first host name */
#define QS_BYTIME 2 /* sort by submission time */
/* how to handle messages without any recipient addresses */
EXTERN int NoRecipientAction;
#define NRA_NO_ACTION 0 /* just leave it as is */
#define NRA_ADD_TO 1 /* add To: header */
#define NRA_ADD_APPARENTLY_TO 2 /* add Apparently-To: header */
#define NRA_ADD_BCC 3 /* add empty Bcc: header */
#define NRA_ADD_TO_UNDISCLOSED 4 /* add To: undisclosed:; header */
/* flags to putxline */
#define PXLF_NOTHINGSPECIAL 0 /* no special mapping */
#define PXLF_MAPFROM 0x0001 /* map From_ to >From_ */
#define PXLF_STRIP8BIT 0x0002 /* strip 8th bit */
#define PXLF_HEADER 0x0004 /* map newlines in headers */
/*
** Additional definitions
*/
/*
** Privacy flags
** These are bit values for the PrivacyFlags word.
*/
#define PRIV_PUBLIC 0 /* what have I got to hide? */
#define PRIV_NEEDMAILHELO 0x0001 /* insist on HELO for MAIL, at least */
#define PRIV_NEEDEXPNHELO 0x0002 /* insist on HELO for EXPN */
#define PRIV_NEEDVRFYHELO 0x0004 /* insist on HELO for VRFY */
#define PRIV_NOEXPN 0x0008 /* disallow EXPN command entirely */
#define PRIV_NOVRFY 0x0010 /* disallow VRFY command entirely */
#define PRIV_AUTHWARNINGS 0x0020 /* flag possible authorization probs */
#define PRIV_NORECEIPTS 0x0040 /* disallow return receipts */
#define PRIV_NOETRN 0x0080 /* disallow ETRN command entirely */
#define PRIV_NOVERB 0x0100 /* disallow VERB command entirely */
#define PRIV_RESTRICTMAILQ 0x1000 /* restrict mailq command */
#define PRIV_RESTRICTQRUN 0x2000 /* restrict queue run */
#define PRIV_GOAWAY 0x0fff /* don't give no info, anyway, anyhow */
/* struct defining such things */
struct prival
{
char *pv_name; /* name of privacy flag */
int pv_flag; /* numeric level */
};
/*
** Flags passed to remotename, parseaddr, allocaddr, and buildaddr.
*/
#define RF_SENDERADDR 0x001 /* this is a sender address */
#define RF_HEADERADDR 0x002 /* this is a header address */
#define RF_CANONICAL 0x004 /* strip comment information */
#define RF_ADDDOMAIN 0x008 /* OK to do domain extension */
#define RF_COPYPARSE 0x010 /* copy parsed user & host */
#define RF_COPYPADDR 0x020 /* copy print address */
#define RF_COPYALL (RF_COPYPARSE|RF_COPYPADDR)
#define RF_COPYNONE 0
/*
** Flags passed to safefile/safedirpath.
*/
#define SFF_ANYFILE 0 /* no special restrictions */
#define SFF_MUSTOWN 0x0001 /* user must own this file */
#define SFF_NOSLINK 0x0002 /* file cannot be a symbolic link */
#define SFF_ROOTOK 0x0004 /* ok for root to own this file */
#define SFF_RUNASREALUID 0x0008 /* if no ctladdr, run as real uid */
#define SFF_NOPATHCHECK 0x0010 /* don't bother checking dir path */
#define SFF_SETUIDOK 0x0020 /* setuid files are ok */
#define SFF_CREAT 0x0040 /* ok to create file if necessary */
#define SFF_REGONLY 0x0080 /* regular files only */
#define SFF_SAFEDIRPATH 0x0100 /* no writable directories allowed */
#define SFF_NOHLINK 0x0200 /* file cannot have hard links */
#define SFF_NOWLINK 0x0400 /* links only in non-writable dirs */
#define SFF_NOGWFILES 0x0800 /* disallow world writable files */
#define SFF_NOWWFILES 0x1000 /* disallow group writable files */
/* flags that are actually specific to safeopen/safefopen/dfopen */
#define SFF_OPENASROOT 0x2000 /* open as root instead of real user */
#define SFF_NOLOCK 0x4000 /* don't lock the file */
/* pseudo-flags */
#define SFF_NOLINK (SFF_NOHLINK|SFF_NOSLINK)
/* functions */
extern int safefile __P((char *, UID_T, GID_T, char *, int, int, struct stat *));
extern int safedirpath __P((char *, UID_T, GID_T, char *, int));
extern int safeopen __P((char *, int, int, int));
extern FILE *safefopen __P((char *, int, int, int));
extern int dfopen __P((char *, int, int, int));
extern bool filechanged __P((char *, int, struct stat *));
/*
** Flags passed to mime8to7.
*/
#define M87F_OUTER 0 /* outer context */
#define M87F_NO8BIT 0x0001 /* can't have 8-bit in this section */
#define M87F_DIGEST 0x0002 /* processing multipart/digest */
/*
** Flags passed to returntosender.
*/
#define RTSF_NO_BODY 0 /* send headers only */
#define RTSF_SEND_BODY 0x0001 /* include body of message in return */
#define RTSF_PM_BOUNCE 0x0002 /* this is a postmaster bounce */
/*
** Regular UNIX sockaddrs are too small to handle ISO addresses, so
** we are forced to declare a supertype here.
*/
# if NETINET || NETUNIX || NETISO || NETNS || NETX25
union bigsockaddr
{
struct sockaddr sa; /* general version */
#if NETUNIX
struct sockaddr_un sunix; /* UNIX family */
#endif
#if NETINET
struct sockaddr_in sin; /* INET family */
#endif
#if NETISO
struct sockaddr_iso siso; /* ISO family */
#endif
#if NETNS
struct sockaddr_ns sns; /* XNS family */
#endif
#if NETX25
struct sockaddr_x25 sx25; /* X.25 family */
#endif
};
#define SOCKADDR union bigsockaddr
EXTERN SOCKADDR RealHostAddr; /* address of host we are talking to */
extern char *hostnamebyanyaddr __P((SOCKADDR *));
extern char *anynet_ntoa __P((SOCKADDR *));
# if DAEMON
extern char *validate_connection __P((SOCKADDR *, char *, ENVELOPE *));
# endif
#endif
/*
** Vendor codes
**
** Vendors can customize sendmail to add special behaviour,
** generally for back compatibility. Ideally, this should
** be set up in the .cf file using the "V" command. However,
** it's quite reasonable for some vendors to want the default
** be their old version; this can be set using
** -DVENDOR_DEFAULT=VENDOR_xxx
** in the Makefile.
**
** Vendors should apply to sendmail@CS.Berkeley.EDU for
** unique vendor codes.
*/
#define VENDOR_BERKELEY 1 /* Berkeley-native configuration file */
#define VENDOR_SUN 2 /* Sun-native configuration file */
#define VENDOR_HP 3 /* Hewlett-Packard specific config syntax */
#define VENDOR_IBM 4 /* IBM specific config syntax */
EXTERN int VendorCode; /* vendor-specific operation enhancements */
/* prototypes for vendor-specific hook routines */
extern void vendor_set_uid __P((UID_T));
extern void vendor_daemon_setup __P((ENVELOPE *));
/*
** DontBlameSendmail options
**
** Hopefully nobody uses these.
*/
#define DBS_SAFE 0
#define DBS_ASSUMESAFECHOWN 0x00000001
#define DBS_GROUPWRITABLEDIRPATHSAFE 0x00000002
#define DBS_GROUPWRITABLEFORWARDFILESAFE 0x00000004
#define DBS_GROUPWRITABLEINCLUDEFILESAFE 0x00000008
#define DBS_GROUPWRITABLEALIASFILE 0x00000010
#define DBS_WORLDWRITABLEALIASFILE 0x00000020
#define DBS_FORWARDFILEINUNSAFEDIRPATH 0x00000040
#define DBS_INCLUDEFILEINUNSAFEDIRPATH 0x00000060
#define DBS_MAPINUNSAFEDIRPATH 0x00000080
#define DBS_LINKEDALIASFILEINWRITABLEDIR 0x00000100
#define DBS_LINKEDCLASSFILEINWRITABLEDIR 0x00000200
#define DBS_LINKEDFORWARDFILEINWRITABLEDIR 0x00000400
#define DBS_LINKEDINCLUDEFILEINWRITABLEDIR 0x00000800
#define DBS_LINKEDMAPINWRITABLEDIR 0x00001000
#define DBS_LINKEDSERVICESWITCHFILEINWRITABLEDIR 0x00002000
#define DBS_FILEDELIVERYTOHARDLINK 0x00004000
#define DBS_FILEDELIVERYTOSYMLINK 0x00008000
#define DBS_WRITEMAPTOHARDLINK 0x00010000
#define DBS_WRITEMAPTOSYMLINK 0x00020000
#define DBS_WRITESTATSTOHARDLINK 0x00040000
#define DBS_WRITESTATSTOSYMLINK 0x00080000
#define DBS_FORWARDFILEINGROUPWRITABLEDIRPATH 0x00100000
#define DBS_INCLUDEFILEINGROUPWRITABLEDIRPATH 0x00200000
#define DBS_CLASSFILEINUNSAFEDIRPATH 0x00400000
#define DBS_ERRORHEADERINUNSAFEDIRPATH 0x00800000
#define DBS_HELPFILEINUNSAFEDIRPATH 0x01000000
#define DBS_FORWARDFILEINUNSAFEDIRPATHSAFE 0x02000000
#define DBS_INCLUDEFILEINUNSAFEDIRPATHSAFE 0x04000000
#define DBS_RUNPROGRAMINUNSAFEDIRPATH 0x08000000
#define DBS_RUNWRITABLEPROGRAM 0x10000000
/* struct defining such things */
struct dbsval
{
char *dbs_name; /* name of DontBlameSendmail flag */
long dbs_flag; /* numeric level */
};
EXTERN long DontBlameSendmail; /* DontBlameSendmail option bits */
/*
** Terminal escape codes.
**
** To make debugging output clearer.
*/
struct termescape
{
char *te_rv_on; /* turn reverse-video on */
char *te_rv_off; /* turn reverse-video off */
};
EXTERN struct termescape TermEscape;
/*
** Error return from inet_addr(3), in case not defined in /usr/include.
*/
#ifndef INADDR_NONE
# define INADDR_NONE 0xffffffff
#endif
/*
** Global variables.
*/
EXTERN bool FromFlag; /* if set, "From" person is explicit */
EXTERN bool MeToo; /* send to the sender also */
EXTERN bool IgnrDot; /* don't let dot end messages */
EXTERN bool SaveFrom; /* save leading "From" lines */
EXTERN bool GrabTo; /* if set, get recipients from msg */
EXTERN bool SuprErrs; /* set if we are suppressing errors */
EXTERN bool HoldErrs; /* only output errors to transcript */
EXTERN bool NoConnect; /* don't connect to non-local mailers */
EXTERN bool SuperSafe; /* be extra careful, even if expensive */
EXTERN bool ForkQueueRuns; /* fork for each job when running the queue */
EXTERN bool AutoRebuild; /* auto-rebuild the alias database as needed */
EXTERN bool CheckAliases; /* parse addresses during newaliases */
EXTERN bool NoAlias; /* suppress aliasing */
EXTERN bool UseNameServer; /* using DNS -- interpret h_errno & MX RRs */
EXTERN bool UseHesiod; /* using Hesiod -- interpret Hesiod errors */
EXTERN bool SevenBitInput; /* force 7-bit data on input */
EXTERN bool HasEightBits; /* has at least one eight bit input byte */
EXTERN bool ConfigFileRead; /* configuration file has been read */
EXTERN time_t SafeAlias; /* interval to wait until @:@ in alias file */
EXTERN FILE *InChannel; /* input connection */
EXTERN FILE *OutChannel; /* output connection */
EXTERN char *RealUserName; /* real user name of caller */
EXTERN uid_t RealUid; /* real uid of caller */
EXTERN gid_t RealGid; /* real gid of caller */
EXTERN uid_t DefUid; /* default uid to run as */
EXTERN gid_t DefGid; /* default gid to run as */
EXTERN char *DefUser; /* default user to run as (from DefUid) */
EXTERN uid_t TrustedFileUid; /* uid of trusted owner of files and dirs */
EXTERN MODE_T OldUmask; /* umask when sendmail starts up */
EXTERN int Verbose; /* set if blow-by-blow desired */
EXTERN int Errors; /* set if errors (local to single pass) */
EXTERN int ExitStat; /* exit status code */
EXTERN int LineNumber; /* line number in current input */
EXTERN int LogLevel; /* level of logging to perform */
EXTERN int FileMode; /* mode on files */
EXTERN int QueueLA; /* load average starting forced queueing */
EXTERN int RefuseLA; /* load average refusing connections are */
EXTERN int CurrentLA; /* current load average */
EXTERN long QueueFactor; /* slope of queue function */
EXTERN time_t QueueIntvl; /* intervals between running the queue */
EXTERN char *HelpFile; /* location of SMTP help file */
EXTERN char *ErrMsgFile; /* file to prepend to all error messages */
EXTERN char *StatFile; /* location of statistics summary */
EXTERN char *QueueDir; /* location of queue directory */
EXTERN char *FileName; /* name to print on error messages */
EXTERN char *SmtpPhase; /* current phase in SMTP processing */
EXTERN char *MyHostName; /* name of this host for SMTP messages */
EXTERN char *RealHostName; /* name of host we are talking to */
EXTERN char *CurHostName; /* current host we are dealing with */
EXTERN jmp_buf TopFrame; /* branch-to-top-of-loop-on-error frame */
EXTERN bool QuickAbort; /* .... but only if we want a quick abort */
EXTERN bool OnlyOneError; /* .... or only want to give one SMTP reply */
EXTERN bool LogUsrErrs; /* syslog user errors (e.g., SMTP RCPT cmd) */
EXTERN bool SendMIMEErrors; /* send error messages in MIME format */
EXTERN bool MatchGecos; /* look for user names in gecos field */
EXTERN bool UseErrorsTo; /* use Errors-To: header (back compat) */
EXTERN bool TryNullMXList; /* if we are the best MX, try host directly */
EXTERN bool InChild; /* true if running in an SMTP subprocess */
EXTERN bool DisConnected; /* running with OutChannel redirected to xf */
EXTERN bool ColonOkInAddr; /* single colon legal in address */
EXTERN bool HasWildcardMX; /* don't use MX records when canonifying */
EXTERN char SpaceSub; /* substitution for <lwsp> */
EXTERN int PrivacyFlags; /* privacy flags */
EXTERN char *ConfFile; /* location of configuration file [conf.c] */
EXTERN char *PidFile; /* location of proc id file [conf.c] */
extern ADDRESS NullAddress; /* a null (template) address [main.c] */
EXTERN long WkClassFact; /* multiplier for message class -> priority */
EXTERN long WkRecipFact; /* multiplier for # of recipients -> priority */
EXTERN long WkTimeFact; /* priority offset each time this job is run */
EXTERN char *UdbSpec; /* user database source spec */
EXTERN int MaxHopCount; /* max # of hops until bounce */
EXTERN int ConfigLevel; /* config file level */
EXTERN char *TimeZoneSpec; /* override time zone specification */
EXTERN char *ForwardPath; /* path to search for .forward files */
EXTERN long MinBlocksFree; /* min # of blocks free on queue fs */
EXTERN char *FallBackMX; /* fall back MX host */
EXTERN long MaxMessageSize; /* advertised max size we will accept */
EXTERN time_t MinQueueAge; /* min delivery interval */
EXTERN time_t DialDelay; /* delay between dial-on-demand tries */
EXTERN char *SafeFileEnv; /* chroot location for file delivery */
EXTERN char *HostsFile; /* path to /etc/hosts file */
EXTERN char *HostStatDir; /* location of host status information */
EXTERN int MaxQueueRun; /* maximum number of jobs in one queue run */
EXTERN int MaxChildren; /* maximum number of daemonic children */
EXTERN int CurChildren; /* current number of daemonic children */
EXTERN char *SmtpGreeting; /* SMTP greeting message (old $e macro) */
EXTERN char *UnixFromLine; /* UNIX From_ line (old $l macro) */
EXTERN char *OperatorChars; /* operators (old $o macro) */
EXTERN bool DontInitGroups; /* avoid initgroups() because of NIS cost */
EXTERN int DefaultNotify; /* default DSN notification flags */
EXTERN bool AllowBogusHELO; /* allow syntax errors on HELO command */
EXTERN bool UserSubmission; /* initial (user) mail submission */
EXTERN char *RunAsUserName; /* user to become for bulk of run */
EXTERN uid_t RunAsUid; /* UID to become for bulk of run */
EXTERN gid_t RunAsGid; /* GID to become for bulk of run */
EXTERN int MaxRcptPerMsg; /* max recipients per SMTP message */
EXTERN bool DoQueueRun; /* non-interrupt time queue run needed */
EXTERN u_long ConnectOnlyTo; /* override connection address (for testing) */
#if _FFR_DSN_RRT_OPTION
EXTERN bool RrtImpliesDsn; /* turn Return-Receipt-To: into DSN */
#endif
EXTERN char *DeadLetterDrop; /* path to dead letter office */
EXTERN bool DontProbeInterfaces; /* don't probe interfaces for names */
EXTERN bool ChownAlwaysSafe; /* treat chown(2) as safe */
EXTERN bool IgnoreHostStatus; /* ignore long term host status files */
EXTERN bool SingleThreadDelivery; /* single thread hosts on delivery */
EXTERN bool SingleLineFromHeader; /* force From: header to be one line */
EXTERN bool DontLockReadFiles; /* don't read lock support files */
EXTERN int ConnRateThrottle; /* throttle for SMTP connection rate */
EXTERN int MaxAliasRecursion; /* maximum depth of alias recursion */
EXTERN int MaxMacroRecursion; /* maximum depth of macro recursion */
EXTERN int MaxRuleRecursion; /* maximum depth of ruleset recursion */
EXTERN char *MustQuoteChars; /* quote these characters in phrases */
EXTERN char *ServiceSwitchFile; /* backup service switch */
EXTERN char *DefaultCharSet; /* default character set for MIME */
EXTERN char *PostMasterCopy; /* address to get errs cc's */
EXTERN int CheckpointInterval; /* queue file checkpoint interval */
EXTERN bool DontPruneRoutes; /* don't prune source routes */
EXTERN bool DontExpandCnames; /* do not $[...$] expand CNAMEs */
EXTERN int MaxMciCache; /* maximum entries in MCI cache */
EXTERN time_t ServiceCacheTime; /* time service switch was cached */
EXTERN time_t ServiceCacheMaxAge; /* refresh interval for cache */
EXTERN time_t MciCacheTimeout; /* maximum idle time on connections */
EXTERN time_t MciInfoTimeout; /* how long 'til we retry down hosts */
EXTERN FILE *TrafficLogFile; /* file in which to log all traffic */
EXTERN char *DoubleBounceAddr; /* where to send double bounces */
EXTERN char **ExternalEnviron; /* input environment */
EXTERN char *UserEnviron[MAXUSERENVIRON + 1];
/* saved user environment */
extern int errno;
/*
** Queue Run Limitations
*/
struct queue_char
{
char *queue_match; /* string to match */
struct queue_char *queue_next;
};
typedef struct queue_char QUEUE_CHAR;
EXTERN QUEUE_CHAR *QueueLimitRecipient; /* limit queue runs to this recipient */
EXTERN QUEUE_CHAR *QueueLimitSender; /* limit queue runs to this sender */
EXTERN QUEUE_CHAR *QueueLimitId; /* limit queue runs to this id */
/*
** Timeouts
**
** Indicated values are the MINIMUM per RFC 1123 section 5.3.2.
*/
EXTERN struct
{
/* RFC 1123-specified timeouts [minimum value] */
time_t to_initial; /* initial greeting timeout [5m] */
time_t to_mail; /* MAIL command [5m] */
time_t to_rcpt; /* RCPT command [5m] */
time_t to_datainit; /* DATA initiation [2m] */
time_t to_datablock; /* DATA block [3m] */
time_t to_datafinal; /* DATA completion [10m] */
time_t to_nextcommand; /* next command [5m] */
/* following timeouts are not mentioned in RFC 1123 */
time_t to_iconnect; /* initial connection timeout (first try) */
time_t to_connect; /* initial connection timeout (later tries) */
time_t to_rset; /* RSET command */
time_t to_helo; /* HELO command */
time_t to_quit; /* QUIT command */
time_t to_miscshort; /* misc short commands (NOOP, VERB, etc) */
time_t to_ident; /* IDENT protocol requests */
time_t to_fileopen; /* opening :include: and .forward files */
/* following are per message */
time_t to_q_return[MAXTOCLASS]; /* queue return timeouts */
time_t to_q_warning[MAXTOCLASS]; /* queue warning timeouts */
} TimeOuts;
/* timeout classes for return and warning timeouts */
# define TOC_NORMAL 0 /* normal delivery */
# define TOC_URGENT 1 /* urgent delivery */
# define TOC_NONURGENT 2 /* non-urgent delivery */
/*
** Trace information
*/
/* trace vector and macros for debugging flags */
EXTERN u_char tTdvect[100];
# define tTd(flag, level) (tTdvect[flag] >= level)
# define tTdlevel(flag) (tTdvect[flag])
/*
** Miscellaneous information.
*/
/*
** The "no queue id" queue id for sm_syslog
*/
#define NOQID "*~*"
/*
** Some in-line functions
*/
/* set exit status */
#define setstat(s) { \
if (ExitStat == EX_OK || ExitStat == EX_TEMPFAIL) \
ExitStat = s; \
}
/* make a copy of a string */
#define newstr(s) strcpy(xalloc(strlen(s) + 1), s)
#define STRUCTCOPY(s, d) d = s
/*
** Declarations of useful functions
*/
extern char *xalloc __P((int));
extern char *sfgets __P((char *, int, FILE *, time_t, char *));
extern char *queuename __P((ENVELOPE *, int));
extern time_t curtime __P((void));
extern bool transienterror __P((int));
extern char *fgetfolded __P((char *, int, FILE *));
extern char *username __P((void));
extern char *pintvl __P((time_t, bool));
extern bool shouldqueue __P((long, time_t));
extern bool lockfile __P((int, char *, char *, int));
extern char *hostsignature __P((MAILER *, char *, ENVELOPE *));
extern void openxscript __P((ENVELOPE *));
extern void closexscript __P((ENVELOPE *));
extern char *shortenstring __P((const char *, int));
extern bool usershellok __P((char *, char *));
extern char *defcharset __P((ENVELOPE *));
extern bool wordinclass __P((char *, int));
extern char *denlstring __P((char *, bool, bool));
extern void makelower __P((char *));
extern bool rebuildaliases __P((MAP *, bool));
extern void readaliases __P((MAP *, FILE *, bool, bool));
extern void finis __P((void));
extern void setsender __P((char *, ENVELOPE *, char **, int, bool));
extern void xputs __P((const char *));
extern void logsender __P((ENVELOPE *, char *));
extern void smtprset __P((MAILER *, MCI *, ENVELOPE *));
extern void smtpquit __P((MAILER *, MCI *, ENVELOPE *));
extern void setuserenv __P((const char *, const char *));
extern char *getextenv __P((const char *));
extern void disconnect __P((int, ENVELOPE *));
extern void putxline __P((char *, size_t, MCI *, int));
extern void dumpfd __P((int, bool, bool));
extern void makemailer __P((char *));
extern void putfromline __P((MCI *, ENVELOPE *));
extern void setoption __P((int, char *, bool, bool, ENVELOPE *));
extern void setclass __P((int, char *));
extern void inittimeouts __P((char *));
extern void logdelivery __P((MAILER *, MCI *, const char *, ADDRESS *, time_t, ENVELOPE *));
extern void giveresponse __P((int, MAILER *, MCI *, ADDRESS *, time_t, ENVELOPE *));
extern void buildfname __P((char *, char *, char *, int));
extern void mci_setstat __P((MCI *, int, char *, char *));
extern char *smtptodsn __P((int));
extern int rscheck __P((char *, char *, char *, ENVELOPE *e));
extern void mime7to8 __P((MCI *, HDR *, ENVELOPE *));
extern int mime8to7 __P((MCI *, HDR *, ENVELOPE *, char **, int));
extern void xfclose __P((FILE *, char *, char *));
extern int switch_map_find __P((char *, char *[], short []));
extern void shorten_hostname __P((char []));
extern int waitfor __P((pid_t));
extern void proc_list_add __P((pid_t));
extern void proc_list_drop __P((pid_t));
extern void proc_list_clear __P((void));
extern void buffer_errors __P((void));
extern void flush_errors __P((bool));
extern void putline __P((char *, MCI *));
extern bool xtextok __P((char *));
extern char *xtextify __P((char *, char *));
extern char *xuntextify __P((char *));
extern void cleanstrcpy __P((char *, char *, int));
extern int getmxrr __P((char *, char **, bool, int *));
extern int strtorwset __P((char *, char **, int));
extern void printav __P((char **));
extern void printopenfds __P((bool));
extern int endmailer __P((MCI *, ENVELOPE *, char **));
extern void fixcrlf __P((char *, bool));
extern int dofork __P((void));
extern void initsys __P((ENVELOPE *));
extern void collect __P((FILE *, bool, HDR **, ENVELOPE *));
extern void stripquotes __P((char *));
extern int include __P((char *, bool, ADDRESS *, ADDRESS **, int, ENVELOPE *));
extern void unlockqueue __P((ENVELOPE *));
extern void xunlink __P((char *));
extern bool runqueue __P((bool, bool));
extern int getla __P((void));
extern void sendall __P((ENVELOPE *, int));
extern void queueup __P((ENVELOPE *, bool));
extern void checkfds __P((char *));
extern int returntosender __P((char *, ADDRESS *, int, ENVELOPE *));
extern void markstats __P((ENVELOPE *, ADDRESS *, bool));
extern void poststats __P((char *));
extern char *arpadate __P((char *));
extern int mailfile __P((char *volatile, MAILER *volatile, ADDRESS *, volatile int, ENVELOPE *));
extern void loseqfile __P((ENVELOPE *, char *));
extern int prog_open __P((char **, int *, ENVELOPE *));
extern bool getcanonname __P((char *, int, bool));
extern bool path_is_dir __P((char *, bool));
extern pid_t dowork __P((char *, bool, bool, ENVELOPE *));
extern int drop_privileges __P((bool));
extern void fill_fd __P((int, char *));
extern const char *errstring __P((int));
extern sigfunc_t setsignal __P((int, sigfunc_t));
extern int blocksignal __P((int));
extern int releasesignal __P((int));
extern struct hostent *sm_gethostbyname __P((char *));
extern struct hostent *sm_gethostbyaddr __P((char *, int, int));
extern struct passwd *sm_getpwnam __P((char *));
extern struct passwd *sm_getpwuid __P((UID_T));
extern struct passwd *finduser __P((char *, bool *));
#ifdef XDEBUG
extern void checkfdopen __P((int, char *));
extern void checkfd012 __P((char *));
#endif
/* ellipsis is a different case though */
extern void auth_warning __P((ENVELOPE *, const char *, ...));
extern void syserr __P((const char *, ...));
extern void usrerr __P((const char *, ...));
extern void message __P((const char *, ...));
extern void nmessage __P((const char *, ...));
extern void setproctitle __P((const char *, ...));
extern void sm_syslog __P((int, const char *, const char *, ...));
#if !HASSNPRINTF
extern int snprintf __P((char *, size_t, const char *, ...));
extern int vsnprintf __P((char *, size_t, const char *, va_list));
#endif
extern char *quad_to_string __P((QUAD_T));
|