1/*++
2/* NAME
3/*	mail_run 3
4/* SUMMARY
5/*	run mail component program
6/* SYNOPSIS
7/*	#include <mail_run.h>
8/*
9/*	int	mail_run_foreground(dir, argv)
10/*	const char *dir;
11/*	char	**argv;
12/*
13/*	int	mail_run_background(dir, argv)
14/*	const char *dir;
15/*	char	**argv;
16/*
17/*	NORETURN mail_run_replace(dir, argv)
18/*	const char *dir;
19/*	char	**argv;
20/* DESCRIPTION
21/*	This module runs programs that live in the mail program directory.
22/*	Each routine takes a directory and a command-line array. The program
23/*	pathname is built by prepending the directory and a slash to the
24/*	command name.
25/*
26/*	mail_run_foreground() runs the named command in the foreground and
27/*	waits until the command terminates.
28/*
29/*	mail_run_background() runs the named command in the background.
30/*
31/*	mail_run_replace() attempts to replace the current process by
32/*	an instance of the named command. This function never returns.
33/*
34/*	Arguments:
35/* .IP argv
36/*	A null-terminated command-line vector. The first array element
37/*	is the base name of the program to be executed.
38/* DIAGNOSTICS
39/*	The result is (-1) if the command could not be run. Otherwise,
40/*	mail_run_foreground() returns the termination status of the
41/*	command. mail_run_background() returns the process id in case
42/*	of success.
43/* CONFIGURATION PARAMETERS
44/*	fork_attempts: number of attempts to fork() a process;
45/*	fork_delay: delay in seconds between fork() attempts.
46/* LICENSE
47/* .ad
48/* .fi
49/*	The Secure Mailer license must be distributed with this software.
50/* AUTHOR(S)
51/*	Wietse Venema
52/*	IBM T.J. Watson Research
53/*	P.O. Box 704
54/*	Yorktown Heights, NY 10598, USA
55/*--*/
56
57/* System library. */
58
59#include <sys_defs.h>
60#include <sys/wait.h>
61#include <unistd.h>
62#include <errno.h>
63
64/* Utility library. */
65
66#include <msg.h>
67#include <stringops.h>
68#include <mymalloc.h>
69
70/* Global library. */
71
72#include "mail_params.h"
73#include "mail_run.h"
74
75/* mail_run_foreground - run command in foreground */
76
77int     mail_run_foreground(const char *dir, char **argv)
78{
79    int     count;
80    char   *path;
81    WAIT_STATUS_T status;
82    int     pid;
83    int     wpid;
84
85#define RETURN(x) { myfree(path); return(x); }
86
87    path = concatenate(dir, "/", argv[0], (char *) 0);
88
89    for (count = 0; count < var_fork_tries; count++) {
90	switch (pid = fork()) {
91	case -1:
92	    msg_warn("fork %s: %m", path);
93	    break;
94	case 0:
95	    /* Reset the msg_cleanup() handlers in the child process. */
96	    (void) msg_cleanup((MSG_CLEANUP_FN) 0);
97	    execv(path, argv);
98	    msg_fatal("execv %s: %m", path);
99	default:
100	    do {
101		wpid = waitpid(pid, &status, 0);
102	    } while (wpid == -1 && errno == EINTR);
103	    RETURN(wpid == -1 ? -1 :
104		   WIFEXITED(status) ? WEXITSTATUS(status) : 1)
105	}
106	sleep(var_fork_delay);
107    }
108    RETURN(-1);
109}
110
111/* mail_run_background - run command in background */
112
113int     mail_run_background(const char *dir, char **argv)
114{
115    int     count;
116    char   *path;
117    int     pid;
118
119#define RETURN(x) { myfree(path); return(x); }
120
121    path = concatenate(dir, "/", argv[0], (char *) 0);
122
123    for (count = 0; count < var_fork_tries; count++) {
124	switch (pid = fork()) {
125	case -1:
126	    msg_warn("fork %s: %m", path);
127	    break;
128	case 0:
129	    /* Reset the msg_cleanup() handlers in the child process. */
130	    (void) msg_cleanup((MSG_CLEANUP_FN) 0);
131	    execv(path, argv);
132	    msg_fatal("execv %s: %m", path);
133	default:
134	    RETURN(pid);
135	}
136	sleep(var_fork_delay);
137    }
138    RETURN(-1);
139}
140
141/* mail_run_replace - run command, replacing current process */
142
143NORETURN mail_run_replace(const char *dir, char **argv)
144{
145    char   *path;
146
147    path = concatenate(dir, "/", argv[0], (char *) 0);
148    execv(path, argv);
149    msg_fatal("execv %s: %m", path);
150}
151