442 #include <sys/stat.h>
454 #include <sysexits.h>
508 #define SM_MODE_ENQUEUE 1
509 #define SM_MODE_NEWALIAS 2
510 #define SM_MODE_MAILQ 3
511 #define SM_MODE_DAEMON 4
512 #define SM_MODE_USER 5
513 #define SM_MODE_FLUSHQ 6
514 #define SM_MODE_IGNORE 7
519 #define SM_FLAG_AEOF (1<<0)
520 #define SM_FLAG_XRCPT (1<<1)
522 #define SM_FLAG_DEFAULT (SM_FLAG_AEOF)
527 static char *verp_delims;
557 #define STR vstring_str
561 static void output_text(
void *context,
int rec_type,
const char *buf, ssize_t len,
566 if (
rec_put(state->
dst, rec_type, buf, len) < 0)
568 "%s(%ld): error writing queue file: %m",
574 static void output_header(
void *context,
int header_class,
605 for (tpp = addr_list; *tpp; tpp++) {
609 myfree((
void *) addr_list);
617 for (line = start =
STR(buf); line; line = next_line) {
619 len = next_line ? next_line - line - 1 : strlen(line);
638 static void enqueue(
const int flags,
const char *encoding,
639 const char *dsn_envid,
int dsn_ret,
int dsn_notify,
640 const char *rewrite_context,
const char *sender,
641 const char *full_name,
char **recipients)
654 STRIP_CR_DUNNO, STRIP_CR_DO, STRIP_CR_DONT, STRIP_CR_ERROR
658 uid_t uid = getuid();
682 "User %s(%ld) is not allowed to submit mail", errstr, (
long) uid);
706 for (naddr = 0, tp = tree; tp != 0; tp = tp->
next)
712 msg_warn(
"-f option specified malformed sender: %s", sender);
716 (
unsigned long) uid);
731 saved_sender, (
long) uid,
STR(postdrop_command));
759 if (full_name || (full_name =
fullname()) != 0)
762 if (verp_delims && *saved_sender == 0)
764 "%s(%ld): -V option requires non-null sender address",
765 saved_sender, (
long) uid);
774 for (cpp = recipients; *cpp != 0; cpp++) {
776 for (addr_count = 0, tp = tree; tp != 0; tp = tp->
next) {
784 "%s(%ld): error writing queue file: %m",
785 saved_sender, (
long) uid);
791 if (addr_count == 0) {
794 "%s(%ld): error writing queue file: %m",
795 saved_sender, (
long) uid);
814 saved_sender, (
long) uid);
820 for (cpp = recipients; *cpp != 0; cpp++) {
822 *cpp, cpp[1] ?
"," :
"");
830 if (flags & SM_FLAG_XRCPT) {
854 if (strip_cr == STRIP_CR_ERROR)
861 strip_cr = STRIP_CR_DO;
863 strip_cr = STRIP_CR_DONT;
868 if (strncmp(start + strspn(start,
">"),
"From ", 5) == 0)
884 "%s(%ld): unable to extract recipients: %s",
885 saved_sender, (
long) uid,
890 "%s(%ld): error writing queue file: %m",
891 saved_sender, (
long) uid);
905 "%s(%ld): unable to extract recipients: %s",
906 saved_sender, (
long) uid,
915 if (flags & SM_FLAG_XRCPT) {
923 "%s(%ld): error writing queue file: %m",
924 saved_sender, (
long) uid);
933 "%s(%ld): No recipient addresses found in message header" :
934 "%s(%ld): Recipient addresses must be specified on"
935 " the command line or via the -t option",
936 saved_sender, (
long) uid);
951 saved_sender, (
long) uid);
962 vstream_printf(
"Mail Delivery Status Report will be mailed to <%s>.\n",
977 static void tempfail(
void)
986 int main(
int argc,
char **argv)
988 static char *full_name = 0;
1000 char *site_to_flush = 0;
1001 char *id_to_flush = 0;
1009 const char *dsn_envid = 0;
1028 for (fd = 0; fd < 3; fd++)
1029 if (
fstat(fd, &st) == -1
1030 && (close(fd), open(
"/dev/null", O_RDWR, 0)) != fd)
1038 for ( ; fd < 100; fd++)
1056 if ((slash = strrchr(argv[0],
'/')) != 0 && slash[1])
1057 argv[0] = slash + 1;
1073 if (geteuid() == 0 && getuid() != 0) {
1074 msg_warn(
"the Postfix sendmail command has set-uid root file permissions");
1075 msg_warn(
"or the command is run from a set-uid root process");
1076 msg_warn(
"the Postfix sendmail command must be installed without set-uid root file permissions");
1085 #define GETOPT_LIST "A:B:C:F:GIL:N:O:R:UV:X:b:ce:f:h:imno:p:r:q:tvx"
1087 saved_optind = optind;
1088 while (argv[
OPTIND] != 0) {
1089 if (strcmp(argv[
OPTIND],
"-q") == 0) {
1108 optind = saved_optind;
1123 signal(SIGPIPE, SIG_IGN);
1138 if (strcmp(argv[0],
"mailq") == 0) {
1140 }
else if (strcmp(argv[0],
"newaliases") == 0) {
1142 }
else if (strcmp(argv[0],
"smtpd") == 0) {
1153 #define OPTIND (optind > 0 ? optind : 1)
1155 while (argv[
OPTIND] != 0) {
1156 if (strcmp(argv[
OPTIND],
"-q") == 0) {
1158 msg_warn(
"ignoring -q option in daemon mode");
1164 if (strcmp(argv[OPTIND],
"-V") == 0
1165 && argv[OPTIND + 1] != 0 && strlen(argv[OPTIND + 1]) == 2) {
1166 msg_warn(
"option -V is deprecated with Postfix 2.3; "
1167 "specify -XV instead");
1170 if (strncmp(argv[OPTIND],
"-V", 2) == 0 && strlen(argv[OPTIND]) == 4) {
1171 msg_warn(
"option %s is deprecated with Postfix 2.3; "
1172 "specify -X%s instead",
1173 argv[OPTIND], argv[OPTIND] + 1);
1176 if (strcmp(argv[OPTIND],
"-XV") == 0) {
1191 if (strcmp(optarg,
"8BITMIME") == 0)
1193 else if (strcmp(optarg,
"7BIT") == 0)
1209 msg_warn(
"bad -N option value -- ignored");
1213 msg_warn(
"bad -R option value -- ignored");
1216 if (strlen(optarg) > 100)
1217 msg_warn(
"too long -V option value -- ignored");
1219 msg_warn(
"bad syntax in -V option value -- ignored");
1231 verp_delims = optarg + 1;
1242 msg_warn(
"ignoring -q option in daemon mode");
1270 flags &= ~SM_FLAG_AEOF;
1276 msg_info(
"-%c%c option ignored", c, *optarg);
1289 flags &= ~SM_FLAG_AEOF;
1301 }
else if (optarg[0] ==
'R') {
1302 site_to_flush = optarg + 1;
1303 if (*site_to_flush == 0)
1305 }
else if (optarg[0] ==
'I') {
1306 id_to_flush = optarg + 1;
1307 if (*id_to_flush == 0)
1338 if (flags & SM_FLAG_XRCPT)
1344 if (msg_verbose == 1)
1364 msg_panic(
"unknown operation mode: %d", mode);
1367 if (site_to_flush) {
1371 argv_add(ext_argv,
"postqueue",
"-s", site_to_flush, (
char *) 0);
1373 argv_add(ext_argv,
"-v", (
char *) 0);
1377 }
else if (id_to_flush) {
1381 argv_add(ext_argv,
"postqueue",
"-i", id_to_flush, (
char *) 0);
1383 argv_add(ext_argv,
"-v", (
char *) 0);
1388 enqueue(flags, encoding, dsn_envid, dsn_ret, dsn_notify,
1389 rewrite_context, sender, full_name, argv +
OPTIND);
1397 "display queue mode requires no recipient");
1399 argv_add(ext_argv,
"postqueue",
"-p", (
char *) 0);
1401 argv_add(ext_argv,
"-v", (
char *) 0);
1408 "flush queue mode requires no recipient");
1410 argv_add(ext_argv,
"postqueue",
"-f", (
char *) 0);
1412 argv_add(ext_argv,
"-v", (
char *) 0);
1420 argv_add(ext_argv,
"postfix", (
char *) 0);
1422 argv_add(ext_argv,
"-v", (
char *) 0);
1423 argv_add(ext_argv,
"start", (
char *) 0);
1432 "alias initialization mode requires no recipient");
1436 argv_add(ext_argv,
"postalias", (
char *) 0);
1438 argv_add(ext_argv,
"-v", (
char *) 0);
1446 "stand-alone mode requires no recipient");
1449 uid = getuid())) != 0)
1451 "User %s(%ld) is not allowed to submit mail",
1452 errstr, (
long) uid);
1454 argv_add(ext_argv,
"smtpd",
"-S", (
char *) 0);
1456 argv_add(ext_argv,
"-v", (
char *) 0);
int mail_stream_finish(MAIL_STREAM *info, VSTRING *why)
#define MAIL_ATTR_DSN_NOTIFY
#define MAIL_ATTR_TRACE_FLAGS
const char * mail_task(const char *argv0)
char * mystrdup(const char *str)
#define MAIL_ATTR_ENCODING
char * var_import_environ
const char * saved_sender
MIME_STATE * mime_state_alloc(int flags, MIME_STATE_HEAD_OUT head_out, MIME_STATE_ANY_END head_end, MIME_STATE_BODY_OUT body_out, MIME_STATE_ANY_END body_end, MIME_STATE_ERR_PRINT err_print, void *context)
void set_mail_conf_str(const char *, const char *)
ARGV * argv_free(ARGV *argvp)
TOK822 ** tok822_grep(TOK822 *, int)
#define VAR_IMPORT_ENVIRON
NORETURN msg_panic(const char *fmt,...)
NORETURN mail_run_replace(const char *dir, char **argv)
#define MAIL_ATTR_RWR_CONTEXT
#define DEL_REQ_TRACE_ONLY(f)
VSTRING * vstring_truncate(VSTRING *vp, ssize_t len)
#define MAIL_ATTR_RWR_LOCAL
void argv_add(ARGV *argvp,...)
void set_file_limit(off_t limit)
#define DEL_REQ_FLAG_USR_VRFY
#define MAIL_ATTR_RWR_REMOTE
ARGV * argv_alloc(ssize_t len)
char * sane_dirname(VSTRING *bp, const char *path)
int rec_streamlf_get(VSTREAM *stream, VSTRING *buf, int maxlen)
#define MIME_OPT_DISABLE_MIME
MAIL_STREAM * mail_stream_command(const char *command)
#define DEL_REQ_TRACE_FLAGS(f)
TOK822 * tok822_free_tree(TOK822 *)
void mail_conf_read(void)
off_t get_file_limit(void)
#define VSTRING_TERMINATE(vp)
#define REC_PUT_BUF(v, t, b)
MAIL_VERSION_STAMP_DECLARE
#define NAME_CODE_FLAG_STRICT_CASE
int mime_state_update(MIME_STATE *state, int rec_type, const char *text, ssize_t len)
ARGV * mail_parm_split(const char *name, const char *value)
MIME_STATE * mime_state_free(MIME_STATE *state)
int dsn_notify_mask(const char *str)
void mail_conf_checkdir(const char *config_dir)
void(* MIME_STATE_ANY_END)(void *)
VSTREAM * vstream_printf(const char *fmt,...)
#define VSTRING_RESET(vp)
char * safe_getenv(const char *)
int rec_fputs(VSTREAM *stream, int type, const char *str)
int mail_run_background(const char *dir, char **argv)
void msg_warn(const char *fmt,...)
VSTRING * vstring_alloc(ssize_t len)
#define MAIL_ATTR_DSN_RET
void mail_dict_init(void)
const char * username(void)
#define MIME_OPT_REPORT_TRUNC_HEADER
#define MAIL_VERSION_STAMP_ALLOCATE
VSTRING * vstring_sprintf(VSTRING *vp, const char *format,...)
#define MAIL_ATTR_DSN_ENVID
VSTRING * tok822_internalize(VSTRING *, TOK822 *, int)
void get_mail_conf_str_table(const CONFIG_STR_TABLE *)
int rec_put(VSTREAM *stream, int type, const char *data, ssize_t len)
int name_code(const NAME_CODE *table, int flags, const char *name)
const char * verp_delims_verify(const char *delims)
const char * mime_state_error(int error_code)
#define MAIL_VERSION_CHECK
int vstream_fflush(VSTREAM *stream)
void update_env(char **preserve_list)
char * concatenate(const char *arg0,...)
#define GETOPT(argc, argv, str)
void msg_syslog_init(const char *name, int logopt, int facility)
int dsn_ret_code(const char *str)
void set_ugid(uid_t uid, gid_t gid)
#define SM_FIX_EOL_STRICT
char * sane_basename(VSTRING *bp, const char *path)
int main(int argc, char **argv)
void(* MIME_STATE_ERR_PRINT)(void *, int, const char *, ssize_t)
#define SM_FIX_EOL_ALWAYS
VSTRING * vstring_free(VSTRING *vp)
const char * check_user_acl_byuid(const char *pname, const char *acl, uid_t uid)
ARGV * argv_split_append(ARGV *, const char *, const char *)
int allprint(const char *string)
char * split_at(char *string, int delimiter)
void msg_vstream_init(const char *name, VSTREAM *vp)
#define CLEANUP_STAT_WRITE
NORETURN msg_fatal_status(int status, const char *fmt,...)
const char * fullname(void)
const char * cleanup_strerror(unsigned status)
#define MAIL_ATTR_ENC_8BIT
#define vstream_ferror(vp)
int rec_fprintf(VSTREAM *stream, int type, const char *format,...)
MSG_CLEANUP_FN msg_cleanup(MSG_CLEANUP_FN cleanup_fn)
VSTRING * vstring_strcat(VSTRING *vp, const char *src)
#define MAIL_ATTR_ENC_7BIT
void argv_terminate(ARGV *argvp)
#define DEL_REQ_FLAG_RECORD
void msg_info(const char *fmt,...)