summaryrefslogtreecommitdiffstats
path: root/src/global/mail_run.c
blob: f3764345f4148b481a87ae3f54035b3c1a257540 (plain)
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
/*++
/* NAME
/*	mail_run 3
/* SUMMARY
/*	run mail component program
/* SYNOPSIS
/*	#include <mail_run.h>
/*
/*	int	mail_run_foreground(dir, argv)
/*	const char *dir;
/*	char	**argv;
/*
/*	int	mail_run_background(dir, argv)
/*	const char *dir;
/*	char	**argv;
/*
/*	NORETURN mail_run_replace(dir, argv)
/*	const char *dir;
/*	char	**argv;
/* DESCRIPTION
/*	This module runs programs that live in the mail program directory.
/*	Each routine takes a directory and a command-line array. The program
/*	pathname is built by prepending the directory and a slash to the
/*	command name.
/*
/*	mail_run_foreground() runs the named command in the foreground and
/*	waits until the command terminates.
/*
/*	mail_run_background() runs the named command in the background.
/*
/*	mail_run_replace() attempts to replace the current process by
/*	an instance of the named command. This function never returns.
/*
/*	Arguments:
/* .IP argv
/*	A null-terminated command-line vector. The first array element
/*	is the base name of the program to be executed.
/* DIAGNOSTICS
/*	The result is (-1) if the command could not be run. Otherwise,
/*	mail_run_foreground() returns the termination status of the
/*	command. mail_run_background() returns the process id in case
/*	of success.
/* CONFIGURATION PARAMETERS
/*	fork_attempts: number of attempts to fork() a process;
/*	fork_delay: delay in seconds between fork() attempts.
/* LICENSE
/* .ad
/* .fi
/*	The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/*	Wietse Venema
/*	IBM T.J. Watson Research
/*	P.O. Box 704
/*	Yorktown Heights, NY 10598, USA
/*--*/

/* System library. */

#include <sys_defs.h>
#include <sys/wait.h>
#include <unistd.h>
#include <errno.h>

/* Utility library. */

#include <msg.h>
#include <stringops.h>
#include <mymalloc.h>

/* Global library. */

#include "mail_params.h"
#include "mail_run.h"

/* mail_run_foreground - run command in foreground */

int     mail_run_foreground(const char *dir, char **argv)
{
    int     count;
    char   *path;
    WAIT_STATUS_T status;
    int     pid;
    int     wpid;

#define RETURN(x) { myfree(path); return(x); }

    path = concatenate(dir, "/", argv[0], (char *) 0);

    for (count = 0; count < var_fork_tries; count++) {
	switch (pid = fork()) {
	case -1:
	    msg_warn("fork %s: %m", path);
	    break;
	case 0:
	    /* Reset the msg_cleanup() handlers in the child process. */
	    (void) msg_cleanup((MSG_CLEANUP_FN) 0);
	    execv(path, argv);
	    msg_fatal("execv %s: %m", path);
	default:
	    do {
		wpid = waitpid(pid, &status, 0);
	    } while (wpid == -1 && errno == EINTR);
	    RETURN(wpid == -1 ? -1 :
		   WIFEXITED(status) ? WEXITSTATUS(status) : 1)
	}
	sleep(var_fork_delay);
    }
    RETURN(-1);
}

/* mail_run_background - run command in background */

int     mail_run_background(const char *dir, char **argv)
{
    int     count;
    char   *path;
    int     pid;

#define RETURN(x) { myfree(path); return(x); }

    path = concatenate(dir, "/", argv[0], (char *) 0);

    for (count = 0; count < var_fork_tries; count++) {
	switch (pid = fork()) {
	case -1:
	    msg_warn("fork %s: %m", path);
	    break;
	case 0:
	    /* Reset the msg_cleanup() handlers in the child process. */
	    (void) msg_cleanup((MSG_CLEANUP_FN) 0);
	    execv(path, argv);
	    msg_fatal("execv %s: %m", path);
	default:
	    RETURN(pid);
	}
	sleep(var_fork_delay);
    }
    RETURN(-1);
}

/* mail_run_replace - run command, replacing current process */

NORETURN mail_run_replace(const char *dir, char **argv)
{
    char   *path;

    path = concatenate(dir, "/", argv[0], (char *) 0);
    execv(path, argv);
    msg_fatal("execv %s: %m", path);
}