00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "main.h"
00028 #include <signal.h>
00029 #include "bg.h"
00030
00031 extern char pid_file[];
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069 typedef struct {
00070 enum {
00071 BG_COMM_QUIT,
00072 BG_COMM_ABORT,
00073 BG_COMM_TRANSFERPF
00074 } comm_type;
00075 union {
00076 struct {
00077 int len;
00078 } transferpf;
00079 } comm_data;
00080 } bg_comm_t;
00081
00082 typedef enum {
00083 BG_NONE = 0,
00084 BG_SPLIT,
00085 BG_PARENT
00086 } bg_state_t;
00087
00088 typedef struct {
00089 int comm_recv;
00090 int comm_send;
00091 bg_state_t state;
00092 pid_t child_pid;
00093 } bg_t;
00094
00095 static bg_t bg = { 0 };
00096
00097
00098
00099
00100
00101
00102 static void bg_do_detach(pid_t p)
00103 {
00104 FILE *fp;
00105
00106
00107 unlink(pid_file);
00108 fp = fopen(pid_file, "w");
00109 if (fp != NULL) {
00110 fprintf(fp, "%u\n", p);
00111 if (fflush(fp)) {
00112
00113 printf(EGG_NOWRITE, pid_file);
00114 printf(" Try freeing some disk space\n");
00115 fclose(fp);
00116 unlink(pid_file);
00117 exit(1);
00118 }
00119 fclose(fp);
00120 } else
00121 printf(EGG_NOWRITE, pid_file);
00122 printf("Launched into the background (pid: %d)\n\n", p);
00123 #ifdef HAVE_SETPGID
00124 setpgid(p, p);
00125 #endif
00126 exit(0);
00127 }
00128
00129 void bg_prepare_split(void)
00130 {
00131 pid_t p;
00132 bg_comm_t message;
00133
00134 if (!fork_before_tcl())
00135 return;
00136
00137
00138
00139 {
00140 int comm_pair[2];
00141
00142 if (pipe(comm_pair) < 0)
00143 fatal("CANNOT OPEN PIPE.", 0);
00144
00145 bg.comm_recv = comm_pair[0];
00146 bg.comm_send = comm_pair[1];
00147 }
00148
00149 p = fork();
00150 if (p == -1)
00151 fatal("CANNOT FORK PROCESS.", 0);
00152 if (p == 0) {
00153 bg.state = BG_SPLIT;
00154 return;
00155 } else {
00156 bg.child_pid = p;
00157 bg.state = BG_PARENT;
00158 }
00159
00160 while (read(bg.comm_recv, &message, sizeof(message)) > 0) {
00161 switch (message.comm_type) {
00162 case BG_COMM_QUIT:
00163 bg_do_detach(p);
00164 break;
00165 case BG_COMM_ABORT:
00166 exit(1);
00167 break;
00168 case BG_COMM_TRANSFERPF:
00169
00170
00171 if (message.comm_data.transferpf.len >= 40)
00172 message.comm_data.transferpf.len = 40 - 1;
00173
00174 if (read(bg.comm_recv, pid_file, message.comm_data.transferpf.len) <= 0)
00175 goto error;
00176 pid_file[message.comm_data.transferpf.len] = 0;
00177 break;
00178 }
00179 }
00180
00181 error:
00182
00183
00184 fatal("COMMUNICATION THROUGH PIPE BROKE.", 0);
00185 }
00186
00187
00188
00189
00190
00191 static void bg_send_pidfile(void)
00192 {
00193 bg_comm_t message;
00194
00195 message.comm_type = BG_COMM_TRANSFERPF;
00196 message.comm_data.transferpf.len = strlen(pid_file);
00197
00198
00199 if (write(bg.comm_send, &message, sizeof(message)) < 0)
00200 goto error;
00201
00202 if (write(bg.comm_send, pid_file, message.comm_data.transferpf.len) < 0)
00203 goto error;
00204 return;
00205 error:
00206 fatal("COMMUNICATION THROUGH PIPE BROKE.", 0);
00207 }
00208
00209 void bg_send_quit(bg_quit_t q)
00210 {
00211 if (!fork_before_tcl())
00212 return;
00213
00214 if (bg.state == BG_PARENT) {
00215 kill(bg.child_pid, SIGKILL);
00216 } else if (bg.state == BG_SPLIT) {
00217 bg_comm_t message;
00218
00219 if (q == BG_QUIT) {
00220 bg_send_pidfile();
00221 message.comm_type = BG_COMM_QUIT;
00222 } else
00223 message.comm_type = BG_COMM_ABORT;
00224
00225 if (write(bg.comm_send, &message, sizeof(message)) < 0)
00226 fatal("COMMUNICATION THROUGH PIPE BROKE.", 0);
00227 }
00228 }
00229
00230 void bg_do_split(void)
00231 {
00232 if (fork_before_tcl()) {
00233
00234 bg_send_quit(BG_QUIT);
00235
00236 } else {
00237
00238 int xx = fork();
00239
00240 if (xx == -1)
00241 fatal("CANNOT FORK PROCESS.", 0);
00242 if (xx != 0)
00243 bg_do_detach(xx);
00244 }
00245 }