death to trailing whitespace
[openafs.git] / src / afsweb / apache_afs_weblog.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  *
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 /* the wrapper nanny process around weblog that would restart it in case it
11  * failed and hopefully log the error somewhere! The need for this nanny
12  * process arises because the pipe descriptors need to be maintained. The
13  * process catches SIGTERM and kills the weblog process and exits.
14  * The following line needs to precede the kill -TERM line for httpd.pid
15  * in the stopd script to stop the server
16           kill -TERM `<cat /local/stronghold/apache/logs/httpd.pid>.afs`
17  * or whatever the pid file
18  */
19
20 #include <afs/stds.h>
21
22 #include <stdio.h>
23 #include <sys/types.h>
24 #include <sys/wait.h>
25 #include <signal.h>
26 #include <fcntl.h>
27
28 #include "weblog_errors.h"
29 #include "AFS_component_version_number.c"
30
31 #define WEBLOG_BIN "weblog"
32
33 /* TODO - set restart_attempts to 0 if not within certain time period */
34 #define MAX_RESTARTS        3   /* after this many restarts just die */
35 static int restart_attempts = 0;
36
37 int error_fd;                   /* error file descriptor */
38
39 void
40 sig_term()
41 {
42 #ifdef AIX
43     pid_t pgrp = getpgrp();
44 #else
45     pid_t pgrp = getpgrp(0);
46 #endif
47     int n;
48
49 #ifdef DEBUG
50     write(2, "weblog_starter: caught SIGTERM, shutting down", 43);
51 #endif
52
53     log_error("weblog_starter: caught SIGTERM, shutting down");
54
55     if (pgrp == (pid_t) - 1) {
56         log_error("getpgrp failed - kill weblog manually");
57         write(2, "getpgrp failed - kill weblog manually", 38);
58         exit(1);
59     }
60     kill(-pgrp, SIGKILL);
61     exit(1);
62 }
63
64 /* strip out this binary and replace it with the weblog binary's name */
65 getpath(char *this, char *path)
66 {
67     char *temp = &this[0];
68     int len = strlen(this);
69     int pos = 0, i = 0, j = 0;
70     char bin_name[] = WEBLOG_BIN;
71     int len1 = strlen(bin_name);
72
73     strcpy(path, this);
74     temp += (len);
75     pos = len;
76     while (*temp != '/') {
77         temp--;
78         pos--;
79     }
80     for (i = (pos + 1); i < len; i++, j++) {
81         path[i] = bin_name[j];
82         if (j >= len1)
83             break;
84     }
85 }
86
87 char *
88 get_time()
89 {
90     time_t t;
91     char *time_string;
92
93     t = time(NULL);
94     time_string = (char *)ctime(&t);
95     time_string[strlen(time_string) - 1] = '\0';
96     return (time_string);
97 }
98
99 log_error(char *msg)
100 {
101     char err_msg[1024];
102
103     sprintf(err_msg, "[%s] weblog:%s\n", get_time(), msg);
104     write(error_fd, (void *)err_msg, strlen(err_msg));
105 }
106
107
108 int
109 main(int argc, char **argv)
110 {
111     pid_t weblog_pid;
112     int stat = -1;
113     int exitstatus = 0;
114     char rn[] = "weblog_starter";
115     char path[1024];
116     char error_fname[1024];
117
118     struct sigaction sa;
119
120     memset(&sa, 0, sizeof sa);
121     sa.sa_handler = (void (*)())sig_term;
122     if (sigaction(SIGTERM, &sa, NULL) < 0) {
123         perror("sigaction(SIGTERM)");
124     }
125
126     getpath(argv[1], path);
127     strcpy(error_fname, argv[2]);
128
129     error_fd = open(error_fname, O_WRONLY | O_APPEND | O_CREAT);
130     if (error_fd < 0) {
131         fprintf(stderr, "%s:Error opening log file:%s\nExiting\n", rn,
132                 error_fname);
133         perror("open");
134         exit(-1);
135     }
136
137     log_error("weblog_starter resuming normal operation");
138
139     while (restart_attempts < MAX_RESTARTS) {
140         /* fork the weblog process and wait till it exits */
141         if ((weblog_pid = fork()) < 0) {
142             log_error("Could not fork process");
143 #ifdef DEBUG
144             perror("apache_afs_weblog:Could not fork process");
145 #endif
146             exit(-1);
147         }
148         switch (weblog_pid) {
149         case 0:
150             /* the child process - in this case weblog */
151             execlp(path, "weblog", argv[3], argv[4], argv[5], argv[6], NULL);
152 #ifdef DEBUG
153             perror("apache_afs_weblog:Could not execute weblog");
154 #endif
155             exit(RESTARTERROR);
156
157         default:
158             /* parent: just wait for the child */
159             weblog_pid = waitpid((pid_t) - 1, &stat, 0);
160
161             if (weblog_pid == -1) {
162 #ifdef DEBUG
163                 perror("apache_Afs_weblog: wait error");
164 #endif
165                 log_error("wait error");
166                 kill(getpid(), SIGTERM);
167             }
168
169             if (WIFEXITED(stat)) {
170                 exitstatus = WEXITSTATUS(stat);
171                 switch (exitstatus) {
172                 case 0:
173 #ifdef DEBUG
174                     fprintf(stderr, "%s:No error ... restarting\n", rn);
175 #endif
176                     break;
177
178                 case RESTART:
179 #ifdef DEBUG
180                     fprintf(stderr, "%s:%s...Exiting\n", rn, RESTARTMSG);
181 #endif
182                     log_error(RESTARTMSG);
183                     exit(-1);
184
185                 case NULLARGS:
186 #ifdef DEBUG
187                     fprintf(stderr, "%s:%s...Exiting\n", rn, NULLARGSMSG);
188                     log_error(NULLARGSMSG);
189 #endif
190                     exit(-1);
191
192                 case PIPESEND:
193 #ifdef DEBUG
194                     fprintf(stderr, "%s:%s...Restarting\n", rn, PIPESENDMSG);
195 #endif
196                     log_error(PIPESENDMSG);
197                     break;
198
199                 case PIPEREAD:
200 #ifdef DEBUG
201                     fprintf(stderr, "%s:%s...Exiting\n", rn, PIPEREADMSG);
202 #endif
203                     log_error(PIPEREADMSG);
204                     exit(-1);
205
206                 case PARSE:
207 #ifdef DEBUG
208                     fprintf(stderr, "%s:%s...Exiting\n", rn, PARSEMSG);
209 #endif
210                     log_error(PARSEMSG);
211                     exit(-1);
212
213                 case KA:
214 #ifdef DEBUG
215                     fprintf(stderr, "%s:%s...Exiting\n", rn, KAMSG);
216 #endif
217                     log_error(KAMSG);
218                     exit(-1);
219
220                 default:
221 #ifdef DEBUG
222                     fprintf(stderr, "%s:Unknown error...Exiting\n", rn);
223 #endif
224                     log_error("Unknown error");
225                     exit(-1);
226                 }               /* switch (exitstatus) */
227             }
228             /* if weblog exited */
229             else {              /* weblog terminated abnormally */
230                 if (WIFSIGNALED(stat)) {
231 #ifdef DEBUG
232                     fprintf(stderr,
233                             "%s:The signal that terminated weblog:%d\n"
234                             "Restarting weblog ...\n", rn, WTERMSIG(stat));
235 #endif
236                 }
237 #ifndef AIX
238                 else if (WCOREDUMP(stat)) {
239 #ifdef DEBUG
240                     fprintf(stderr, "%s: weblog dumped core" "Exiting ...\n",
241                             rn);
242 #endif
243                     log_error("Core dump");
244                     exit(-1);
245                 }
246 #endif
247                 else {
248 #ifdef DEBUG
249                     fprintf(stderr,
250                             "%s: weblog died under STRANGE circumstances..."
251                             "restarting weblog\n", rn);
252 #endif
253                 }
254             }
255             break;
256         }                       /* switch(weblog_pid) */
257         restart_attempts++;
258     }                           /* while */
259 }