Subversion Repositories general

Compare Revisions

Ignore whitespace Rev 1142 → Rev 1143

/rebootdaemon/trunk/rebootdaemon.c
1,7 → 1,7
/******************************************************************
*
* Daemon which waiting on specified TCP port for special string
* and reboot the computer.
* Daemon which waits on specified TCP port for special string
* and reboots the computer.
*
* Command line: rebootdaemon [--port PORT] [--config CONFIG_FILE]
* Defaults are port 19 and config /etc/rebootdaemon.conf.
35,8 → 35,8
#include <netinet/in.h>
#include <arpa/inet.h>
 
#define PORT 19
#define CFG_FILE "/etc/rebootdaemon.conf"
#define DEFAULT_PORT 19
#define DEFAULT_CFG_FILE "/etc/rebootdaemon.conf"
#define CMDSIZE 4096
#define BUFSIZE 4096
#define MAX_CONFIG_LINE 4096
55,8 → 55,6
char password[MAX_CONFIG_LINE];
};
 
static struct config cfg;
 
static int parse_cmd_line(int argc, char* argv[], long *port, char *config_name);
static int parse_config_file(char *config_name, long *port, char *password);
 
89,7 → 87,7
return s;
}
 
static void listen_socket(int socket)
static void listen_socket(struct config *cfg, int socket)
{
int t;
char cmd[CMDSIZE];
122,7 → 120,7
 
syslog(LOG_INFO, "got command [%s]", cmd);
if(0 == strncmp(cmd, cfg.password, sizeof(cmd))) {
if(0 == strncmp(cmd, cfg->password, sizeof(cmd))) {
syslog(LOG_EMERG, "REBOOT");
sleep(5);
if(reboot(RB_AUTOBOOT) < 0) {
151,27 → 149,29
return 0;
}
 
static int read_config(int argc, char* argv[])
static int read_config(struct config *cfg, int argc, char* argv[])
{
long cmd_port;
long file_port;
char cmd_config[MAX_CONFIG_LINE];
 
if(!parse_cmd_line(argc, argv, &cmd_port, cmd_config)) return 0;
if(!parse_cmd_line(argc, argv, &cmd_port, cmd_config))
return 0;
 
if(!parse_config_file(cmd_config[0] != '\0' ? cmd_config : CFG_FILE, &file_port, cfg.password)) return 0;
if(!parse_config_file(cmd_config[0] != '\0' ? cmd_config : DEFAULT_CFG_FILE, &file_port, cfg->password))
return 0;
 
if(cfg.password[0] == '\0') {
if(cfg->password[0] == '\0') {
fprintf(stderr, "Password is not set\n");
return 0;
}
 
if(cmd_port > 0)
cfg.port = (int)cmd_port;
cfg->port = (int)cmd_port;
else if(file_port > 0)
cfg.port = (int)file_port;
cfg->port = (int)file_port;
else
cfg.port = PORT;
cfg->port = DEFAULT_PORT;
 
return 1;
}
305,19 → 305,79
return 1;
}
 
static int create_child(int socket)
{
pid_t child;
 
child = fork();
if(child == -1) {
fprintf(stderr, "Cannot fork: %s\n", strerror(errno));
return 2; /* an unexpected error */
}
else if(child > 0) {
if(close(socket) != 0) {
fprintf(stderr, "Cannot close socket: %s\n", strerror(errno));
return 2; /* an unexpected error */
}
return 0; /* we are the parent */
}
else {
return 1; /* we are the child */
}
}
 
static int close_descr(int d)
{
if(close(d) != 0) {
syslog(LOG_ERR, "Cannot close descriptor %d: %s\n", d, strerror(errno));
return 0;
}
return 1;
}
 
int main(int argc, char* argv[])
{
int s;
int socket;
struct config cfg;
 
if(!read_config(argc, argv)) return 1;
 
if((s = establish(cfg.port)) < 0) {
/* get config */
if(!read_config(&cfg, argc, argv)) return 1;
 
/* try to listen the port */
if((socket = establish(cfg.port)) < 0) {
fprintf(stderr, "Cannot listen to port %i\n", cfg.port);
return 1;
}
 
listen_socket(s);
/* fork and release the console */
switch(create_child(socket)) {
case 0: return 0;
case 2: return 2;
}
 
/* continue as first child */
if(setsid() == -1) {
fprintf(stderr, "Cannot create session: %s\n", strerror(errno));
return 2;
}
 
/* fork the second time */
switch(create_child(socket)) {
case 0: return 0;
case 2: return 2;
}
 
/* continue as final child, from now do not use console for error output */
chdir("/");
umask(0);
if(!close_descr(0)) return 2;
if(!close_descr(1)) return 2;
if(!close_descr(2)) return 2;
 
syslog(LOG_INFO, "listen on %d", cfg.port);
listen_socket(&cfg, socket);
 
return 0;
}
 
/rebootdaemon/trunk/rebootdaemon.conf
0,0 → 1,5
# reboot daemon configuration
 
port=2019
password="password"