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 
mail_run_foreground(const char * dir,char ** argv)77 int     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 
mail_run_background(const char * dir,char ** argv)113 int     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 
mail_run_replace(const char * dir,char ** argv)143 NORETURN 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