* #include <err.h>
* #include <stdlib.h>
*
+ * #define STATE_FILE "/var/run/oserver/dump"
+ *
* int main(int argc, char *argv[])
* {
* struct tevent_context *ev = tevent_context_init(NULL);
* unsigned int port = OSERVER_PORT;
+ * bool restore = false;
+ * char **restore_argv;
+ *
+ * // Save args before opt_parse mangles them.
+ * restore_argv = talloc_array(NULL, char *, argc+2);
+ * restore_argv[0] = argv[0];
+ * restore_argv[1] = "--restore";
+ * memcpy(restore_argv+2, argv+1, sizeof(argv[0])*argc);
*
* opt_register_noarg("--help|--usage|-h", opt_usage_and_exit,
* "\nA oserver program", "Usage information");
* opt_register_arg("--port", opt_set_uintval, opt_show_uintval,
* &port, "Server port number");
+ * opt_register_noarg("--restore", opt_set_bool,
+ * &restore, opt_hidden);
*
* opt_parse(&argc, argv, opt_log_stderr_exit);
* if (argc != 1)
* opt_log_stderr_exit("Unknown extra arguments");
*
- * if (!oserver_setup(ev, port, "/var/run/oserver/dump"))
+ * if (restore) {
+ * if (!oserver_restore(ev, STATE_FILE))
+ * err(1, "Restoring server");
+ * } else if (!oserver_setup(ev, port, STATE_FILE, restore_argv))
* err(1, "Failed to set up server");
*
* while (tevent_loop_wait(ev) == 0);
write(fd, str, strlen(str));
close(fd);
talloc_free(str);
+ if (oserver->argv)
+ execvp(oserver->argv[0], oserver->argv);
}
static bool load_file(struct oserver *oserver, const char *file)
}
struct oserver *oserver_setup(struct tevent_context *ev, unsigned short port,
- const char *dumpfile)
+ const char *dumpfile, char *argv[])
{
struct oserver *oserver;
int one = 1;
} u;
oserver = talloc(ev, struct oserver);
+ oserver->argv = argv;
+ if (argv) {
+ /* Count the terminal NULL in argv_len. */
+ for (oserver->argv_len = 1;
+ argv[oserver->argv_len - 1];
+ oserver->argv_len++);
+ } else
+ oserver->argv_len = 0;
clear_clients(oserver);
oserver->fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (oserver->fd < 0) {
* @ev: tevent context to use.
* @port: port to use (usually OSERVER_PORT)
* @dumpfile: file to save state to on SIGHUP (if non-NULL).
+ * @argv: arguments to re-exec on SIGHUP (if non-NULL).
*
* Opens a socket and binds it to @port, then sets it up to listen
* for connections. talloc_free() the pointer returned to shut it down
* Example:
* ...
* else {
- * oserver = oserver_setup(ev, OSERVER_PORT, "oserver.dump");
+ * oserver = oserver_setup(ev, OSERVER_PORT, "oserver.dump", argv);
* if (!oserver)
* err(1, "Failed to set up server");
* }
* err(1, "Event loop failed");
*/
struct oserver *oserver_setup(struct tevent_context *ev, unsigned short port,
- const char *dumpfile);
+ const char *dumpfile, char *argv[]);
#define OSERVER_PORT 2828
#endif /* CCAN_OSERVER_H */
int fd;
struct tevent_fd *fde CDUMP_IGNORE;
const char *dumpfile;
+ int argv_len;
+ char **argv CDUMP_LEN(argv_len);
};
#endif /* CCAN_OSERVER_TYPES_H */
/* This is how many tests you plan to run */
plan_tests(2);
- oserver = oserver_setup(ev, OSERVER_PORT, NULL);
+ oserver = oserver_setup(ev, OSERVER_PORT, NULL, NULL);
if (!oserver)
err(1, "Failed to set up server");
{
struct tevent_context *ev = tevent_context_init(NULL);
- if (oserver_setup(ev, OSERVER_PORT, NULL) == NULL)
+ if (oserver_setup(ev, OSERVER_PORT, NULL, NULL) == NULL)
exit(1);
tevent_add_fd(ev, ev, exitfd, TEVENT_FD_READ, exit_quietly, NULL);