summaryrefslogtreecommitdiffabout
path: root/src/dudki.cc
Unidiff
Diffstat (limited to 'src/dudki.cc') (more/less context) (ignore whitespace changes)
-rw-r--r--src/dudki.cc61
1 files changed, 39 insertions, 22 deletions
diff --git a/src/dudki.cc b/src/dudki.cc
index b4e95a7..e91ad5e 100644
--- a/src/dudki.cc
+++ b/src/dudki.cc
@@ -53,30 +53,29 @@ void signal_self(const configuration& config,int signum) {
53} 53}
54 54
55int main(int argc,char **argv) { 55int main(int argc,char **argv) {
56 try { 56 try {
57 _argv = new char*[argc+1]; 57 _argv = new char*[argc+1];
58 if(!_argv) 58 if(!_argv)
59 throw runtime_error("memory allocation problem at the very start"); 59 throw runtime_error("memory allocation problem at the very start");
60 memmove(_argv,argv,sizeof(*_argv)*(argc+1)); 60 memmove(_argv,argv,sizeof(*_argv)*(argc+1));
61 string config_file = DEFAULT_CONF_FILE; 61 string config_file = DEFAULT_CONF_FILE;
62 enum { 62 enum {
63 op_default, 63 op_default,
64 op_work, 64 op_work,
65 op_hup, 65 op_signal,
66 op_term,
67 op_check,
68 op_ensure, 66 op_ensure,
69 op_test 67 op_test
70 } op = op_default; 68 } op = op_default;
69 int op_signum = 0;
71 while(true) { 70 while(true) {
72 #defineSHORTOPTSTRING "f:hVLrkcet" 71 #defineSHORTOPTSTRING "f:hVLrkcet"
73#ifdef HAVE_GETOPT_LONG 72#ifdef HAVE_GETOPT_LONG
74 static struct option opts[] = { 73 static struct option opts[] = {
75 { "help", no_argument, 0, 'h' }, 74 { "help", no_argument, 0, 'h' },
76 { "usage", no_argument, 0, 'h' }, 75 { "usage", no_argument, 0, 'h' },
77 { "version", no_argument, 0, 'V' }, 76 { "version", no_argument, 0, 'V' },
78 { "license", no_argument, 0, 'L' }, 77 { "license", no_argument, 0, 'L' },
79 { "config", required_argument, 0, 'f' }, 78 { "config", required_argument, 0, 'f' },
80 { "kill", no_argument, 0, 'k' }, 79 { "kill", no_argument, 0, 'k' },
81 { "reload", no_argument, 0, 'r' }, 80 { "reload", no_argument, 0, 'r' },
82 { "check", no_argument, 0, 'c' }, 81 { "check", no_argument, 0, 'c' },
@@ -84,85 +83,90 @@ int main(int argc,char **argv) {
84 { "test", no_argument, 0, 't' }, 83 { "test", no_argument, 0, 't' },
85 { NULL, 0, 0, 0 } 84 { NULL, 0, 0, 0 }
86 }; 85 };
87 int c = getopt_long(argc,argv,SHORTOPTSTRING,opts,NULL); 86 int c = getopt_long(argc,argv,SHORTOPTSTRING,opts,NULL);
88#else /* !HAVE_GETOPT_LONG */ 87#else /* !HAVE_GETOPT_LONG */
89 int c = getopt(argc,argv,SHORTOPTSTRING); 88 int c = getopt(argc,argv,SHORTOPTSTRING);
90#endif /* /HAVE_GETOPT_LONG */ 89#endif /* /HAVE_GETOPT_LONG */
91 if(c==-1) 90 if(c==-1)
92 break; 91 break;
93 switch(c) { 92 switch(c) {
94 case 'h': 93 case 'h':
95 cerr << PHEADER << endl 94 cerr << PHEADER << endl
96 << PCOPY << endl << endl << 95 << PCOPY << endl << endl
96 << " " << argv[0] << " [options] [processes]" << endl << endl <<
97#ifdef HAVE_GETOPT_LONG 97#ifdef HAVE_GETOPT_LONG
98 " -h, --help\n" 98 " -h, --help\n"
99 " --usage display this text\n" 99 " --usage display this text\n"
100 " -V, --version display version number\n" 100 " -V, --version display version number\n"
101 " -L, --license show license\n" 101 " -L, --license show license\n"
102 " -f filename, --config=filename\n" 102 " -f filename, --config=filename\n"
103 " specify the configuration file to use\n" 103 " specify the configuration file to use\n"
104 "\n" 104 "\n"
105 " -k, --kill stop running instance\n" 105 " -k, --kill stop running instance (send SIGTERM)\n"
106 " -r, --reload reload running instance (send SIGHUP)\n" 106 " -r, --reload reload running instance (send SIGHUP)\n"
107 " -c, --check check if dudki is running\n" 107 " -c, --check check if the process is running\n"
108 " (the above commands operate on dudki itself if no\n"
109 " process name has been specified)\n"
108 " -e, --ensure ensure that dudki is running\n" 110 " -e, --ensure ensure that dudki is running\n"
109 " -t, --test test configuration file and exit" 111 " -t, --test test configuration file and exit"
110#else /* !HAVE_GETOPT_LONG */ 112#else /* !HAVE_GETOPT_LONG */
111 " -h display this text\n" 113 " -h display this text\n"
112 " -V display version number\n" 114 " -V display version number\n"
113 " -L show license\n" 115 " -L show license\n"
114 " -f filename specify the configuration file to use\n" 116 " -f filename specify the configuration file to use\n"
115 "\n" 117 "\n"
116 " -k stop running instance\n" 118 " -k stop running instance (send SIGTERM)\n"
117 " -r reload running instance (send SIGHUP)\n" 119 " -r reload running instance (send SIGHUP)\n"
118 " -c check if dudki is running\n" 120 " -c check if the process is running\n"
121 " (the above commands operate on dudki itself if no\n"
122 " process name has been specified)\n"
119 " -e ensure that dudki is running\n" 123 " -e ensure that dudki is running\n"
120 " -t test configuration file and exit" 124 " -t test configuration file and exit"
121#endif /* /HAVE_GETOPT_LONG */ 125#endif /* /HAVE_GETOPT_LONG */
122 << endl; 126 << endl;
123 exit(0); 127 exit(0);
124 break; 128 break;
125 case 'V': 129 case 'V':
126 cerr << VERSION << endl; 130 cerr << VERSION << endl;
127 exit(0); 131 exit(0);
128 break; 132 break;
129 case 'L': 133 case 'L':
130 extern const char *COPYING; 134 extern const char *COPYING;
131 cerr << COPYING << endl; 135 cerr << COPYING << endl;
132 exit(0); 136 exit(0);
133 break; 137 break;
134 case 'f': 138 case 'f':
135 config_file = optarg; 139 config_file = optarg;
136 break; 140 break;
137 case 'k': 141 case 'k':
138 if(op!=op_default) { 142 if(op!=op_default) {
139 cerr << "Can't obey two or more orders at once" << endl; 143 cerr << "Can't obey two or more orders at once" << endl;
140 exit(1); 144 exit(1);
141 } 145 }
142 op = op_term; 146 op = op_signal; op_signum = SIGTERM;
143 break; 147 break;
144 case 'r': 148 case 'r':
145 if(op!=op_default) { 149 if(op!=op_default) {
146 cerr << "Can't obey two or more orders at once" << endl; 150 cerr << "Can't obey two or more orders at once" << endl;
147 exit(1); 151 exit(1);
148 } 152 }
149 op = op_hup; 153 op = op_signal; op_signum = SIGHUP;
150 break; 154 break;
151 case 'c': 155 case 'c':
152 if(op!=op_default) { 156 if(op!=op_default) {
153 cerr << "Can't obey two or more orders at once" << endl; 157 cerr << "Can't obey two or more orders at once" << endl;
154 exit(1); 158 exit(1);
155 } 159 }
156 op = op_check; 160 op = op_signal; op_signum = 0;
157 break; 161 break;
158 case 'e': 162 case 'e':
159 if(op!=op_default) { 163 if(op!=op_default) {
160 cerr << "Can't obey two or more orders at once" << endl; 164 cerr << "Can't obey two or more orders at once" << endl;
161 exit(1); 165 exit(1);
162 } 166 }
163 op = op_ensure; 167 op = op_ensure;
164 break; 168 break;
165 case 't': 169 case 't':
166 if(op!=op_default) { 170 if(op!=op_default) {
167 cerr << "Can't obey two or more orders at once" << endl; 171 cerr << "Can't obey two or more orders at once" << endl;
168 exit(1); 172 exit(1);
@@ -178,36 +182,49 @@ int main(int argc,char **argv) {
178 const char *sid = *argv; 182 const char *sid = *argv;
179 const char *t; 183 const char *t;
180 while(t = index(sid,'/')) { 184 while(t = index(sid,'/')) {
181 sid = t; sid++; 185 sid = t; sid++;
182 } 186 }
183 openlog(sid,LOG_CONS|LOG_PERROR|LOG_PID,LOG_DAEMON); 187 openlog(sid,LOG_CONS|LOG_PERROR|LOG_PID,LOG_DAEMON);
184 configuration config; 188 configuration config;
185 config.parse(config_file); 189 config.parse(config_file);
186 switch(op) { 190 switch(op) {
187 case op_test: 191 case op_test:
188 cerr << "Configuration OK" << endl; 192 cerr << "Configuration OK" << endl;
189 break; 193 break;
190 case op_hup: 194 case op_signal:
191 signal_self(config,SIGHUP); 195 try {
192 break; 196 if(optind>=argc) {
193 case op_term: 197 signal_self(config,op_signum);
194 signal_self(config,SIGTERM); 198 }else{
195 break; 199 int failures = 0;
196 case op_check: 200 for(int narg=optind;narg<argc;narg++) {
197 try{ 201 try {
198 signal_self(config,0); 202 processes_t::const_iterator i = config.processes.find(argv[narg]);
199 exit(0); 203 if(i==config.processes.end())
204 throw runtime_error("no such process configured");
205 i->second.signal(op_signum);
206 }catch(exception& e) {
207 cerr << "dudki(" << argv[narg] << "): " << e.what() << endl;
208 failures++;
209 }
210 }
211 if(failures)
212 throw runtime_error("not all processes have been successfully signaled");
213 }
214 if(!op_signum)
215 exit(0);
200 }catch(exception& e) { 216 }catch(exception& e) {
201 exit(1); 217 if(!op_signum)
218 exit(1);
202 } 219 }
203 case op_ensure: 220 case op_ensure:
204 try { 221 try {
205 signal_self(config,0); 222 signal_self(config,0);
206 break; 223 break;
207 }catch(exception& e) { 224 }catch(exception& e) {
208 syslog(LOG_NOTICE,"The dudki process is down, taking its place"); 225 syslog(LOG_NOTICE,"The dudki process is down, taking its place");
209 config.daemonize = true; 226 config.daemonize = true;
210 }catch(int zero) { 227 }catch(int zero) {
211 // we throw zero in case we're ensuring that this very process is running. 228 // we throw zero in case we're ensuring that this very process is running.
212 // we don't have to daemonize if we're daemonic. 229 // we don't have to daemonize if we're daemonic.
213 config.daemonize = false; 230 config.daemonize = false;