void *malloc(int);
struct handle
{
- int argc;
- char **argv;
- char *ctl;
- int nextarg, nextchar;
+ int argc;
+ char **argv;
+ char *ctl;
+ int nextarg, nextchar;
};
#define NULLH ((struct handle *)0)
struct handle *args_init(int argc, char **argv, char *ctl)
{
- /* if ctl is bad, return NULL, else a handle */
- int i;
- struct handle *h;
- for (i=0 ; ctl[i]; i+= 2)
- if (ctl[i+1] != '?' && ctl[i+1] != '-' && ctl[i+1] != '+' && ctl[i+1] != ':')
- break;
- if (ctl[i])
- return NULLH;
+ /* if ctl is bad, return NULL, else a handle */
+ int i;
+ struct handle *h;
+ for (i=0 ; ctl[i]; i+= 2)
+ if (ctl[i+1] != '?' && ctl[i+1] != '-' && ctl[i+1] != '+' && ctl[i+1] != ':')
+ break;
+ if (ctl[i])
+ return NULLH;
- h = (struct handle*)malloc(sizeof(struct handle));
- if (h == NULLH)
+ h = (struct handle*)malloc(sizeof(struct handle));
+ if (h == NULLH)
+ return h;
+ h->argc = argc;
+ h->argv = argv;
+ h->ctl = ctl;
+ h->nextarg = 1;
+ h->nextchar = 0;
return h;
- h->argc = argc;
- h->argv = argv;
- h->ctl = ctl;
- h->nextarg = 1;
- h->nextchar = 0;
- return h;
}
int args_next(struct handle *h, int *pos, int *inv, char **opt)
{
- int invc = 0;
- int invfound = 0;
- int i;
- char *a;
- if (h->nextarg >= h->argc)
- return END_ARGS;
- if (h->nextchar == 0)
- {
- if (h->argv[h->nextarg][0] != '-')
+ int invc = 0;
+ int invfound = 0;
+ int i;
+ char *a;
+ if (h->nextarg >= h->argc)
+ return END_ARGS;
+ if (h->nextchar == 0)
{
- if (pos) *pos = h->nextarg;
- if (inv) *inv = 0;
- if (opt) *opt = h->argv[h->nextarg];
- h->nextarg++;
- return NO_FLAG;
+ if (h->argv[h->nextarg][0] != '-')
+ {
+ if (pos) *pos = h->nextarg;
+ if (inv) *inv = 0;
+ if (opt) *opt = h->argv[h->nextarg];
+ h->nextarg++;
+ return NO_FLAG;
+ }
+ h->nextchar++;
+ }
+ a = h->argv[h->nextarg];
+ while (a[h->nextchar] == '~')
+ {
+ invc = !invc;
+ invfound = 1;
+ h->nextchar++;
+ }
+ for (i=0 ; h->ctl[i] ; i+=2)
+ if (h->ctl[i] == a[h->nextchar])
+ break;
+ if (h->ctl[i] == 0)
+ {
+ h->nextchar = 0;
+ h->nextarg ++;
+ return BAD_FLAG;
}
h->nextchar++;
- }
- a = h->argv[h->nextarg];
- while (a[h->nextchar] == '~')
- {
- invc = !invc;
- invfound = 1;
- h->nextchar++;
- }
- for (i=0 ; h->ctl[i] ; i+=2)
- if (h->ctl[i] == a[h->nextchar])
- break;
- if (h->ctl[i] == 0)
- {
- h->nextchar = 0;
- h->nextarg ++;
- return BAD_FLAG;
- }
- h->nextchar++;
- if (pos) *pos = h->nextarg;
- if (inv) *inv = invc;
- if (a[h->nextchar] == 0)
- {
- h->nextchar = 0;
- h->nextarg ++;
- }
- switch(h->ctl[i+1])
- {
- case '?':
+ if (pos) *pos = h->nextarg;
+ if (inv) *inv = invc;
+ if (a[h->nextchar] == 0)
+ {
+ h->nextchar = 0;
+ h->nextarg ++;
+ }
+ switch(h->ctl[i+1])
+ {
+ case '?':
+ return h->ctl[i];
+ case '+':
+ if (inv)
+ return h->ctl[i];
+ break;
+ case '-':
+ if (!inv)
+ return h->ctl[i];
+ break;
+ case ':':
+ break;
+ }
+ /* need optarg */
+ if (h->nextarg >= h->argc)
+ return BAD_FLAG;
+ if (opt)
+ *opt = h->argv[h->nextarg] + h->nextchar;
+ h->nextarg++;
+ h->nextchar=0;
return h->ctl[i];
- case '+':
- if (inv)
- return h->ctl[i];
- break;
- case '-':
- if (!inv)
- return h->ctl[i];
- break;
- case ':':
- break;
- }
- /* need optarg */
- if (h->nextarg >= h->argc)
- return BAD_FLAG;
- if (opt)
- *opt = h->argv[h->nextarg] + h->nextchar;
- h->nextarg++;
- h->nextchar=0;
- return h->ctl[i];
}
/* broadcast a string on all interfaces, to udp_port(); */
-
+
#include <sys/types.h>
#include <unistd.h>
#include <sys/socket.h>
static void sendaddr(struct sockaddr_in addr, char *packet)
{
- addr.sin_port = udp_port();
- addr.sin_family = AF_INET;
+ addr.sin_port = udp_port();
+ addr.sin_family = AF_INET;
- sendto(sock, packet, strlen(packet), 0, (struct sockaddr *)&addr, sizeof(addr));
+ sendto(sock, packet, strlen(packet), 0, (struct sockaddr *)&addr, sizeof(addr));
}
static void sendinter(int n, char *packet)
{
- struct ifreq ifr;
+ struct ifreq ifr;
- ifr = iflist.ifc_req[n];
+ ifr = iflist.ifc_req[n];
/* printf("interface = %s\n", ifr.ifr_name); */
- ioctl(sock, SIOCGIFBRDADDR, &ifr);
- sendaddr(*(struct sockaddr_in*)&ifr.ifr_broadaddr, packet);
+ ioctl(sock, SIOCGIFBRDADDR, &ifr);
+ sendaddr(*(struct sockaddr_in*)&ifr.ifr_broadaddr, packet);
}
void broadcast(char *packet)
{
- int n;
- int port;
- struct sockaddr_in myaddr;
- int a = -1;
+ int n;
+ int port;
+ struct sockaddr_in myaddr;
+ int a = -1;
- sock = socket(AF_INET, SOCK_DGRAM, 0);
- setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char*)&a, 4);
- memset(&myaddr, 0, sizeof(myaddr));
- myaddr.sin_family = AF_INET;
- if (geteuid()==0)
- port = 1023;
- else
- port = 10230;
- myaddr.sin_port = htons(port);
- while (bind(sock, (struct sockaddr *)&myaddr, sizeof(myaddr))== -1) myaddr.sin_port = htons(--port);
- if (ifconfinit()!= -1) /* gets list of interfaces */
- for (n = 0 ; n < interfaces ; n++)
- sendinter(n, packet);
+ sock = socket(AF_INET, SOCK_DGRAM, 0);
+ setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char*)&a, 4);
+ memset(&myaddr, 0, sizeof(myaddr));
+ myaddr.sin_family = AF_INET;
+ if (geteuid()==0)
+ port = 1023;
+ else
+ port = 10230;
+ myaddr.sin_port = htons(port);
+ while (bind(sock, (struct sockaddr *)&myaddr, sizeof(myaddr))== -1) myaddr.sin_port = htons(--port);
+ if (ifconfinit()!= -1) /* gets list of interfaces */
+ for (n = 0 ; n < interfaces ; n++)
+ sendinter(n, packet);
}
extern struct class daemon_class;
extern struct class stream_class;
static struct class *classes[] = {
- &daemon_class, &stream_class, NULL
- };
+ &daemon_class,
+ &stream_class,
+ NULL
+};
class_t find_class(char *name)
{
- int c;
- for (c=0 ; classes[c] ; c++)
- if (strccmp(name, classes[c]->class)==0)
- return classes[c];
- return NULL;
+ int c;
+ for (c=0 ; classes[c] ; c++)
+ if (strcasecmp(name, classes[c]->class)==0)
+ return classes[c];
+ return NULL;
}
static char *gather_arg(char **args)
{
- char *line;
- int len = 0;
- int a;
- for (a=0 ; args[a] ; a++) len += strlen(args[a])+1;
- line = (char*)malloc(len+1);
- len = 0;
- for (a=0 ; args[a] ; a++)
- {
- strcpy(line+len, args[a]);
- len += strlen(args[a]);
- line[len++] = ' ';
- }
- if (len>0)
- line[len-1] = '\0';
- else
- line[len] = 0;
- return line;
+ char *line;
+ int len = 0;
+ int a;
+ for (a=0 ; args[a] ; a++) len += strlen(args[a])+1;
+ line = (char*)malloc(len+1);
+ len = 0;
+ for (a=0 ; args[a] ; a++)
+ {
+ strcpy(line+len, args[a]);
+ len += strlen(args[a]);
+ line[len++] = ' ';
+ }
+ if (len>0)
+ line[len-1] = '\0';
+ else
+ line[len] = 0;
+ return line;
}
static void do_version(char **args, char *host, void *con)
{
- char *rv;
-
- if (con)
- {
- extern char version[];
- rv = (char*)malloc(strlen(version)+2);
- strcpy(rv+1, version);
- rv[0] = 2;
- set_reply(con, rv, strlen(version)+2);
- }
-
+ char *rv;
+
+ if (con)
+ {
+ extern char version[];
+ rv = (char*)malloc(strlen(version)+2);
+ strcpy(rv+1, version);
+ rv[0] = 2;
+ set_reply(con, rv, strlen(version)+2);
+ }
}
static void do_broad(char **args, char *host, void *con)
{
- /* remaining args are packaged up and broadcast on all interfaces */
- char *line;
- line = gather_arg(args+1);
- logmsg(LOG_INFO, "Broadcast request from %s for %s", host, line);
- broadcast(line);
- free(line);
+ /* remaining args are packaged up and broadcast on all interfaces */
+ char *line;
+ line = gather_arg(args+1);
+ logmsg(LOG_INFO, "Broadcast request from %s for %s", host, line);
+ broadcast(line);
+ free(line);
}
static void do_die(char **args, char *host, void *con)
{
- logmsg(LOG_WARNING, "Die request from %s", host);
- exit(1); /* FIXME */
+ logmsg(LOG_WARNING, "Die request from %s", host);
+ exit(1); /* FIXME */
}
static void do_disable(char **args, char *host, void *con)
{
- service_t sv;
- if (args[1] == NULL)
- return_error(con, "No service given for disabling");
- else if ((sv=find_service(args[1]))==NULL)
- return_error(con, "Cannot find service %s to disable it", args[1]);
- else for ( ; sv ; sv=find_service(NULL))
- if (sv->enabled)
- {
- logmsg(LOG_INFO, "Disable request from %s for %s", host, sv->service);
- (sv->class->disable_service)(sv);
- sv->enabled = 0;
- }
+ service_t sv;
+ if (args[1] == NULL)
+ return_error(con, "No service given for disabling");
+ else if ((sv=find_service(args[1]))==NULL)
+ return_error(con, "Cannot find service %s to disable it", args[1]);
+ else for ( ; sv ; sv=find_service(NULL))
+ if (sv->enabled)
+ {
+ logmsg(LOG_INFO, "Disable request from %s for %s", host, sv->service);
+ (sv->class->disable_service)(sv);
+ sv->enabled = 0;
+ }
}
static void do_enable(char **args, char *host, void *con)
{
- service_t sv;
- if (args[1] == NULL)
- return_error(con, "No service given for enabling");
- else if ((sv=find_service(args[1]))==NULL)
- return_error(con, "Cannot find service %s to enable it", args[1]);
- else for ( ; sv ; sv=find_service(NULL))
- if (!sv->enabled)
- {
- logmsg(LOG_INFO, "Enable request from %s for %s", host, sv->service);
- (sv->class->register_service)(sv);
- sv->enabled = 1;
- }
+ service_t sv;
+ if (args[1] == NULL)
+ return_error(con, "No service given for enabling");
+ else if ((sv=find_service(args[1]))==NULL)
+ return_error(con, "Cannot find service %s to enable it", args[1]);
+ else for ( ; sv ; sv=find_service(NULL))
+ if (!sv->enabled)
+ {
+ logmsg(LOG_INFO, "Enable request from %s for %s", host, sv->service);
+ (sv->class->register_service)(sv);
+ sv->enabled = 1;
+ }
}
static void do_run(char **args, char *host, void *con)
{
- /* attempt to run service called args[1] with METAD_ARG set to remaining args and METAD_HOST set to host
- */
- service_t sv;
- if (args[1] == NULL)
- return_error(con, "No service given to run");
- else if ((sv=find_service(args[1]))==NULL)
- return_error(con, "Cannot find service %s to run", args[1]);
- else
- {
- char *env[3];
- char *arg = gather_arg(args+2);
- env[0] = strcat(strcpy((char*)malloc(20+strlen(host)), "METAD_REASON=run:"), host);
- env[1] = strcat(strcpy((char*)malloc(11+strlen(arg)), "METAD_ARG="), arg);
- env[2] = NULL;
- for ( ; sv ; sv = find_service(NULL))
+ /* attempt to run service called args[1] with METAD_ARG set to remaining args and METAD_HOST set to host
+ */
+ service_t sv;
+ if (args[1] == NULL)
+ return_error(con, "No service given to run");
+ else if ((sv=find_service(args[1]))==NULL)
+ return_error(con, "Cannot find service %s to run", args[1]);
+ else
{
- /* first clear all hold-times */
- proc_t *pp;
- for (pp=skip_first(sv->proc_list) ; pp ; pp=skip_next(pp))
- if ((*pp)->hold_time != 0)
- (*pp)->hold_time = 1;
- sv->next_hold = 2;
- logmsg(LOG_INFO,"starting %s for %s : arg = %s", sv->service, host, arg);
- new_proc(sv, env);
+ char *env[3];
+ char *arg = gather_arg(args+2);
+ env[0] = strcat(strcpy((char*)malloc(20+strlen(host)), "METAD_REASON=run:"), host);
+ env[1] = strcat(strcpy((char*)malloc(11+strlen(arg)), "METAD_ARG="), arg);
+ env[2] = NULL;
+ for ( ; sv ; sv = find_service(NULL))
+ {
+ /* first clear all hold-times */
+ proc_t *pp;
+ for (pp=skip_first(sv->proc_list) ; pp ; pp=skip_next(pp))
+ if ((*pp)->hold_time != 0)
+ (*pp)->hold_time = 1;
+ sv->next_hold = 2;
+ logmsg(LOG_INFO,"starting %s for %s : arg = %s", sv->service, host, arg);
+ new_proc(sv, env);
+ }
+ free(arg);
+ free(env[1]);
+ free(env[0]);
}
- free(arg);
- free(env[1]);
- free(env[0]);
- }
}
static void do_kill(char **args, char *host, void *con)
{
- /* args[1] = signal
- * args[2] = pid or service name
- */
- int sig;
- pid_t pid;
- service_t sv;
- if (args[1] == NULL)
- return_error(con, "No signal number given for kill");
- else if ((sig=atoi(args[1]))<= 0)
- return_error(con, "Bad signal number given for kill: %s", args[1]);
- else if (args[2] == NULL)
- return_error(con, "No process id or service name given for kill");
- else if ((pid = atoi(args[2]))>0)
- {
- proc_t *pp = skip_search(allprocs, &pid);
- if (pp)
+ /* args[1] = signal
+ * args[2] = pid or service name
+ */
+ int sig;
+ pid_t pid;
+ service_t sv;
+ if (args[1] == NULL)
+ return_error(con, "No signal number given for kill");
+ else if ((sig=atoi(args[1]))<= 0)
+ return_error(con, "Bad signal number given for kill: %s", args[1]);
+ else if (args[2] == NULL)
+ return_error(con, "No process id or service name given for kill");
+ else if ((pid = atoi(args[2]))>0)
{
- logmsg(LOG_INFO, "killing %s for %s", args[2], host);
- if ((*pp)->exit_time == 0)
- kill((*pp)->pid, sig);
- else if ((*pp)->it_forked > 1)
- kill((*pp)->it_forked, sig);
+ proc_t *pp = skip_search(allprocs, &pid);
+ if (pp)
+ {
+ logmsg(LOG_INFO, "killing %s for %s", args[2], host);
+ if ((*pp)->exit_time == 0)
+ kill((*pp)->pid, sig);
+ else if ((*pp)->it_forked > 1)
+ kill((*pp)->it_forked, sig);
+ }
+ else
+ return_error(con, "Cannot find process %s to kill", args[2]);
}
- else
- return_error(con, "Cannot find process %s to kill", args[2]);
- }
- else if ((sv = find_service(args[2]))!= NULL)
- {
- for ( ; sv ; sv = find_service(NULL))
+ else if ((sv = find_service(args[2]))!= NULL)
{
- proc_t *pp;
- for (pp = skip_first(sv->proc_list) ; pp ; pp = skip_next(pp))
- if ((*pp)->exit_time == 0 || (*pp)->it_forked)
+ for ( ; sv ; sv = find_service(NULL))
{
- logmsg(LOG_INFO,
- "signalling %s:%d with %d for %s", sv->service,
- (*pp)->exit_time?(*pp)->it_forked:(*pp)->pid,
- sig, host);
- if ((*pp)->exit_time == 0)
- kill((*pp)->pid, sig);
- else if ((*pp)->it_forked > 1)
- kill((*pp)->it_forked, sig);
+ proc_t *pp;
+ for (pp = skip_first(sv->proc_list) ; pp ; pp = skip_next(pp))
+ if ((*pp)->exit_time == 0 || (*pp)->it_forked)
+ {
+ logmsg(LOG_INFO,
+ "signalling %s:%d with %d for %s", sv->service,
+ (*pp)->exit_time?(*pp)->it_forked:(*pp)->pid,
+ sig, host);
+ if ((*pp)->exit_time == 0)
+ kill((*pp)->pid, sig);
+ else if ((*pp)->it_forked > 1)
+ kill((*pp)->it_forked, sig);
+ }
}
}
- }
- else
- return_error(con, "Cannot find service %s to kill", args[2]);
+ else
+ return_error(con, "Cannot find service %s to kill", args[2]);
}
static void do_reread(char **args, char *host, void *con)
{
- char *errs = NULL;
- int old;
- logmsg(LOG_INFO, "Rereading config file for %s", host);
- old= errors_to(ERROR_STRING, &errs);
- if (read_config(services, NULL) != 0)
- return_error(con, "%s", errs);
- errors_to(old, NULL);
- if (errs) free(errs);
+ char *errs = NULL;
+ int old;
+ logmsg(LOG_INFO, "Rereading config file for %s", host);
+ old= errors_to(ERROR_STRING, &errs);
+ if (read_config(services, NULL) != 0)
+ return_error(con, "%s", errs);
+ errors_to(old, NULL);
+ if (errs) free(errs);
}
static void do_list(char **args, char *host, void *con)
{
- service_t sv, *svp;
- init_return();
- send_byte(3); /* listing */
- if (args[1] == NULL)
- {
- for (svp = skip_first(services) ; svp ; svp = skip_next(svp))
+ service_t sv, *svp;
+ init_return();
+ send_byte(3); /* listing */
+ if (args[1] == NULL)
+ {
+ for (svp = skip_first(services) ; svp ; svp = skip_next(svp))
+ {
+ send_service(*svp);
+ }
+ send_byte(0); /* finished */
+ do_send(con);
+ }
+ else if ((sv=find_service(args[1])) != NULL)
{
- send_service(*svp);
+ for ( ; sv ; sv = find_service(NULL))
+ send_service(sv);
+ send_byte(0);
+ do_send(con);
}
- send_byte(0); /* finished */
- do_send(con);
- }
- else if ((sv=find_service(args[1])) != NULL)
- {
- for ( ; sv ; sv = find_service(NULL))
- send_service(sv);
- send_byte(0);
- do_send(con);
- }
- else
- return_error(con, "Cannot find service %s to list", args[1]);
+ else
+ return_error(con, "Cannot find service %s to list", args[1]);
}
void do_restart(char **args, char *host, void *con)
{
- logmsg(LOG_INFO, "About to restart for %s", host);
- control_close();
- prepare_restart();
- restart();
- exit(0);
+ logmsg(LOG_INFO, "About to restart for %s", host);
+ control_close();
+ prepare_restart();
+ restart();
+ exit(0);
}
-
static struct commands cmds[] = {
- { "list", do_list },
- { "version",do_version },
- { "broad", do_broad },
- { "die", do_die },
- { "disable",do_disable},
- { "enable", do_enable},
- { "kick", do_run},
- { "run", do_run},
- { "kill", do_kill},
- { "reread", do_reread},
- { "restart", do_restart},
- { NULL, NULL}
- };
+ { "list", do_list },
+ { "version",do_version },
+ { "broad", do_broad },
+ { "die", do_die },
+ { "disable",do_disable},
+ { "enable", do_enable},
+ { "kick", do_run},
+ { "run", do_run},
+ { "kill", do_kill},
+ { "reread", do_reread},
+ { "restart", do_restart},
+ { NULL, NULL}
+};
int do_command(char **args, char *host, void *con)
{
- int cmd = 0;
- for (cmd = 0; cmds[cmd].name ; cmd++)
- if (strccmp(cmds[cmd].name, args[0])==0)
- break;
- if (cmds[cmd].name)
- {
- (cmds[cmd].proc)(args, host, con);
- return 1;
- }
- else
- return 0;
+ int cmd = 0;
+ for (cmd = 0; cmds[cmd].name ; cmd++)
+ if (strcasecmp(cmds[cmd].name, args[0])==0)
+ break;
+ if (cmds[cmd].name)
+ {
+ (cmds[cmd].proc)(args, host, con);
+ return 1;
+ }
+ else
+ return 0;
}
static int tcp_listen;
static struct tcpcon {
- int sock;
- char buf[1024]; /*for incoming command */
- char host[1024]; /* host connection is from */
- int buflen; /* how much has been read */
- char *outbuf; /* outgoing data */
- int outlen; /* size of outgoing data */
- int outpos; /* how much sent so far */
- time_t connect_time;/* when the connection was established */
+ int sock;
+ char buf[1024]; /*for incoming command */
+ char host[1024]; /* host connection is from */
+ int buflen; /* how much has been read */
+ char *outbuf; /* outgoing data */
+ int outlen; /* size of outgoing data */
+ int outpos; /* how much sent so far */
+ time_t connect_time;/* when the connection was established */
} tcpcon;
void return_error(struct tcpcon *con, char *fmt, char *a, char *b, char *c)
{
- char buf[1024];
- char *rv;
- extern char version[];
- if (con)
- {
- sprintf(buf, fmt, a, b, c);
- sprintf(buf+strlen(buf), " (metad version %s)", version);
- rv = (char*)malloc(strlen(buf)+2);
- strcpy(rv+1, buf);
- rv[0]= 1;
- con->outbuf = rv;
- con->outlen = strlen(buf)+2;
- con->outpos = 0;
- }
+ char buf[1024];
+ char *rv;
+ extern char version[];
+ if (con)
+ {
+ sprintf(buf, fmt, a, b, c);
+ sprintf(buf+strlen(buf), " (metad version %s)", version);
+ rv = (char*)malloc(strlen(buf)+2);
+ strcpy(rv+1, buf);
+ rv[0]= 1;
+ con->outbuf = rv;
+ con->outlen = strlen(buf)+2;
+ con->outpos = 0;
+ }
}
static int address_ok(struct sockaddr_in *sa, char *host)
{
- struct hostent *he;
- int len;
- int a;
- static char *tail = ".cse.unsw.edu.au";
+ struct hostent *he;
+ int len;
+ int a;
+ static char *tail = ".cse.unsw.edu.au";
- if (ntohs(sa->sin_port) >= 1024 && geteuid() == 0)
- return 0;
- if (sa->sin_addr.s_addr == htonl(0x7f000001))
- {
- strcpy(host, "localhost");
- return 1; /* localhost */
- }
- he = gethostbyaddr((char*)&sa->sin_addr, 4, AF_INET);
- if (he == NULL)
- return 0;
- strcpy(host, he->h_name);
- he = gethostbyname(host);
- if (he == NULL)
- return 0;
- for (a=0; he->h_addr_list[a] ; a++)
- if (memcmp(&sa->sin_addr, he->h_addr_list[a], 4)==0)
+ if (ntohs(sa->sin_port) >= 1024 && geteuid() == 0)
+ return 0;
+ if (sa->sin_addr.s_addr == htonl(0x7f000001))
{
- /* well, we have a believeable name */
-
- len = strlen(host);
- if (len > strlen(tail) && strccmp(tail, host+len - strlen(tail))== 0)
- return 1;
- return 0;
+ strcpy(host, "localhost");
+ return 1; /* localhost */
}
- return 0;
+ he = gethostbyaddr((char*)&sa->sin_addr, 4, AF_INET);
+ if (he == NULL)
+ return 0;
+ strcpy(host, he->h_name);
+ he = gethostbyname(host);
+ if (he == NULL)
+ return 0;
+ for (a=0; he->h_addr_list[a] ; a++)
+ if (memcmp(&sa->sin_addr, he->h_addr_list[a], 4)==0)
+ {
+ /* well, we have a believeable name */
+
+ len = strlen(host);
+ if (len > strlen(tail) && strcasecmp(tail, host+len - strlen(tail))== 0)
+ return 1;
+ return 0;
+ }
+ return 0;
}
static void run_command(char *buf, char *host, struct tcpcon *con)
{
- char *cp;
- char **words, **wp;
+ char *cp;
+ char **words, **wp;
- for (cp= buf; *cp ; cp++)
- {
- if (*cp == '\r' || *cp == '\n') *cp = 0;
- }
- wp = words = strsplit(buf, " ");
- if (isdigit(wp[0][0]))
- wp++; /* old gossip put a port number at the start for return info */
- if (!do_command(wp, host, con))
- {
- /* possibly return error */
- if (con)
- return_error(con, "unknown command %s", wp[0], NULL, NULL);
- }
+ for (cp= buf; *cp ; cp++)
+ {
+ if (*cp == '\r' || *cp == '\n') *cp = 0;
+ }
+ wp = words = strsplit(buf, " ");
+ if (isdigit(wp[0][0]))
+ wp++; /* old gossip put a port number at the start for return info */
+ if (!do_command(wp, host, con))
+ {
+ /* possibly return error */
+ if (con)
+ return_error(con, "unknown command %s", wp[0], NULL, NULL);
+ }
}
void nodelay(int socket)
{
- int f;
- f = fcntl(socket, F_GETFL, 0);
- fcntl(socket, F_SETFL, f|O_NDELAY);
- fcntl(socket, F_SETFD, 1); /* set close-on-exec */
+ int f;
+ f = fcntl(socket, F_GETFL, 0);
+ fcntl(socket, F_SETFL, f|O_NDELAY);
+ fcntl(socket, F_SETFD, 1); /* set close-on-exec */
}
int control_init()
{
- udp_sock = socket(AF_INET, SOCK_DGRAM, 0);
- if (udp_sock >= 0)
- {
- struct sockaddr_in sa;
- memset(&sa, 0, sizeof(sa));
- sa.sin_family = AF_INET;
- sa.sin_port = udp_port();
- nodelay(udp_sock);
- if (bind(udp_sock, (struct sockaddr *)&sa, sizeof(sa)) != 0)
+ udp_sock = socket(AF_INET, SOCK_DGRAM, 0);
+ if (udp_sock >= 0)
+ {
+ struct sockaddr_in sa;
+ memset(&sa, 0, sizeof(sa));
+ sa.sin_family = AF_INET;
+ sa.sin_port = udp_port();
+ nodelay(udp_sock);
+ if (bind(udp_sock, (struct sockaddr *)&sa, sizeof(sa)) != 0)
+ {
+ error("cannot bind udp port");
+ return -1;
+ }
+ }
+ else
+ {
+ error("cannot create udp socket");
+ return -1;
+ }
+ tcp_listen = socket(AF_INET, SOCK_STREAM, 0);
+ if (tcp_listen >= 0)
{
- error("cannot bind udp port");
- return -1;
+ struct sockaddr_in sa;
+ int i = 1;
+ nodelay(tcp_listen);
+ memset(&sa, 0, sizeof(sa));
+ sa.sin_family = AF_INET;
+ sa.sin_port = tcp_port();
+ setsockopt(tcp_listen, SOL_SOCKET, SO_REUSEADDR, (char*)&i, 4);
+ if (bind(tcp_listen, (struct sockaddr *)&sa, sizeof(sa)) != 0)
+ {
+ error("cannot bind tcp port");
+ return -1;
+ }
+ listen(tcp_listen, 5);
}
- }
- else
- {
- error("cannot create udp socket");
- return -1;
- }
- tcp_listen = socket(AF_INET, SOCK_STREAM, 0);
- if (tcp_listen >= 0)
- {
- struct sockaddr_in sa;
- int i = 1;
- nodelay(tcp_listen);
- memset(&sa, 0, sizeof(sa));
- sa.sin_family = AF_INET;
- sa.sin_port = tcp_port();
- setsockopt(tcp_listen, SOL_SOCKET, SO_REUSEADDR, (char*)&i, 4);
- if (bind(tcp_listen, (struct sockaddr *)&sa, sizeof(sa)) != 0)
+ else
{
- error("cannot bind tcp port");
- return -1;
+ error("Cannot create tcp socket");
+ return -1;
}
- listen(tcp_listen, 5);
- }
- else
- {
- error("Cannot create tcp socket");
- return -1;
- }
- tcpcon.sock = -1;
- return 0;
+ tcpcon.sock = -1;
+ return 0;
}
void control_close(void)
{
- close(tcp_listen);
- close(udp_sock);
- close(tcpcon.sock);
+ close(tcp_listen);
+ close(udp_sock);
+ close(tcpcon.sock);
}
void check_control(void)
{
- /* first check udp */
- if (readyon(udp_sock))
- {
- char buf[1024];
- char host[1024];
- int n;
- struct sockaddr_in sa;
- unsigned int salen = sizeof(sa);
- n = recvfrom(udp_sock, buf, sizeof(buf)-1, 0, (struct sockaddr *)&sa, &salen );
- if (n>0 && address_ok(&sa, host))
+ /* first check udp */
+ if (readyon(udp_sock))
{
- buf[n] = 0;
- run_command(buf, host, NULL);
+ char buf[1024];
+ char host[1024];
+ int n;
+ struct sockaddr_in sa;
+ unsigned int salen = sizeof(sa);
+ n = recvfrom(udp_sock, buf, sizeof(buf)-1, 0, (struct sockaddr *)&sa, &salen );
+ if (n>0 && address_ok(&sa, host))
+ {
+ buf[n] = 0;
+ run_command(buf, host, NULL);
+ }
}
- }
- listenon(udp_sock);
+ listenon(udp_sock);
- /* then check tcpcon or tcp_listen */
- if (tcpcon.sock != -1)
- {
- time_t now;
- time(&now);
- if (tcpcon.connect_time + 120 < now)
- {
- /* just give up */
- close(tcpcon.sock);
- tcpcon.sock = -1;
- if (tcpcon.outbuf) free(tcpcon.outbuf);
- tcpcon.outbuf = NULL;
- listenon(tcp_listen);
- }
- else if (tcpcon.outbuf)
+ /* then check tcpcon or tcp_listen */
+ if (tcpcon.sock != -1)
{
- if (canwrite(tcpcon.sock) && tcpcon.outpos < tcpcon.outlen)
- {
- int l = tcpcon.outlen - tcpcon.outpos;
- if (l>1024) l = 1024;
- l = write(tcpcon.sock, tcpcon.outbuf+tcpcon.outpos, l);
- if (l< 0)
- {
- close(tcpcon.sock); tcpcon.sock = -1; free(tcpcon.outbuf);
- tcpcon.outbuf = NULL;
- }
- else
- tcpcon.outpos += l;
- if (tcpcon.outpos >= tcpcon.outlen)
+ time_t now;
+ time(&now);
+ if (tcpcon.connect_time + 120 < now)
{
- close(tcpcon.sock); tcpcon.sock = -1; free(tcpcon.outbuf);
- tcpcon.outbuf = NULL;
+ /* just give up */
+ close(tcpcon.sock);
+ tcpcon.sock = -1;
+ if (tcpcon.outbuf) free(tcpcon.outbuf);
+ tcpcon.outbuf = NULL;
+ listenon(tcp_listen);
}
- }
- if (tcpcon.sock == -1)
- listenon(tcp_listen);
- else
- writeon(tcpcon.sock);
- }
- else /* we are still reading a command */
- {
- if (readyon(tcpcon.sock))
- {
- int l = sizeof(tcpcon.buf) - tcpcon.buflen;
- l = read(tcpcon.sock, tcpcon.buf+tcpcon.buflen, l-1);
- if (l<0)
+ else if (tcpcon.outbuf)
{
- close(tcpcon.sock); tcpcon.sock = -1;
+ if (canwrite(tcpcon.sock) && tcpcon.outpos < tcpcon.outlen)
+ {
+ int l = tcpcon.outlen - tcpcon.outpos;
+ if (l>1024) l = 1024;
+ l = write(tcpcon.sock, tcpcon.outbuf+tcpcon.outpos, l);
+ if (l< 0)
+ {
+ close(tcpcon.sock); tcpcon.sock = -1; free(tcpcon.outbuf);
+ tcpcon.outbuf = NULL;
+ }
+ else
+ tcpcon.outpos += l;
+ if (tcpcon.outpos >= tcpcon.outlen)
+ {
+ close(tcpcon.sock); tcpcon.sock = -1; free(tcpcon.outbuf);
+ tcpcon.outbuf = NULL;
+ }
+ }
+ if (tcpcon.sock == -1)
+ listenon(tcp_listen);
+ else
+ writeon(tcpcon.sock);
}
- else
+ else /* we are still reading a command */
{
- tcpcon.buf[l] = 0;
- if (l == 0 || strchr(tcpcon.buf, '\n') || strchr(tcpcon.buf, '\r') || strlen(tcpcon.buf) < l)
- {
- run_command(tcpcon.buf, tcpcon.host, &tcpcon);
- if (tcpcon.outbuf == NULL)
+ if (readyon(tcpcon.sock))
{
- tcpcon.outbuf = malloc(1);
- tcpcon.outbuf[0] = 0;
- tcpcon.outlen = 1;
- tcpcon.outpos = 0;
+ int l = sizeof(tcpcon.buf) - tcpcon.buflen;
+ l = read(tcpcon.sock, tcpcon.buf+tcpcon.buflen, l-1);
+ if (l<0)
+ {
+ close(tcpcon.sock); tcpcon.sock = -1;
+ }
+ else
+ {
+ tcpcon.buf[l] = 0;
+ if (l == 0 || strchr(tcpcon.buf, '\n') || strchr(tcpcon.buf, '\r') || strlen(tcpcon.buf) < l)
+ {
+ run_command(tcpcon.buf, tcpcon.host, &tcpcon);
+ if (tcpcon.outbuf == NULL)
+ {
+ tcpcon.outbuf = malloc(1);
+ tcpcon.outbuf[0] = 0;
+ tcpcon.outlen = 1;
+ tcpcon.outpos = 0;
+ }
+ }
+ }
}
- }
+ if (tcpcon.sock == -1)
+ listenon(tcp_listen);
+ else if (tcpcon.outbuf)
+ writeon(tcpcon.sock);
+ else
+ listenon(tcpcon.sock);
}
- }
- if (tcpcon.sock == -1)
- listenon(tcp_listen);
- else if (tcpcon.outbuf)
- writeon(tcpcon.sock);
- else
- listenon(tcpcon.sock);
-
}
- }
- else
- {
- if (readyon(tcp_listen))
+ else
{
- struct sockaddr_in sa;
- unsigned int salen = sizeof(sa);
- tcpcon.buflen = 0;
- tcpcon.outbuf = NULL;
- tcpcon.sock = accept(tcp_listen, (struct sockaddr *)&sa, &salen);
- if (tcpcon.sock >= 0)
- {
- nodelay(tcpcon.sock);
- if (address_ok(&sa, tcpcon.host))
- {
- time(&tcpcon.connect_time);
- listenon(tcpcon.sock);
- waituntil(tcpcon.connect_time+122);
- }
- else
+ if (readyon(tcp_listen))
{
- close(tcpcon.sock);
- tcpcon.sock = -1;
+ struct sockaddr_in sa;
+ unsigned int salen = sizeof(sa);
+ tcpcon.buflen = 0;
+ tcpcon.outbuf = NULL;
+ tcpcon.sock = accept(tcp_listen, (struct sockaddr *)&sa, &salen);
+ if (tcpcon.sock >= 0)
+ {
+ nodelay(tcpcon.sock);
+ if (address_ok(&sa, tcpcon.host))
+ {
+ time(&tcpcon.connect_time);
+ listenon(tcpcon.sock);
+ waituntil(tcpcon.connect_time+122);
+ }
+ else
+ {
+ close(tcpcon.sock);
+ tcpcon.sock = -1;
+ }
+ }
}
- }
+ if (tcpcon.sock < 0)
+ listenon(tcp_listen);
}
- if (tcpcon.sock < 0)
- listenon(tcp_listen);
- }
}
void set_reply(struct tcpcon *con, char *reply, int len)
{
- if (con)
- {
- con->outbuf = reply;
- con->outlen = len;
- con->outpos = 0;
- }
- else free(reply);
+ if (con)
+ {
+ con->outbuf = reply;
+ con->outlen = len;
+ con->outpos = 0;
+ }
+ else free(reply);
}
typedef struct daemon_opts
{
- int min;
- int period;
- time_t last_start;
+ int min;
+ int period;
+ time_t last_start;
} *daemon_t;
#define c(sv) ((daemon_t)((sv)->classinfo))
static int daemon_opt(service_t sv, char *opt)
{
- /* understand min= period= */
- if (strncmp(opt, "min=", 4)==0)
- {
- c(sv)->min = atoi(opt+4);
- return 1;
- }
- if (strncmp(opt, "period=", 7) == 0)
- {
- char *cp = opt+7;
- int num = atoi(cp);
- if (num==0) num=1;
- while (isdigit(*cp)) cp++;
- switch(*cp) {
- case 0: break;
- case 's': break;
- case 'm': num *= 60; break;
- case 'h': num *= 3600 ; break;
- case 'd': num *= 24*3600 ; break;
- default: error("bad period specifier, %s", opt); break;
+ /* understand min= period= */
+ if (strncmp(opt, "min=", 4)==0)
+ {
+ c(sv)->min = atoi(opt+4);
+ return 1;
}
- c(sv)->period = num;
- return 1;
- }
- return 0;
+ if (strncmp(opt, "period=", 7) == 0)
+ {
+ char *cp = opt+7;
+ int num = atoi(cp);
+ if (num==0) num=1;
+ while (isdigit(*cp)) cp++;
+ switch(*cp) {
+ case 0: break;
+ case 's': break;
+ case 'm': num *= 60; break;
+ case 'h': num *= 3600 ; break;
+ case 'd': num *= 24*3600 ; break;
+ default: error("bad period specifier, %s", opt); break;
+ }
+ c(sv)->period = num;
+ return 1;
+ }
+ return 0;
}
static void daemon_register(service_t sv)
{
- /* nothing to do.. */
- c(sv)->last_start = 0;
+ /* nothing to do.. */
+ c(sv)->last_start = 0;
}
static void daemon_unregister(service_t sv)
{
- /* nothing to do... */
-
+ /* nothing to do... */
}
static int daemon_prefork(service_t sv)
static void daemon_check(service_t sv)
{
- /* make sure min are running, and watch for next period */
- char *env[3];
- env[0] = "METAD_REASON=min";
- env[1] = "METAD_ARG=";
- env[2] = NULL;
- while (c(sv)->min > 0 && count_procs(sv) < c(sv)->min)
- {
- if (new_proc(sv, env)<=0)
- break;
- }
- if (c(sv)->period > 0 &&
- c(sv)->last_start + c(sv)->period <= time(0))
- {
- env[0] = "METAD_REASON=period";
- new_proc(sv, env);
- c(sv)->last_start = time(0); /* even if it didn't start, we tried */
- }
- if (c(sv)->period > 0)
- waituntil(c(sv)->last_start + c(sv)->period);
+ /* make sure min are running, and watch for next period */
+ char *env[3];
+ env[0] = "METAD_REASON=min";
+ env[1] = "METAD_ARG=";
+ env[2] = NULL;
+ while (c(sv)->min > 0 && count_procs(sv) < c(sv)->min)
+ {
+ if (new_proc(sv, env)<=0)
+ break;
+ }
+ if (c(sv)->period > 0 &&
+ c(sv)->last_start + c(sv)->period <= time(0))
+ {
+ env[0] = "METAD_REASON=period";
+ new_proc(sv, env);
+ c(sv)->last_start = time(0); /* even if it didn't start, we tried */
+ }
+ if (c(sv)->period > 0)
+ waituntil(c(sv)->last_start + c(sv)->period);
}
static void daemon_copy(service_t from, service_t to)
{
- /* copy the classinfo - min and period */
- daemon_t n; // o;
- if (from)
- {
- /* no special state to copy
- * the new service should have parsed its own args
- * - simonb 11nov2003
- */
- //o = from->classinfo;
- //n->min = o->min;
- //n->period = o->period;
- //n->last_start = o->last_start;
- }
- else
- {
- n = (daemon_t)malloc(sizeof(struct daemon_opts));
- n->min = 0;
- n->period = 0;
- n->last_start = 0;
- to->classinfo = n;
- }
+ /* copy the classinfo - min and period */
+ daemon_t n; // o;
+ if (from)
+ {
+ /* no special state to copy
+ * the new service should have parsed its own args
+ * - simonb 11nov2003
+ */
+ //o = from->classinfo;
+ //n->min = o->min;
+ //n->period = o->period;
+ //n->last_start = o->last_start;
+ }
+ else
+ {
+ n = (daemon_t)malloc(sizeof(struct daemon_opts));
+ n->min = 0;
+ n->period = 0;
+ n->last_start = 0;
+ to->classinfo = n;
+ }
}
static void daemon_freestate(service_t sv)
{
- free(sv->classinfo);
+ free(sv->classinfo);
}
static void daemon_send(service_t sv)
{
- /* send min, period, last_start */
- send_byte(1); /* daemon */
- send_int(c(sv)->min);
- send_int(c(sv)->period);
- send_int(c(sv)->last_start);
+ /* send min, period, last_start */
+ send_byte(1); /* daemon */
+ send_int(c(sv)->min);
+ send_int(c(sv)->period);
+ send_int(c(sv)->last_start);
}
-struct class daemon_class =
- { "daemon", daemon_opt, daemon_register, daemon_check,
- daemon_copy, daemon_freestate, daemon_send,
- daemon_unregister, daemon_newparent, daemon_newchild,
- daemon_prefork
- };
+struct class daemon_class = {
+ .class = "daemon",
+ .c_process_opt = daemon_opt,
+ .register_service = daemon_register,
+ .c_check_service= daemon_check,
+ .copy_state = daemon_copy,
+ .free_state = daemon_freestate,
+ .send_class = daemon_send,
+ .disable_service= daemon_unregister,
+ .new_parent = daemon_newparent,
+ .new_child = daemon_newchild,
+ .prefork = daemon_prefork,
+};
void *dl_head()
{
- void *h;
- h = dl_alloc(0);
- dl_next(h) = h;
- dl_prev(h) = h;
- return h;
+ void *h;
+ h = dl_alloc(0);
+ dl_next(h) = h;
+ dl_prev(h) = h;
+ return h;
}
-void dl_free(v)
-void *v;
+void dl_free(void *v)
{
- struct __dl_head *vv = v;
- free(vv-1);
+ struct __dl_head *vv = v;
+ free(vv-1);
}
-void dl_insert(head, val)
-void *head, *val;
+void dl_insert(void *head, void *val)
{
dl_next(val) = dl_next(head);
dl_prev(val) = head;
dl_prev(dl_next(val)) = val;
}
-void dl_add(head, val)
-void *head, *val;
+void dl_add(void *head, void *val)
{
dl_prev(val) = dl_prev(head);
dl_next(val) = head;
dl_prev(dl_next(val)) = val;
}
-void dl_del(val)
-void *val;
+void dl_del(void *val)
{
- if (dl_prev(val) == 0 || dl_next(val) == 0)
- return;
- dl_prev(dl_next(val)) = dl_prev(val);
- dl_next(dl_prev(val)) = dl_next(val);
- dl_prev(val) = dl_next(val) = 0;
+ if (dl_prev(val) == 0 || dl_next(val) == 0)
+ return;
+ dl_prev(dl_next(val)) = dl_prev(val);
+ dl_next(dl_prev(val)) = dl_next(val);
+ dl_prev(val) = dl_next(val) = 0;
}
char *dl_strndup(char *s, int l)
{
- char *n;
- if (s == NULL)
- return NULL;
- n = dl_newv(char, l+1);
- if (n == NULL)
- return NULL;
- else
- {
- strncpy(n, s, l);
- n[l] = 0;
- return n;
- }
+ char *n;
+ if (s == NULL)
+ return NULL;
+ n = dl_newv(char, l+1);
+ if (n == NULL)
+ return NULL;
+ else
+ {
+ strncpy(n, s, l);
+ n[l] = 0;
+ return n;
+ }
}
char *dl_strdup(char *s)
{
- return dl_strndup(s, (int)strlen(s));
+ return dl_strndup(s, (int)strlen(s));
}
int errors_to(int where, char **place)
{
- int rv = error_dest;
- error_dest = where;
- if (where == ERROR_STRING)
- error_str = place;
- if (rv == ERROR_SYSLOG && where != ERROR_SYSLOG)
- closelog();
- if (where == ERROR_SYSLOG && rv != ERROR_SYSLOG)
- {
+ int rv = error_dest;
+ error_dest = where;
+ if (where == ERROR_STRING)
+ error_str = place;
+ if (rv == ERROR_SYSLOG && where != ERROR_SYSLOG)
+ closelog();
+ if (where == ERROR_SYSLOG && rv != ERROR_SYSLOG)
+ {
#ifdef LOG_DAEMON
- openlog("metad", LOG_PID, LOG_DAEMON);
+ openlog("metad", LOG_PID, LOG_DAEMON);
#else
- openlog("metad", 0);
+ openlog("metad", 0);
#endif
- }
- return rv;
+ }
+ return rv;
}
void error(char *mesg, char *a, char *b, char *c)
{
- char buf[1024];
-
- sprintf(buf, mesg, a, b, c);
+ char buf[1024];
- switch(error_dest)
- {
- case ERROR_STDERR:
- fprintf(stderr, "metad: %s\n", buf);
- break;
- case ERROR_STRING:
- if (*error_str == NULL)
- {
- *error_str = (char*)malloc(err_str_len=(strlen(buf)+100));
- strcpy(*error_str, buf);
- }
- else if (strlen(*error_str)+strlen(buf)+1 > err_str_len)
+ sprintf(buf, mesg, a, b, c);
+
+ switch(error_dest)
{
- *error_str = (char*)realloc(*error_str, err_str_len += strlen(buf)+100);
- strcat(*error_str, buf);
+ case ERROR_STDERR:
+ fprintf(stderr, "metad: %s\n", buf);
+ break;
+ case ERROR_STRING:
+ if (*error_str == NULL)
+ {
+ *error_str = (char*)malloc(err_str_len=(strlen(buf)+100));
+ strcpy(*error_str, buf);
+ }
+ else if (strlen(*error_str)+strlen(buf)+1 > err_str_len)
+ {
+ *error_str = (char*)realloc(*error_str, err_str_len += strlen(buf)+100);
+ strcat(*error_str, buf);
+ }
+ else
+ strcat(*error_str, buf);
+ break;
+ case ERROR_SYSLOG:
+ syslog(LOG_ERR, "%s", buf);
+ break;
}
- else
- strcat(*error_str, buf);
- break;
- case ERROR_SYSLOG:
- syslog(LOG_ERR, "%s", buf);
- break;
- }
}
#ifdef STDARGS
va_dcl
#endif
{
- va_list pvar;
- char buf[1024];
- char *format;
+ va_list pvar;
+ char buf[1024];
+ char *format;
#ifdef STDARGS
- va_start(pvar, level);
+ va_start(pvar, level);
#else
- int level;
- va_start(pvar);
- level = va_arg(pvar, int);
+ int level;
+ va_start(pvar);
+ level = va_arg(pvar, int);
#endif
- format = va_arg(pvar, char *);
- vsprintf(buf, format, pvar);
- switch(error_dest)
- {
- case ERROR_STDERR:
- fprintf(stderr, "metad: %s\n", buf);
- break;
- case ERROR_STRING:
- if (*error_str == NULL)
- {
- *error_str = (char*)malloc(err_str_len=(strlen(buf)+100));
- strcpy(*error_str, buf);
- }
- else if (strlen(*error_str)+strlen(buf)+1 > err_str_len)
+ format = va_arg(pvar, char *);
+ vsprintf(buf, format, pvar);
+ switch(error_dest)
{
- *error_str = (char*)realloc(*error_str, err_str_len += strlen(buf)+100);
- strcat(*error_str, buf);
+ case ERROR_STDERR:
+ fprintf(stderr, "metad: %s\n", buf);
+ break;
+ case ERROR_STRING:
+ if (*error_str == NULL)
+ {
+ *error_str = (char*)malloc(err_str_len=(strlen(buf)+100));
+ strcpy(*error_str, buf);
+ }
+ else if (strlen(*error_str)+strlen(buf)+1 > err_str_len)
+ {
+ *error_str = (char*)realloc(*error_str, err_str_len += strlen(buf)+100);
+ strcat(*error_str, buf);
+ }
+ else
+ strcat(*error_str, buf);
+ break;
+ case ERROR_SYSLOG:
+ syslog(level, "%s", buf);
+ break;
}
- else
- strcat(*error_str, buf);
- break;
- case ERROR_SYSLOG:
- syslog(level, "%s", buf);
- break;
- }
-}
+}
void dolog(service_t sv, proc_t p, char *buf)
{
- logmsg(LOG_INFO, "%s: %d: %s\n", sv->service, p->pid, buf);
+ logmsg(LOG_INFO, "%s: %d: %s\n", sv->service, p->pid, buf);
}
char *get_return();
void qfree(char *a)
{
- if (a) free(a);
+ if (a) free(a);
}
void loadstate(int fd)
{
- int len = lseek(fd, 0, 2);
- int b;
- char *buf;
- lseek(fd, 0, 0);
-
- buf = (char*)malloc(len);
- read(fd, buf, len);
- close(fd);
+ int len = lseek(fd, 0, 2);
+ int b;
+ char *buf;
+ lseek(fd, 0, 0);
- init_recv(buf);
- if (get_byte() != 3) return; /* something VERY wrong */
- b = get_byte();
- while(b==1 || b == 2) /* service */
- {
- char *sname;
- int enabled;
- int args;
- int class;
- service_t sv, *svp = NULL;
+ buf = (char*)malloc(len);
+ read(fd, buf, len);
+ close(fd);
- sname = get_str();
- if (sname)
- {
- svp = skip_search(services, sname);
- free(sname);
- }
- get_int(); /* max */
- qfree(get_str()); /* home */
- qfree(get_str()); /* user */
- qfree(get_str()); /* crash */
- if (b == 2)
- {
- get_int(); /* watch_output */
- qfree(get_str()); /* pidfile */
- }
- get_int(); /* cnt */
- enabled = get_int();
- qfree(get_str()); /* prog */
- args = get_int();
- while (args--)
- qfree(get_str());
- class = get_byte();
- switch(class)
- {
- case 1:
- get_int();
- get_int();
- get_int();
- break;
- case 2:
- get_int();
- get_int();
- get_int();
- get_int();
- break;
- }
- if (svp) sv= *svp ;else sv= NULL;
- if (sv) sv->enabled = enabled;
+ init_recv(buf);
+ if (get_byte() != 3) return; /* something VERY wrong */
b = get_byte();
- while (b == 3 || b == 4) /* process */
+ while(b==1 || b == 2) /* service */
{
- int pid, start, xit;
- int forkedpid = 0, pipefd = -1;
- pid = get_int();
- if (b == 4)
- {
- forkedpid = get_int();
- pipefd = get_int();
- }
-
- start = get_int(); /* start */
- get_int(); /* hold */
- xit = get_int();
- get_int(); /* status */
- if ((sv && (xit == 0 && kill(pid, 0)==0)) || (xit>0 && forkedpid>0 && kill(forkedpid,0)==0) )
- {
- proc_t p = (proc_t)malloc(sizeof(struct proc));
- p->pid = pid;
- p->service = sv;
- p->pipefd = pipefd;
- p->bufptr = 0;
- p->it_forked = forkedpid;
- p->is_crash = 0;
- p->start_time = start;
- p->hold_time = xit?1:0;
- p->exit_time = xit;
- skip_insert(sv->proc_list, p);
- skip_insert(allprocs, p);
- }
- b = get_byte();
+ char *sname;
+ int enabled;
+ int args;
+ int class;
+ service_t sv, *svp = NULL;
+
+ sname = get_str();
+ if (sname)
+ {
+ svp = skip_search(services, sname);
+ free(sname);
+ }
+ get_int(); /* max */
+ qfree(get_str()); /* home */
+ qfree(get_str()); /* user */
+ qfree(get_str()); /* crash */
+ if (b == 2)
+ {
+ get_int(); /* watch_output */
+ qfree(get_str()); /* pidfile */
+ }
+ get_int(); /* cnt */
+ enabled = get_int();
+ qfree(get_str()); /* prog */
+ args = get_int();
+ while (args--)
+ qfree(get_str());
+ class = get_byte();
+ switch(class)
+ {
+ case 1:
+ get_int();
+ get_int();
+ get_int();
+ break;
+ case 2:
+ get_int();
+ get_int();
+ get_int();
+ get_int();
+ break;
+ }
+ if (svp) sv= *svp ;else sv= NULL;
+ if (sv) sv->enabled = enabled;
+ b = get_byte();
+ while (b == 3 || b == 4) /* process */
+ {
+ int pid, start, xit;
+ int forkedpid = 0, pipefd = -1;
+ pid = get_int();
+ if (b == 4)
+ {
+ forkedpid = get_int();
+ pipefd = get_int();
+ }
+
+ start = get_int(); /* start */
+ get_int(); /* hold */
+ xit = get_int();
+ get_int(); /* status */
+ if ((sv && (xit == 0 && kill(pid, 0)==0)) || (xit>0 && forkedpid>0 && kill(forkedpid,0)==0) )
+ {
+ proc_t p = (proc_t)malloc(sizeof(struct proc));
+ p->pid = pid;
+ p->service = sv;
+ p->pipefd = pipefd;
+ p->bufptr = 0;
+ p->it_forked = forkedpid;
+ p->is_crash = 0;
+ p->start_time = start;
+ p->hold_time = xit?1:0;
+ p->exit_time = xit;
+ skip_insert(sv->proc_list, p);
+ skip_insert(allprocs, p);
+ }
+ b = get_byte();
+ }
}
- }
- free(buf);
+ free(buf);
}
extern char **gargv;
void restart(void)
{
- int fd;
- int len;
- char *buf;
- service_t *svp;
- char *file = "/var/tmp/...metad-temp-file";
+ int fd;
+ int len;
+ char *buf;
+ service_t *svp;
+ char *file = "/var/tmp/...metad-temp-file";
- fd = open(file, O_RDWR|O_TRUNC|O_CREAT, 0600);
- if (fd < 0)
- {
- close(0);
+ fd = open(file, O_RDWR|O_TRUNC|O_CREAT, 0600);
+ if (fd < 0)
+ {
+ close(0);
+ execv(gargv[2], gargv);
+ exit(1);
+ }
+ unlink(file);
+ init_return();
+ send_byte(3); /* listing */
+ for (svp = skip_first(services) ; svp ; svp = skip_next(svp))
+ {
+ send_service(*svp);
+ }
+ send_byte(0); /* finished */
+
+ buf = get_return(&len);
+ write(fd, buf, len);
+ if (fd > 0)
+ {
+ close(0);
+ dup(fd);
+ close(fd);
+ }
+ gargv[0] = "metad-restart";
execv(gargv[2], gargv);
exit(1);
- }
- unlink(file);
- init_return();
- send_byte(3); /* listing */
- for (svp = skip_first(services) ; svp ; svp = skip_next(svp))
- {
- send_service(*svp);
- }
- send_byte(0); /* finished */
-
- buf = get_return(&len);
- write(fd, buf, len);
- if (fd > 0)
- {
- close(0);
- dup(fd);
- close(fd);
- }
- gargv[0] = "metad-restart";
- execv(gargv[2], gargv);
- exit(1);
}
void listenon(int socket)
{
- FD_SET(socket, &wait_for);
+ FD_SET(socket, &wait_for);
}
int readyon(int socket)
{
- return FD_ISSET(socket, &are_ready);
+ return FD_ISSET(socket, &are_ready);
}
void writeon(int socket)
{
- FD_SET(socket, &write_on);
+ FD_SET(socket, &write_on);
}
int canwrite(int socket)
{
- return FD_ISSET(socket, &can_write);
+ return FD_ISSET(socket, &can_write);
}
void waituntil(time_t when)
{
- if (when_wake == 0 || when_wake > when) when_wake = when;
+ if (when_wake == 0 || when_wake > when) when_wake = when;
}
static struct
{
- pid_t pid;
- int status;
- time_t time;
+ pid_t pid;
+ int status;
+ time_t time;
} saved_pids[20] = { { 0 } };
static struct timeval select_tv;
static void collectchild()
{
- pid_t pid;
- int status;
+ pid_t pid;
+ int status;
- if ((pid = waitpid(-1, &status, WNOHANG)) > 0)
- {
- int i;
- for (i=0; i<20 ; i++)
- if (saved_pids[i].pid == 0)
- {
- saved_pids[i].pid = pid;
- saved_pids[i].status = status;
- time(&saved_pids[i].time);
- break;
- }
- }
- select_tv.tv_usec = 0;
- select_tv.tv_sec = 0;
+ if ((pid = waitpid(-1, &status, WNOHANG)) > 0)
+ {
+ int i;
+ for (i=0; i<20 ; i++)
+ if (saved_pids[i].pid == 0)
+ {
+ saved_pids[i].pid = pid;
+ saved_pids[i].status = status;
+ time(&saved_pids[i].time);
+ break;
+ }
+ }
+ select_tv.tv_usec = 0;
+ select_tv.tv_sec = 0;
}
int is_saved_pid(pid_t pid)
void main_loop()
{
- struct sigaction sa;
- sigset_t ss;
- sa.sa_handler = collectchild;
- sa.sa_flags = 0;
- sigemptyset(&ss);
- sigaddset(&ss, SIGCLD);
- sa.sa_mask = ss;
- sigaction(SIGCLD, &sa, NULL);
-
- FD_ZERO(&are_ready);
- FD_ZERO(&can_write);
- while (1)
- {
- service_t *svp;
- int i;
- FD_ZERO(&wait_for);
- FD_ZERO(&write_on);
- when_wake = time(0)+5*60; /* always wakeup every 5minutes to look around... */
- collectchild(); /* incase signal was missed */
-
- for (i=0 ; i<20 ; i++)
- if (saved_pids[i].pid)
- {
- proc_t *pp;
- pp = skip_search(allprocs, &saved_pids[i].pid);
- if (pp)
- {
- (*pp)->status = saved_pids[i].status;
- (*pp)->exit_time = saved_pids[i].time;;
- select_tv.tv_sec = 0;
- logmsg(LOG_INFO, "process %d (%s) exited - status 0x%04x", saved_pids[i].pid, (*pp)->service->service, (*pp)->status);
- } else
- logmsg(LOG_INFO, "process %d exited - status 0x%04x", saved_pids[i].pid, saved_pids[i].status);
- saved_pids[i].pid = 0;
-
- }
-
- for (svp = skip_first(services) ; svp ; svp = skip_next(svp))
- check_service(*svp);
- check_control();
- are_ready = wait_for;
- can_write = write_on;
-
- if (when_wake)
- {
- time_t now;
- time(&now);
- select_tv.tv_sec = when_wake - now;
- select_tv.tv_usec = 0;
- if (when_wake < now) select_tv.tv_sec = 0;
- }
- else
- {
- select_tv.tv_sec = 100000;
- select_tv.tv_usec = 0;
- }
- if (select(FD_SETSIZE, &are_ready, &can_write, NULL, &select_tv) <= 0)
+ struct sigaction sa;
+ sigset_t ss;
+ sa.sa_handler = collectchild;
+ sa.sa_flags = 0;
+ sigemptyset(&ss);
+ sigaddset(&ss, SIGCLD);
+ sa.sa_mask = ss;
+ sigaction(SIGCLD, &sa, NULL);
+
+ FD_ZERO(&are_ready);
+ FD_ZERO(&can_write);
+ while (1)
{
- FD_ZERO(&are_ready);
- FD_ZERO(&can_write);
+ service_t *svp;
+ int i;
+ FD_ZERO(&wait_for);
+ FD_ZERO(&write_on);
+ when_wake = time(0)+5*60; /* always wakeup every 5minutes to look around... */
+ collectchild(); /* incase signal was missed */
+
+ for (i=0 ; i<20 ; i++)
+ if (saved_pids[i].pid)
+ {
+ proc_t *pp;
+ pp = skip_search(allprocs, &saved_pids[i].pid);
+ if (pp)
+ {
+ (*pp)->status = saved_pids[i].status;
+ (*pp)->exit_time = saved_pids[i].time;;
+ select_tv.tv_sec = 0;
+ logmsg(LOG_INFO, "process %d (%s) exited - status 0x%04x", saved_pids[i].pid, (*pp)->service->service, (*pp)->status);
+ } else
+ logmsg(LOG_INFO, "process %d exited - status 0x%04x", saved_pids[i].pid, saved_pids[i].status);
+ saved_pids[i].pid = 0;
+
+ }
+
+ for (svp = skip_first(services) ; svp ; svp = skip_next(svp))
+ check_service(*svp);
+ check_control();
+ are_ready = wait_for;
+ can_write = write_on;
+
+ if (when_wake)
+ {
+ time_t now;
+ time(&now);
+ select_tv.tv_sec = when_wake - now;
+ select_tv.tv_usec = 0;
+ if (when_wake < now) select_tv.tv_sec = 0;
+ }
+ else
+ {
+ select_tv.tv_sec = 100000;
+ select_tv.tv_usec = 0;
+ }
+ if (select(FD_SETSIZE, &are_ready, &can_write, NULL, &select_tv) <= 0)
+ {
+ FD_ZERO(&are_ready);
+ FD_ZERO(&can_write);
+ }
}
- }
}
void usage(char *fmt, char *arg)
{
- char buf[1024];
- sprintf(buf, fmt, arg);
- fprintf(stderr,"%s: %s\n", progname, buf);
- fprintf(stderr,"Usage: %s -[h?Vubv] -[LRXB] {-[rklDEK] service} [-C command] hostlist ...\n", progname);
+ char buf[1024];
+ sprintf(buf, fmt, arg);
+ fprintf(stderr,"%s: %s\n", progname, buf);
+ fprintf(stderr,"Usage: %s -[h?Vubv] -[LRXB] {-[rklDEK] service} [-C command] hostlist ...\n", progname);
}
void help()
{
- printf(
- "Usage: %s -[h?Vubv] -[LRXB] {-[rklDEK] service} [-C command] hostlist ...\n"
- " -h This help message\n"
- " -? As above\n"
- " -V Print version number of metac and the metad running on any\n"
- " host listed\n"
- " -u Send commands in udp datagrams. This is faster than the\n"
- " normal tcp, but\n"
- " avoids delays on dead machines.\n"
- " -b Send each request as a broadcast on any available network\n"
- " interfaces.\n"
- " -v Be verbose when listing services.\n"
- " -L List all services supported by the metad on the remote host.\n"
- " -R Tell metad to reread it's configuration file.\n"
- " -X Tell metad to eXit.\n"
- " -B Tell the metad to rebroadcast the request on it's\n"
- " interfaces.\n"
- " -r service Try to start a process running for the service.\n"
- " -k service Kick a service into action, same as above.\n"
- " -l service List details of the named service.\n"
- " -D service Disable a service. No more processes will be started for\n"
- " that service.\n"
- " -E service Enable a service. Metad will start processes as\n"
- " appropriate.\n"
- " -K pid Of metad is managing a process with number pid, then it\n"
- " is sent a SIGTERM.\n"
- " -K service Every process running for the given service is sent a\n"
- " SIGTERM.\n"
- " -C command Send the given command (which will usually be quoted).\n"
- " Commands are:\n"
- " run service args like -r, but allows args to be passed to\n"
- " the process.\n"
- " kill signum pid-or-service like -K, but allows a signal number\n"
- " to be given.\n"
- " restart tell metad to re-exec itself, for use when a\n"
- " new version is installed\n"
- " (plus others that duplicate the above flags)\n"
- , progname) ;
+ printf(
+ "Usage: %s -[h?Vubv] -[LRXB] {-[rklDEK] service} [-C command] hostlist ...\n"
+ " -h This help message\n"
+ " -? As above\n"
+ " -V Print version number of metac and the metad running on any\n"
+ " host listed\n"
+ " -u Send commands in udp datagrams. This is faster than the\n"
+ " normal tcp, but\n"
+ " avoids delays on dead machines.\n"
+ " -b Send each request as a broadcast on any available network\n"
+ " interfaces.\n"
+ " -v Be verbose when listing services.\n"
+ " -L List all services supported by the metad on the remote host.\n"
+ " -R Tell metad to reread it's configuration file.\n"
+ " -X Tell metad to eXit.\n"
+ " -B Tell the metad to rebroadcast the request on it's\n"
+ " interfaces.\n"
+ " -r service Try to start a process running for the service.\n"
+ " -k service Kick a service into action, same as above.\n"
+ " -l service List details of the named service.\n"
+ " -D service Disable a service. No more processes will be started for\n"
+ " that service.\n"
+ " -E service Enable a service. Metad will start processes as\n"
+ " appropriate.\n"
+ " -K pid Of metad is managing a process with number pid, then it\n"
+ " is sent a SIGTERM.\n"
+ " -K service Every process running for the given service is sent a\n"
+ " SIGTERM.\n"
+ " -C command Send the given command (which will usually be quoted).\n"
+ " Commands are:\n"
+ " run service args like -r, but allows args to be passed to\n"
+ " the process.\n"
+ " kill signum pid-or-service like -K, but allows a signal number\n"
+ " to be given.\n"
+ " restart tell metad to re-exec itself, for use when a\n"
+ " new version is installed\n"
+ " (plus others that duplicate the above flags)\n"
+ , progname) ;
}
int send_cmd(char *cmd, int udp, char *host, int verbose);
int main(int argc, char *argv[])
{
- void *cmds = dl_head();
- void *hosts = dl_head();
- int local_broad = 0;
- int remote_broad = 0;
- int use_dgram = 0;
- int show_version = 0;
- int show_help = 0;
- int verbose = 0;
- char *c, *c2;
- void *opts = args_init(argc, argv, "??h?V?u?b?r:a:k:l:L?D:E:K:R?X?v?C:B?");
- int opt;
- char *arg;
- int pos, inv;
- progname = strrchr(argv[0], '/');
- if (progname) progname++; else progname = argv[0];
+ void *cmds = dl_head();
+ void *hosts = dl_head();
+ int local_broad = 0;
+ int remote_broad = 0;
+ int use_dgram = 0;
+ int show_version = 0;
+ int show_help = 0;
+ int verbose = 0;
+ char *c, *c2;
+ void *opts = args_init(argc, argv, "??h?V?u?b?r:a:k:l:L?D:E:K:R?X?v?C:B?");
+ int opt;
+ char *arg;
+ int pos, inv;
+ progname = strrchr(argv[0], '/');
+ if (progname) progname++; else progname = argv[0];
- while ((opt = args_next(opts, &pos, &inv, &arg))!= END_ARGS)
- switch(opt)
+ while ((opt = args_next(opts, &pos, &inv, &arg))!= END_ARGS)
+ switch(opt)
+ {
+ case BAD_FLAG:
+ usage("Bad option: %s", argv[pos]);
+ exit(1);
+ case NO_FLAG:
+ c = dl_strdup(arg);
+ dl_add(hosts, c);
+ break;
+ case 'h':
+ case '?':
+ show_help = 1;
+ break;
+ case 'V': /* my version number */
+ printf("%s: version %s\n", progname, version);
+ show_version =1;
+ break;
+ case 'u':
+ use_dgram = 1;
+ break;
+ case 'b':
+ local_broad = 1;
+ break;
+ case 'r':
+ case 'k':
+ c = dl_strndup("kick ", 5+strlen(arg)+1);
+ strcat(c, arg);
+ dl_add(cmds, c);
+ break;
+ case 'a':
+ c = dl_prev(cmds);
+ if (c == cmds || (strncmp(c, "kick ", 5)!= 0 && strncmp(c, "run ", 4)!= 0))
+ {
+ usage("%s: -a only valid after -r or -k", NULL);
+ exit(1);
+ }
+ c2 = dl_strndup(c, strlen(c)+1+strlen(arg)+1);
+ strcat(c2, " ");
+ strcat(c2, arg);
+ dl_del(c); dl_free(c);
+ dl_add(cmds, c2);
+ break;
+ case 'l':
+ c = dl_strndup("list ", 5+strlen(arg)+1);
+ strcat(c, arg);
+ dl_add(cmds, c);
+ break;
+ case 'L':
+ c = dl_strdup("list");
+ dl_add(cmds, c);
+ break;
+ case 'D':
+ c = dl_strndup("disable ", 8+strlen(arg)+1);
+ strcat(c, arg);
+ dl_add(cmds, c);
+ break;
+ case 'E':
+ c = dl_strndup("enable ", 7+strlen(arg)+1);
+ strcat(c, arg);
+ dl_add(cmds, c);
+ break;
+ case 'K':
+ c = dl_strndup("kill 15 ", 8+strlen(arg)+1);
+ strcat(c, arg);
+ dl_add(cmds, c);
+ break;
+ case 'R':
+ c = dl_strdup("reread");
+ dl_add(cmds, c);
+ break;
+ case 'X':
+ c = dl_strdup("die");
+ dl_add(cmds, c);
+ break;
+ case 'v':
+ verbose = 1;
+ break;
+ case 'C':
+ c = dl_strdup(arg);
+ dl_add(cmds, c);
+ break;
+ case 'B':
+ remote_broad = 1;
+ break;
+ }
+
+ if (show_help)
+ {
+ help();
+ exit(0);
+ }
+ if (dl_next(hosts) == hosts && local_broad == 0)
+ {
+ /* no where to send to... */
+ if (dl_next(cmds) != cmds)
+ {
+ fprintf(stderr,"%s: commands were specified with no where to send them!\n", progname);
+ exit(1);
+ }
+ /* nothing to do, though might has displayed version.
+ * Should probably give usage...
+ */
+ if (show_version == 0)
+ usage("Nothing to do", NULL), exit(1);
+ exit(0);
+ }
+ if (dl_next(hosts) != hosts && local_broad)
{
- case BAD_FLAG:
- usage("Bad option: %s", argv[pos]);
- exit(1);
- case NO_FLAG:
- c = dl_strdup(arg);
- dl_add(hosts, c);
- break;
- case 'h':
- case '?':
- show_help = 1;
- break;
- case 'V': /* my version number */
- printf("%s: version %s\n", progname, version);
- show_version =1;
- break;
- case 'u':
- use_dgram = 1;
- break;
- case 'b':
- local_broad = 1;
- break;
- case 'r':
- case 'k':
- c = dl_strndup("kick ", 5+strlen(arg)+1);
- strcat(c, arg);
- dl_add(cmds, c);
- break;
- case 'a':
- c = dl_prev(cmds);
- if (c == cmds || (strncmp(c, "kick ", 5)!= 0 && strncmp(c, "run ", 4)!= 0))
- {
- usage("%s: -a only valid after -r or -k", NULL);
+ fprintf(stderr, "%s: you probably don't want to broadcast AND list hosts...\n", progname);
exit(1);
- }
- c2 = dl_strndup(c, strlen(c)+1+strlen(arg)+1);
- strcat(c2, " ");
- strcat(c2, arg);
- dl_del(c); dl_free(c);
- dl_add(cmds, c2);
- break;
- case 'l':
- c = dl_strndup("list ", 5+strlen(arg)+1);
- strcat(c, arg);
- dl_add(cmds, c);
- break;
- case 'L':
- c = dl_strdup("list");
- dl_add(cmds, c);
- break;
- case 'D':
- c = dl_strndup("disable ", 8+strlen(arg)+1);
- strcat(c, arg);
- dl_add(cmds, c);
- break;
- case 'E':
- c = dl_strndup("enable ", 7+strlen(arg)+1);
- strcat(c, arg);
- dl_add(cmds, c);
- break;
- case 'K':
- c = dl_strndup("kill 15 ", 8+strlen(arg)+1);
- strcat(c, arg);
- dl_add(cmds, c);
- break;
- case 'R':
- c = dl_strdup("reread");
- dl_add(cmds, c);
- break;
- case 'X':
- c = dl_strdup("die");
- dl_add(cmds, c);
- break;
- case 'v':
- verbose = 1;
- break;
- case 'C':
- c = dl_strdup(arg);
- dl_add(cmds, c);
- break;
- case 'B':
- remote_broad = 1;
- break;
}
- if (show_help)
- {
- help();
- exit(0);
- }
- if (dl_next(hosts) == hosts && local_broad == 0)
- {
- /* no where to send to... */
- if (dl_next(cmds) != cmds)
+ if (show_version)
{
- fprintf(stderr,"%s: commands were specified with no where to send them!\n", progname);
- exit(1);
+ c = dl_strdup("version");
+ dl_insert(cmds, c);
}
- /* nothing to do, though might has displayed version.
- * Should probably give usage...
- */
- if (show_version == 0)
- usage("Nothing to do", NULL), exit(1);
- exit(0);
- }
- if (dl_next(hosts) != hosts && local_broad)
- {
- fprintf(stderr, "%s: you probably don't want to broadcast AND list hosts...\n", progname);
- exit(1);
- }
-
- if (show_version)
- {
- c = dl_strdup("version");
- dl_insert(cmds, c);
- }
- for (c= dl_next(cmds) ; c != cmds ; c = dl_next(c))
- {
- char *cmd = (char*)malloc(10 + strlen(c)); /* make sure there is room for port and broad */
- char *h;
-
- strcpy(cmd, "1 ");
- if (remote_broad)
- strcat(cmd, "BROAD ");
- strcat(cmd, c);
- if (local_broad)
- broadcast(cmd);
- else for (h=dl_next(hosts) ; h != hosts ; h = dl_next(h))
+ for (c= dl_next(cmds) ; c != cmds ; c = dl_next(c))
{
- if (strcmp(h, ".")== 0)
- send_cmd(cmd, use_dgram, "localhost", verbose);
- else
- send_cmd(cmd, use_dgram, h, verbose);
+ char *cmd = (char*)malloc(10 + strlen(c)); /* make sure there is room for port and broad */
+ char *h;
+
+ strcpy(cmd, "1 ");
+ if (remote_broad)
+ strcat(cmd, "BROAD ");
+ strcat(cmd, c);
+ if (local_broad)
+ broadcast(cmd);
+ else for (h=dl_next(hosts) ; h != hosts ; h = dl_next(h))
+ {
+ if (strcmp(h, ".")== 0)
+ send_cmd(cmd, use_dgram, "localhost", verbose);
+ else
+ send_cmd(cmd, use_dgram, h, verbose);
+ }
}
- }
- exit(0); /* FIXME what exit status */
+ exit(0); /* FIXME what exit status */
}
int main(int argc, char *argv[])
{
- gargv = argv;
+ gargv = argv;
- {
- int ttyfd = open("/dev/tty", 2, 0);
- if (ttyfd >= 0) {
- ioctl(ttyfd, TIOCNOTTY, NULL);
- close(ttyfd);
+ {
+ int ttyfd = open("/dev/tty", 2, 0);
+ if (ttyfd >= 0) {
+ ioctl(ttyfd, TIOCNOTTY, NULL);
+ close(ttyfd);
+ }
}
- }
- /* FIXME should make sure stdin/stdout/stderr are open to something */
- service_init();
- control_init();
- errors_to(ERROR_SYSLOG, NULL);
- read_config(services, argv[1]);
- if (strcmp(argv[0], "metad-restart")==0) {
- loadstate(0);
- open("/dev/null", O_RDONLY);
- }
- main_loop();
- exit(0);
+ /* FIXME should make sure stdin/stdout/stderr are open to something */
+ service_init();
+ control_init();
+ errors_to(ERROR_SYSLOG, NULL);
+ read_config(services, argv[1]);
+ if (strcmp(argv[0], "metad-restart")==0) {
+ loadstate(0);
+ open("/dev/null", O_RDONLY);
+ }
+ main_loop();
+ exit(0);
}
#include <ctype.h>
#include <signal.h>
/* hold config file info */
-#ifdef ULTRIX
-char *strdup(char*);
-#endif
+
typedef struct service {
- char *service; /* name of service */
- struct class *class; /* pointer to class*/
- void *classinfo; /* class specific options */
- /* class independant options */
-
- int max_proc; /* max number of processes */
- char *crash_prog; /* prog to call when process crashes */
- char *home_dir; /* directory to run process in */
- char *username; /* who to run process as */
- char *pidfile; /* file to read process id from after child exits */
- int watch_output; /* if true, attatch a pipe to std{out,err} and what it */
- int enabled; /* whether to start enabled */
- int start_cnt;
- char *program; /* program to run */
- char **args; /* arguments */
-
- int pending; /* set before reprocessing config file, cleared when found in file */
-
- void *proc_list; /* skiplist of currently active processes */
- time_t next_hold; /* hold time for next crashing processes */
+ char *service; /* name of service */
+ struct class *class; /* pointer to class*/
+ void *classinfo; /* class specific options */
+ /* class independant options */
+
+ int max_proc; /* max number of processes */
+ char *crash_prog; /* prog to call when process crashes */
+ char *home_dir; /* directory to run process in */
+ char *username; /* who to run process as */
+ char *pidfile; /* file to read process id from after child exits */
+ int watch_output; /* if true, attatch a pipe to std{out,err} and what it */
+ int enabled; /* whether to start enabled */
+ int start_cnt;
+ char *program; /* program to run */
+ char **args; /* arguments */
+
+ int pending; /* set before reprocessing config file, cleared when found in file */
+
+ void *proc_list; /* skiplist of currently active processes */
+ time_t next_hold; /* hold time for next crashing processes */
} *service_t;
typedef struct class {
- char *class; /* name of class */
- int (*c_process_opt)(); /* function to processes options */
- void (*register_service)(); /* register the service if necessary */
- void (*c_check_service)(); /* check if anything needs to be done for a service */
- void (*copy_state)(); /* copy state from old service struct to new */
- void (*free_state)(); /* free class dependant state */
- void (*send_class)(); /* send class info */
- void (*disable_service)(); /* unregister service */
- void (*new_parent)(); /* in parent of new child */
- void (*new_child)(); /* in a new child */
- int (*prefork)(); /* just before fork */
+ char *class; /* name of class */
+ int (*c_process_opt)(); /* function to processes options */
+ void (*register_service)(); /* register the service if necessary */
+ void (*c_check_service)(); /* check if anything needs to be done for a service */
+ void (*copy_state)(); /* copy state from old service struct to new */
+ void (*free_state)(); /* free class dependant state */
+ void (*send_class)(); /* send class info */
+ void (*disable_service)(); /* unregister service */
+ void (*new_parent)(); /* in parent of new child */
+ void (*new_child)(); /* in a new child */
+ int (*prefork)(); /* just before fork */
} *class_t;
typedef struct proc {
- pid_t pid; /* pid of process */
- service_t service;
- int pipefd; /* if a pipe was conencted to stdout/stderr */
- char pipebuf[300]; /* buffer lines of data from pipefd before syslogging */
- int bufptr; /* how full buf is */
- int it_forked; /* true if process fork/exited, and we have pid from pidfile */
- int is_crash; /* if cleaning up after core dump */
- time_t start_time; /* when processes started */
- time_t hold_time; /* time to let go of processes slot - set if process crashes early */
- time_t exit_time; /* the time that it exited */
- int status; /* wait status if exit_time > 0 */
+ pid_t pid; /* pid of process */
+ service_t service;
+ int pipefd; /* if a pipe was conencted to stdout/stderr */
+ char pipebuf[300]; /* buffer lines of data from pipefd before syslogging */
+ int bufptr; /* how full buf is */
+ int it_forked; /* true if process fork/exited, and we have pid from pidfile */
+ int is_crash; /* if cleaning up after core dump */
+ time_t start_time; /* when processes started */
+ time_t hold_time; /* time to let go of processes slot - set if process crashes early */
+ time_t exit_time; /* the time that it exited */
+ int status; /* wait status if exit_time > 0 */
} *proc_t;
typedef struct daemon_info { /* class specific info for class "daemon" */
- int min_proc; /* minimum number of processes to have running */
- int period; /* period in seconds for restarts */
+ int min_proc; /* minimum number of processes to have running */
+ int period; /* period in seconds for restarts */
- time_t last_restart; /* last time a periodic restart was attempted */
+ time_t last_restart; /* last time a periodic restart was attempted */
} *daemon_info_t;
typedef struct commands {
- char * name;
- void (*proc)();
+ char * name;
+ void (*proc)();
} *commands_t;
class_t find_class(char *name);
int tcp_port(void);
void nodelay(int socket);
-int strccmp(char*, char*);
#ifndef IN_ERROR
void error(char *mesg,...);
void logmsg(int, char*, ...);
char **strlistdup(char **l);
void strlistfree(char **l);
char **strsplit(char *line, char *sep);
-/*char *strdup(char*);*/
void dolog(service_t, proc_t, char *);
#include "args.h"
struct handle
{
- int argc;
- char **argv;
- char *ctl;
- int nextarg, nextchar;
+ int argc;
+ char **argv;
+ char *ctl;
+ int nextarg, nextchar;
};
struct handle *args_init(int argc, char **argv, char *ctl)
{
- /* if ctl is bad, return NULL, else a handle */
- int i;
- handle *h;
- for (i=0 ; ctl[i]; i+= 2)
- if (ctl[i+1] != '?' && ctl[i+1] != '-' && ctl[i+1] != '+' && ctl[i+1] != ':')
- break;
- if (ctl[i])
- return NULL;
+ /* if ctl is bad, return NULL, else a handle */
+ int i;
+ handle *h;
+ for (i=0 ; ctl[i]; i+= 2)
+ if (ctl[i+1] != '?' && ctl[i+1] != '-' && ctl[i+1] != '+' && ctl[i+1] != ':')
+ break;
+ if (ctl[i])
+ return NULL;
- h = (struct handle*)malloc(sizeof(struct handle));
- if (h == NULL)
+ h = (struct handle*)malloc(sizeof(struct handle));
+ if (h == NULL)
+ return h;
+ h->argc = argc;
+ h->argv = argv;
+ h->ctl = ctl;
+ h->nextarg = 1;
+ h->nextchar = 0;
return h;
- h->argc = argc;
- h->argv = argv;
- h->ctl = ctl;
- h->nextarg = 1;
- h->nextchar = 0;
- return h;
}
int args_next(struct handle *h, int *pos, int *inv, char **opt)
{
- int invc = 0;
- int invfound = 0;
- int i;
- char *a;
- if (h->nextarg >= h->argc)
- return END_ARGS;
- if (h->nextchar == 0)
- {
- if (h->argv[h->nextarg][0] != '-')
+ int invc = 0;
+ int invfound = 0;
+ int i;
+ char *a;
+ if (h->nextarg >= h->argc)
+ return END_ARGS;
+ if (h->nextchar == 0)
{
- if (pos) *pos = h->nextarg;
- if (inv) *inv = 0;
- if (opt) *opt = h->argv[h->nextarg];
- h->nextarg++;
- return NO_FLAG;
+ if (h->argv[h->nextarg][0] != '-')
+ {
+ if (pos) *pos = h->nextarg;
+ if (inv) *inv = 0;
+ if (opt) *opt = h->argv[h->nextarg];
+ h->nextarg++;
+ return NO_FLAG;
+ }
+ h->nextchar++;
+ }
+ a = h->argv[h->nextarg];
+ while (a[h->nextchar] == '~')
+ {
+ invc = !invc;
+ invfound = 1;
+ h->nextchar++;
+ }
+ for (i=0 ; h->ctl[i] ; i+=2)
+ if (h->ctl[i] == a[h->nextchar])
+ break;
+ if (h->ctl[i] == 0)
+ {
+ h->nextchar = 0;
+ h->nextarg ++;
+ return BAD_FLAG;
}
h->nextchar++;
- }
- a = h->argv[h->nextarg];
- while (a[h->nextchar] == '~')
- {
- invc = !invc;
- invfound = 1;
- h->nextchar++;
- }
- for (i=0 ; h->ctl[i] ; i+=2)
- if (h->ctl[i] == a[h->nextchar])
- break;
- if (h->ctl[i] == 0)
- {
- h->nextchar = 0;
- h->nextarg ++;
- return BAD_FLAG;
- }
- h->nextchar++;
- if (pos) *pos = h->nextarg;
- if (inv) *inv = invc;
- if (a[h->nextchar] == 0)
- {
- h->nextchar = 0;
- h->nextarg ++;
- }
- switch(h->ctl[i+1])
- {
- case '?':
+ if (pos) *pos = h->nextarg;
+ if (inv) *inv = invc;
+ if (a[h->nextchar] == 0)
+ {
+ h->nextchar = 0;
+ h->nextarg ++;
+ }
+ switch(h->ctl[i+1])
+ {
+ case '?':
+ return h->ctl[i];
+ case '+':
+ if (inv)
+ return h->ctl[i];
+ break;
+ case '-':
+ if (!inv)
+ return h->ctl[i];
+ break;
+ case ':':
+ break;
+ }
+ /* need optarg */
+ if (h->nextarg >= h->argc)
+ return BAD_FLAG;
+ if (opt)
+ *opt = h->argv[h->nextarg] + h->nextchar;
+ h->nextarg++;
+ h->nextchar=0;
return h->ctl[i];
- case '+':
- if (inv)
- return h->ctl[i];
- break;
- case '-':
- if (!inv)
- return h->ctl[i];
- break;
- case ':':
- break;
- }
- /* need optarg */
- if (h->nextarg >= h->argc)
- return BAD_FLAG;
- if (opt)
- *opt = h->argv[h->nextarg] + h->nextchar;
- h->nextarg++;
- h->nextchar=0;
- return h->ctl[i];
}
int tcp_port()
{
- struct servent *sv;
- if (geteuid() > 0)
- return htons(6110);
- sv = getservbyname("metad","tcp");
- if (sv)
- return sv->s_port;
- else
- return htons(611);
+ struct servent *sv;
+ if (geteuid() > 0)
+ return htons(6110);
+ sv = getservbyname("metad","tcp");
+ if (sv)
+ return sv->s_port;
+ else
+ return htons(611);
}
int udp_port()
{
- struct servent *sv;
- if (geteuid() > 0)
- return htons(6110);
- sv = getservbyname("metad","udp");
- if (sv)
- return sv->s_port;
- else
- return htons(611);
+ struct servent *sv;
+ if (geteuid() > 0)
+ return htons(6110);
+ sv = getservbyname("metad","udp");
+ if (sv)
+ return sv->s_port;
+ else
+ return htons(611);
}
char *prtime(time_t time)
{
-static char tim[9];
+ static char tim[9];
if (time >= WEEKS) {
sprintf(tim,"%4ldw%02ldd", time / WEEKS, (time % WEEKS) / DAYS);
} else if (time >= DAYS) {
char *prticks(time_t ticks)
{
- return prtime(ticks/HZ);
+ return prtime(ticks/HZ);
}
int read_config(void *services, char *file)
{
- service_t *serv;
- char linebuf[1024];
- FILE *f;
- int err = 0;
- static char *lastfile = NULL;
- if (file) lastfile = file;
- else file = lastfile;
-
- for (serv = skip_first(services) ; serv ; serv = skip_next(serv))
- (*serv)->pending = 1;
+ service_t *serv;
+ char linebuf[1024];
+ FILE *f;
+ int err = 0;
+ static char *lastfile = NULL;
+ if (file) lastfile = file;
+ else file = lastfile;
- f = fopen(file, "r");
- if (f == NULL)
- {
- error("cannot find config file %s", file);
- return 1;
- }
- while (fgets(linebuf, sizeof(linebuf), f)!= NULL)
- {
- int len = strlen(linebuf);
- char **words;
- int w;
-
- if (len > 1000 && linebuf[len-1] != '\n')
+ for (serv = skip_first(services) ; serv ; serv = skip_next(serv))
+ (*serv)->pending = 1;
+
+ f = fopen(file, "r");
+ if (f == NULL)
{
- error("line too long in config file");
- fclose(f);
- return 1;
+ error("cannot find config file %s", file);
+ return 1;
}
- if (linebuf[len-1] == '\n') linebuf[--len] = 0;
-
- words = strsplit(linebuf, " \t\n");
- if (words)
+ while (fgets(linebuf, sizeof(linebuf), f)!= NULL)
{
- for (w=0 ;words[w] ; w++) if (words[w][0]=='#') words[w]=NULL;
- if (words[0] && words[1])
- {
- /* not a comment */
- service_t *svp = skip_search(services, words[0]);
- service_t sv;
- class_t cl = find_class(words[1]);
- if (svp != NULL)
- {
- if ((*svp)->class != cl)
- {
- /* different classes - rename old services */
- skip_delete(services, words[0]);
- strcpy(linebuf, words[0]);
- do { strcat(linebuf, ".old"); } while (skip_search(services, linebuf)!= NULL);
- free((*svp)->service);
- (*svp)->service = strdup(linebuf);
- skip_insert(services, *svp);
- svp = NULL;
- }
- }
- if (cl == NULL)
- {
- error("unknown class %s", words[1]);
- err ++;
- continue;
- }
- sv = new_service(words[0], cl);
- /* now process options */
- for (w=2 ; words[w] && words[w][0] != '/' ; w++)
+ int len = strlen(linebuf);
+ char **words;
+ int w;
+
+ if (len > 1000 && linebuf[len-1] != '\n')
{
- int ok = process_opt(sv, words[w]);
- if (ok == 0)
- ok = sv->class->c_process_opt(sv, words[w]);
- if (ok <= 0)
- {
- if (ok == 0)
- error("unknown option: %s", words[w]);
- else
- error("error in option: %s", words[w]);
- free_service(sv);
- sv = NULL;
- err++;
- break;
- }
+ error("line too long in config file");
+ fclose(f);
+ return 1;
}
- if (sv == NULL) continue;
- if (words[w])
- sv->program = strdup(words[w++]);
- if (words[w])
- sv->args = strlistdup(words+w);
- if (sv->program == NULL)
- error("missing program name for service %s", words[0]), err++;
- else if (sv->args == NULL)
- error("missing program arguments for service %s", words[0]), err++;
- else
+ if (linebuf[len-1] == '\n') linebuf[--len] = 0;
+
+ words = strsplit(linebuf, " \t\n");
+ if (words)
{
- if (svp)
- {
- proc_t *pp2;
- service_t sv2 = *svp;
- sv->enabled = sv2->enabled;
- sv->proc_list = sv2->proc_list;
-
- /* change service pointer to the new structure (for aidan) */
- if (sv->proc_list)
- for (pp2 = skip_first(sv->proc_list) ; pp2 ; pp2=skip_next(pp2))
- (*pp2)->service = sv;
-
- sv2->proc_list = NULL;
- sv->class->copy_state(sv2, sv);
- skip_delete(services, sv2->service);
- free_service(sv2);
- }
- skip_insert(services, sv);
- sv->class->register_service(sv);
- sv = NULL;
+ for (w=0 ;words[w] ; w++) if (words[w][0]=='#') words[w]=NULL;
+ if (words[0] && words[1])
+ {
+ /* not a comment */
+ service_t *svp = skip_search(services, words[0]);
+ service_t sv;
+ class_t cl = find_class(words[1]);
+ if (svp != NULL)
+ {
+ if ((*svp)->class != cl)
+ {
+ /* different classes - rename old services */
+ skip_delete(services, words[0]);
+ strcpy(linebuf, words[0]);
+ do { strcat(linebuf, ".old"); } while (skip_search(services, linebuf)!= NULL);
+ free((*svp)->service);
+ (*svp)->service = strdup(linebuf);
+ skip_insert(services, *svp);
+ svp = NULL;
+ }
+ }
+ if (cl == NULL)
+ {
+ error("unknown class %s", words[1]);
+ err ++;
+ continue;
+ }
+ sv = new_service(words[0], cl);
+ /* now process options */
+ for (w=2 ; words[w] && words[w][0] != '/' ; w++)
+ {
+ int ok = process_opt(sv, words[w]);
+ if (ok == 0)
+ ok = sv->class->c_process_opt(sv, words[w]);
+ if (ok <= 0)
+ {
+ if (ok == 0)
+ error("unknown option: %s", words[w]);
+ else
+ error("error in option: %s", words[w]);
+ free_service(sv);
+ sv = NULL;
+ err++;
+ break;
+ }
+ }
+ if (sv == NULL) continue;
+ if (words[w])
+ sv->program = strdup(words[w++]);
+ if (words[w])
+ sv->args = strlistdup(words+w);
+ if (sv->program == NULL)
+ error("missing program name for service %s", words[0]), err++;
+ else if (sv->args == NULL)
+ error("missing program arguments for service %s", words[0]), err++;
+ else
+ {
+ if (svp)
+ {
+ proc_t *pp2;
+ service_t sv2 = *svp;
+ sv->enabled = sv2->enabled;
+ sv->proc_list = sv2->proc_list;
+
+ /* change service pointer to the new structure (for aidan) */
+ if (sv->proc_list)
+ for (pp2 = skip_first(sv->proc_list) ; pp2 ; pp2=skip_next(pp2))
+ (*pp2)->service = sv;
+
+ sv2->proc_list = NULL;
+ sv->class->copy_state(sv2, sv);
+ skip_delete(services, sv2->service);
+ free_service(sv2);
+ }
+ skip_insert(services, sv);
+ sv->class->register_service(sv);
+ sv = NULL;
+ }
+ if (sv) free_service(sv);
+ }
+ free(words[-1]);
+ free(words-1);
}
- if (sv) free_service(sv);
- }
- free(words[-1]);
- free(words-1);
}
- }
- fclose(f);
- for (serv = skip_first(services) ; serv ; serv = skip_next(serv))
- if ((*serv)->pending)
- (*serv)->enabled = 0;
- return err;
+ fclose(f);
+ for (serv = skip_first(services) ; serv ; serv = skip_next(serv))
+ if ((*serv)->pending)
+ (*serv)->enabled = 0;
+ return err;
}
+#include <malloc.h>
-void *malloc(int);
char *recvbuf;
int recvptr;
void init_recv(char *buf)
{
- recvbuf = buf;
- recvptr = 0;
+ recvbuf = buf;
+ recvptr = 0;
}
int get_byte()
{
- return 0xff & recvbuf[recvptr++];
+ return 0xff & recvbuf[recvptr++];
}
int get_int()
{
- int i = 0;
- i = get_byte();
- i = (i<<8) | get_byte();
- i = (i<<8) | get_byte();
- i = (i<<8) | get_byte();
- return i;
+ int i = 0;
+ i = get_byte();
+ i = (i<<8) | get_byte();
+ i = (i<<8) | get_byte();
+ i = (i<<8) | get_byte();
+ return i;
}
char *get_str()
{
- int l = get_int();
- char *s,*p;
- if (l == 0)
- return (char*)0;
- p = s = (char*)malloc(l);
- while (l--)
- *p++ = get_byte();
- return s;
+ int l = get_int();
+ char *s,*p;
+ if (l == 0)
+ return (char*)0;
+ p = s = (char*)malloc(l);
+ while (l--)
+ *p++ = get_byte();
+ return s;
}
/* cache addresses */
typedef struct acache
{
- char *host;
- struct sockaddr_in addr;
+ char *host;
+ struct sockaddr_in addr;
} *acache;
extern char *progname;
static int acmp(acache a, acache b, char *host)
{
- if (b) host=b->host;
- return strcmp(a->host, host);
+ if (b) host=b->host;
+ return strcmp(a->host, host);
}
static void afree(acache a)
{
- free(a->host);
- free(a);
+ free(a->host);
+ free(a);
}
int send_cmd(char *cmd, int udp, char *host, int verbose)
{
- acache *cp, c;
- if (addr_cache == NULL)
- addr_cache = skip_new(acmp, afree, NULL);
+ acache *cp, c;
+ if (addr_cache == NULL)
+ addr_cache = skip_new(acmp, afree, NULL);
- cp = skip_search(addr_cache, host);
- if (cp != NULL)
- c = *cp;
- else
- {
- c = (acache)malloc(sizeof(struct acache));
- c->host = strdup(host);
- c->addr.sin_port = udp ? udp_port() : tcp_port();
- c->addr.sin_addr.s_addr = inet_addr(host);
- if (c->addr.sin_addr.s_addr > 0 && c->addr.sin_addr.s_addr < 0xffffffff)
- {
- c->addr.sin_family = AF_INET;
- }
+ cp = skip_search(addr_cache, host);
+ if (cp != NULL)
+ c = *cp;
else
{
- struct hostent *he;
- he = gethostbyname(host);
- if (he == NULL)
- {
- c->addr.sin_family = -1;
- fprintf(stderr, "%s: unknown host %s\n", progname, host);
- }
- else
- {
- memcpy(&c->addr.sin_addr, he->h_addr_list[0], 4);
- c->addr.sin_family = AF_INET;
- }
- }
- skip_insert(addr_cache, c);
- }
- if (c->addr.sin_family != AF_INET)
- return -1;
- if (udp)
- {
- static int sock = -1;
-
- if (sock == -1)
- {
- sock = socket(AF_INET, SOCK_DGRAM, 0);
- if (geteuid() == 0)
- {
- int port;
- struct sockaddr_in myaddr;
- port = 600 + time(0)%400;
-
- memset(&myaddr, 0, sizeof(myaddr));
- myaddr.sin_family = AF_INET;
- while (port > 500)
+ c = (acache)malloc(sizeof(struct acache));
+ c->host = strdup(host);
+ c->addr.sin_port = udp ? udp_port() : tcp_port();
+ c->addr.sin_addr.s_addr = inet_addr(host);
+ if (c->addr.sin_addr.s_addr > 0 && c->addr.sin_addr.s_addr < 0xffffffff)
{
- myaddr.sin_port = htons(port);
- if (bind(sock, (struct sockaddr *)&myaddr, sizeof(myaddr))== 0)
- break;
- port --;
+ c->addr.sin_family = AF_INET;
}
- if (port == 500)
+ else
{
- fprintf(stderr, "%s: cannot bind priv udp port...\n", progname);
+ struct hostent *he;
+ he = gethostbyname(host);
+ if (he == NULL)
+ {
+ c->addr.sin_family = -1;
+ fprintf(stderr, "%s: unknown host %s\n", progname, host);
+ }
+ else
+ {
+ memcpy(&c->addr.sin_addr, he->h_addr_list[0], 4);
+ c->addr.sin_family = AF_INET;
+ }
}
- }
+ skip_insert(addr_cache, c);
}
- sendto(sock, cmd, strlen(cmd)+1, 0, (struct sockaddr *)&c->addr, sizeof(c->addr));
- }
- else
- {
- /* tcp - have to make a new connection each time */
- int sock;
- static int port = 0;
- char buf[8192]; /* FIXME autosize */
- int n;
- int have = 0;
+ if (c->addr.sin_family != AF_INET)
+ return -1;
+ if (udp)
+ {
+ static int sock = -1;
- if (port == 0)
- port = 600 + time(0)%400;
+ if (sock == -1)
+ {
+ sock = socket(AF_INET, SOCK_DGRAM, 0);
+ if (geteuid() == 0)
+ {
+ int port;
+ struct sockaddr_in myaddr;
+ port = 600 + time(0)%400;
- if (geteuid() == 0)
- sock = rresvport(&port);
+ memset(&myaddr, 0, sizeof(myaddr));
+ myaddr.sin_family = AF_INET;
+ while (port > 500)
+ {
+ myaddr.sin_port = htons(port);
+ if (bind(sock, (struct sockaddr *)&myaddr, sizeof(myaddr))== 0)
+ break;
+ port --;
+ }
+ if (port == 500)
+ {
+ fprintf(stderr, "%s: cannot bind priv udp port...\n", progname);
+ }
+ }
+ }
+ sendto(sock, cmd, strlen(cmd)+1, 0, (struct sockaddr *)&c->addr, sizeof(c->addr));
+ }
else
- sock = socket(AF_INET, SOCK_STREAM, 0);
- if (sock == -1)
{
- fprintf(stderr, "%s: cannot bind socket!!\n", progname);
- return -1;
- }
+ /* tcp - have to make a new connection each time */
+ int sock;
+ static int port = 0;
+ char buf[8192]; /* FIXME autosize */
+ int n;
+ int have = 0;
+
+ if (port == 0)
+ port = 600 + time(0)%400;
+
+ if (geteuid() == 0)
+ sock = rresvport(&port);
+ else
+ sock = socket(AF_INET, SOCK_STREAM, 0);
+ if (sock == -1)
+ {
+ fprintf(stderr, "%s: cannot bind socket!!\n", progname);
+ return -1;
+ }
#ifdef TCP_CONN_ABORT_THRESHOLD
- {
- int thresh;
- thresh = 10*1000;
- setsockopt(sock, IPPROTO_TCP, TCP_CONN_ABORT_THRESHOLD, (char*)&thresh, 4);
- }
+ {
+ int thresh;
+ thresh = 10*1000;
+ setsockopt(sock, IPPROTO_TCP, TCP_CONN_ABORT_THRESHOLD, (char*)&thresh, 4);
+ }
#endif
-/* */
- if (connect(sock, (struct sockaddr *)&c->addr, sizeof(c->addr))!= 0)
- {
- fprintf(stderr, "%s: cannot connect to %s\n", progname, c->host);
- close(sock);
- c->addr.sin_family = -1;
- return -1;
- }
- write(sock, cmd, strlen(cmd)+1);
- shutdown(sock, 1); /* don't want to write no more */
- do
- {
- n = read(sock, buf+have, sizeof(buf)-1 - have);
- if (n>0) have += n;
- } while (n>0 && have < sizeof(buf)-1);
- close(sock);
- if (have <= 0)
- return 0; /* probably OK, FIXME */
- buf[have] = 0;
- switch(buf[0])
- {
- case 0: return 0; /* definately ok */
- case 1: /* error message */
- fprintf(stderr, "%s: %s: %s\n", progname, c->host, buf+1);
- return 1;
- case 2: /* version number */
- fprintf(stdout, "%s: %s\n", c->host, buf+1);
- return 0;
- case 3: /* listing */
- init_recv(buf+1);
- list_service(c->host, verbose);
- /* FIXME */
- return 0;
+/* */
+ if (connect(sock, (struct sockaddr *)&c->addr, sizeof(c->addr))!= 0)
+ {
+ fprintf(stderr, "%s: cannot connect to %s\n", progname, c->host);
+ close(sock);
+ c->addr.sin_family = -1;
+ return -1;
+ }
+ write(sock, cmd, strlen(cmd)+1);
+ shutdown(sock, 1); /* don't want to write no more */
+ do
+ {
+ n = read(sock, buf+have, sizeof(buf)-1 - have);
+ if (n>0) have += n;
+ } while (n>0 && have < sizeof(buf)-1);
+ close(sock);
+ if (have <= 0)
+ return 0; /* probably OK, FIXME */
+ buf[have] = 0;
+ switch(buf[0])
+ {
+ case 0: return 0; /* definately ok */
+ case 1: /* error message */
+ fprintf(stderr, "%s: %s: %s\n", progname, c->host, buf+1);
+ return 1;
+ case 2: /* version number */
+ fprintf(stdout, "%s: %s\n", c->host, buf+1);
+ return 0;
+ case 3: /* listing */
+ init_recv(buf+1);
+ list_service(c->host, verbose);
+ /* FIXME */
+ return 0;
- case 'm': /* old version number */
- fprintf(stdout, "%s\n", buf);
- return 0;
- default: /* old metad */
- /* FIXME */
- return 0;
+ case 'm': /* old version number */
+ fprintf(stdout, "%s\n", buf);
+ return 0;
+ default: /* old metad */
+ /* FIXME */
+ return 0;
+ }
}
- }
- return 0;
+ return 0;
}
-
+
static void list_service(char *host, int verbose)
{
- int b;
- b = get_byte();
- while (b == 1 || b == 2) /* a service */
- {
- char *sname, *home, *user, *crash, *prog;
- char **args;
- int argc;
- int max, cnt, enabled;
- int i;
- int class;
- char *classname=NULL;
- char *pidfile = NULL;
- int watch_output = 0;
- int min=0, period=0, last;
- int proto, port=0, active=0, backlog=0;
-
- sname = get_str();
- max = get_int();
- home = get_str();
- user = get_str();
- crash = get_str();
- if (b == 2)
- {
- watch_output = get_int();
- pidfile = get_str();
- }
- cnt = get_int();
- enabled = get_int();
- prog = get_str();
- argc = get_int();
- args = (char**)malloc((argc+1)*sizeof(char*));
- for (i=0 ; i<argc ; i++)
- args[i] = get_str();
- args[i] = NULL;
- class = get_byte();
- switch(class)
+ int b;
+ b = get_byte();
+ while (b == 1 || b == 2) /* a service */
{
- case 1: /* daemon */
- classname = "daemon";
- min = get_int();
- period = get_int();
- last = get_int();
- break;
- case 2: /* stream */
- classname = "stream";
- proto = get_int();
- port = get_int();
- backlog = get_int();
- active = get_int();
- break;
- }
+ char *sname, *home, *user, *crash, *prog;
+ char **args;
+ int argc;
+ int max, cnt, enabled;
+ int i;
+ int class;
+ char *classname=NULL;
+ char *pidfile = NULL;
+ int watch_output = 0;
+ int min=0, period=0, last;
+ int proto, port=0, active=0, backlog=0;
+
+ sname = get_str();
+ max = get_int();
+ home = get_str();
+ user = get_str();
+ crash = get_str();
+ if (b == 2)
+ {
+ watch_output = get_int();
+ pidfile = get_str();
+ }
+ cnt = get_int();
+ enabled = get_int();
+ prog = get_str();
+ argc = get_int();
+ args = (char**)malloc((argc+1)*sizeof(char*));
+ for (i=0 ; i<argc ; i++)
+ args[i] = get_str();
+ args[i] = NULL;
+ class = get_byte();
+ switch(class)
+ {
+ case 1: /* daemon */
+ classname = "daemon";
+ min = get_int();
+ period = get_int();
+ last = get_int();
+ break;
+ case 2: /* stream */
+ classname = "stream";
+ proto = get_int();
+ port = get_int();
+ backlog = get_int();
+ active = get_int();
+ break;
+ }
/* printf("Host: %s\n", host); */
- if (sname == NULL) sname = "*unknown*";
- printf("%s:%s%*.0s %s %s (x%d)", host, sname, 18-(int)strlen(host) - (int)strlen(sname), "",
- classname, enabled?"enabled":"DISABLED", cnt);
- if (verbose)
- {
- printf("\n");
- printf(" Prog: %s\n", prog);
- printf(" Args:");
- for (i=0; i<argc ; i++)
- printf(" %s", args[i]);
- printf("\n");
- printf(" Opts:");
- if (max) printf(" max=%d", max);
- if (home) printf(" dir=%s", home);
- if (user) printf(" user=%s", user);
- if (crash) printf(" crash=%s", crash);
- if (pidfile) printf(" pidfile=%s", pidfile);
- if (watch_output) printf(" watch_output");
- switch(class)
- {
- case 1: /* daemon */
- if (min) printf(" min=%d", min);
- if (period) printf(" period=%d", period);
- break;
- case 2:
- printf(" port=%d", port);
- printf(" backlog=%d", backlog);
- if (!active) printf(" INACTIVE");
- break;
+ if (sname == NULL) sname = "*unknown*";
+ printf("%s:%s%*.0s %s %s (x%d)", host, sname, 18-(int)strlen(host) - (int)strlen(sname), "",
+ classname, enabled?"enabled":"DISABLED", cnt);
+ if (verbose)
+ {
+ printf("\n");
+ printf(" Prog: %s\n", prog);
+ printf(" Args:");
+ for (i=0; i<argc ; i++)
+ printf(" %s", args[i]);
+ printf("\n");
+ printf(" Opts:");
+ if (max) printf(" max=%d", max);
+ if (home) printf(" dir=%s", home);
+ if (user) printf(" user=%s", user);
+ if (crash) printf(" crash=%s", crash);
+ if (pidfile) printf(" pidfile=%s", pidfile);
+ if (watch_output) printf(" watch_output");
+ switch(class)
+ {
+ case 1: /* daemon */
+ if (min) printf(" min=%d", min);
+ if (period) printf(" period=%d", period);
+ break;
+ case 2:
+ printf(" port=%d", port);
+ printf(" backlog=%d", backlog);
+ if (!active) printf(" INACTIVE");
+ break;
- }
- printf("\n");
- }
- b = get_byte();
- while (b == 3 || b == 4) /* process */
- {
- int pid, hold, status;
- int forkedpid;
- time_t start, xit;
- pid = get_int();
- if (b==4)
- {
- forkedpid = get_int();
- get_int(); /* pipefd */
- }
- else forkedpid = 0;
- start = get_int();
- hold = get_int();
- xit = get_int();
- status = get_int();
- if (verbose)
- {
- printf(" Proc: pid=%5d%s %s", (xit && forkedpid) ? forkedpid : pid,
- (xit&&forkedpid)?"f":"", ctime(&start));
- if (xit && forkedpid==0)
+ }
+ printf("\n");
+ }
+ b = get_byte();
+ while (b == 3 || b == 4) /* process */
{
- char *t,*t2;
- time_t holdt;
- holdt = hold - time(0);
- t = prtime(holdt);
- while(*t == ' ') t++;
- t2=ctime(&xit)+4;
- printf(" Exited %1.12s holding for %s\n", t2, t);
+ int pid, hold, status;
+ int forkedpid;
+ time_t start, xit;
+ pid = get_int();
+ if (b==4)
+ {
+ forkedpid = get_int();
+ get_int(); /* pipefd */
+ }
+ else forkedpid = 0;
+ start = get_int();
+ hold = get_int();
+ xit = get_int();
+ status = get_int();
+ if (verbose)
+ {
+ printf(" Proc: pid=%5d%s %s", (xit && forkedpid) ? forkedpid : pid,
+ (xit&&forkedpid)?"f":"", ctime(&start));
+ if (xit && forkedpid==0)
+ {
+ char *t,*t2;
+ time_t holdt;
+ holdt = hold - time(0);
+ t = prtime(holdt);
+ while(*t == ' ') t++;
+ t2=ctime(&xit)+4;
+ printf(" Exited %1.12s holding for %s\n", t2, t);
+ }
+ }
+ else
+ {
+ char *t;
+ time_t age = time(0) - start;
+ t = (char*)prtime(age);
+ while(*t == ' ') t++;
+ printf(" %d%s(%s%s)", (xit && forkedpid) ? forkedpid : pid,
+ (xit&&forkedpid)?"f":"",
+ (xit && forkedpid==0)?"exited:":"", t);
+ }
+ b = get_byte();
}
- }
- else
- {
- char *t;
- time_t age = time(0) - start;
- t = (char*)prtime(age);
- while(*t == ' ') t++;
- printf(" %d%s(%s%s)", (xit && forkedpid) ? forkedpid : pid,
- (xit&&forkedpid)?"f":"",
- (xit && forkedpid==0)?"exited:":"", t);
- }
- b = get_byte();
+ if (!verbose) printf("\n");
}
- if (!verbose) printf("\n");
- }
}
void send_proc(proc_t p)
{
- if (p->it_forked > 0 || p->pipefd >= 0)
- {
- send_byte(4);
- send_int(p->pid);
- send_int(p->it_forked);
- send_int(p->pipefd);
- }
- else
- {
- send_byte(3); /* process */
- send_int(p->pid);
- }
- send_int(p->start_time);
- send_int(p->hold_time);
- send_int(p->exit_time);
- send_int(p->status);
+ if (p->it_forked > 0 || p->pipefd >= 0) {
+ send_byte(4);
+ send_int(p->pid);
+ send_int(p->it_forked);
+ send_int(p->pipefd);
+ } else {
+ send_byte(3); /* process */
+ send_int(p->pid);
+ }
+ send_int(p->start_time);
+ send_int(p->hold_time);
+ send_int(p->exit_time);
+ send_int(p->status);
}
void send_service(service_t sv)
{
- int i;
- proc_t *pp;
- if (sv->watch_output || sv->pidfile)
- send_byte(2);
- else
- send_byte(1); /* service */
- send_str(sv->service);
- send_int(sv->max_proc);
- send_str(sv->home_dir);
- send_str(sv->username);
- send_str(sv->crash_prog);
- if (sv->watch_output || sv->pidfile)
- {
- send_int(sv->watch_output);
- send_str(sv->pidfile);
- }
- send_int(sv->start_cnt);
- send_int(sv->enabled);
- send_str(sv->program);
- for (i=0 ; sv->args[i] ; i++);
- send_int(i);
- for (i=0 ; sv->args[i] ; i++)
- send_str(sv->args[i]);
- (sv->class->send_class)(sv);
- for (pp = skip_first(sv->proc_list) ; pp ; pp = skip_next(pp))
- send_proc(*pp);
+ int i;
+ proc_t *pp;
+ if (sv->watch_output || sv->pidfile)
+ send_byte(2);
+ else
+ send_byte(1); /* service */
+ send_str(sv->service);
+ send_int(sv->max_proc);
+ send_str(sv->home_dir);
+ send_str(sv->username);
+ send_str(sv->crash_prog);
+ if (sv->watch_output || sv->pidfile) {
+ send_int(sv->watch_output);
+ send_str(sv->pidfile);
+ }
+ send_int(sv->start_cnt);
+ send_int(sv->enabled);
+ send_str(sv->program);
+ for (i=0 ; sv->args[i] ; i++);
+ send_int(i);
+ for (i=0 ; sv->args[i] ; i++)
+ send_str(sv->args[i]);
+ (sv->class->send_class)(sv);
+ for (pp = skip_first(sv->proc_list) ; pp ; pp = skip_next(pp))
+ send_proc(*pp);
}
void send_int(int i)
{
- send_byte((i>>24)& 0xff);
- send_byte((i>>16)& 0xff);
- send_byte((i>> 8)& 0xff);
- send_byte((i>> 0)& 0xff);
-}
+ send_byte((i>>24)& 0xff);
+ send_byte((i>>16)& 0xff);
+ send_byte((i>> 8)& 0xff);
+ send_byte((i>> 0)& 0xff);
+}
+
void send_str(char *s)
{
- if (s == NULL)
- send_int(0);
- else
- {
- send_int(strlen(s)+1);
- while (*s)
- send_byte(*s++);
- send_byte(0);
- }
+ if (s == NULL)
+ send_int(0);
+ else {
+ send_int(strlen(s)+1);
+ while (*s)
+ send_byte(*s++);
+ send_byte(0);
+ }
}
static char *sendbuf = NULL;
void send_byte(int b)
{
- if (sendptr >= sendsize)
- {
- sendsize += 100;
- sendbuf = (char*)realloc(sendbuf, sendsize);
- }
- sendbuf[sendptr++] = b;
+ if (sendptr >= sendsize) {
+ sendsize += 100;
+ sendbuf = (char*)realloc(sendbuf, sendsize);
+ }
+ sendbuf[sendptr++] = b;
}
void init_return()
{
- sendptr = 0;
- if (sendbuf == NULL)
- {
- sendsize = 200;
- sendbuf = malloc(sendsize);
- }
+ sendptr = 0;
+ if (sendbuf == NULL) {
+ sendsize = 200;
+ sendbuf = malloc(sendsize);
+ }
}
void do_send(void *con)
{
- set_reply(con, sendbuf, sendptr);
- sendbuf = NULL;
- sendptr = 0;
+ set_reply(con, sendbuf, sendptr);
+ sendbuf = NULL;
+ sendptr = 0;
}
char *get_return(int *i)
{
- char *c = sendbuf;
- *i = sendptr;
- sendbuf = NULL;
- sendptr = 0;
- return c;
+ char *c = sendbuf;
+ *i = sendptr;
+ sendbuf = NULL;
+ sendptr = 0;
+ return c;
}
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
-#include <values.h>
+#include <values.h>
void *services;
void *allprocs;
int count_procs(service_t sv)
{
- proc_t *pp, p;
- int cnt;
- time_t now = time(0);
- for (cnt=0, pp=skip_first(sv->proc_list) ; pp ; pp=skip_next(pp))
- {
- p = *pp;
- if (p->exit_time == 0 || p->hold_time > now || p->pipefd >=0 || p->it_forked)
- cnt++;
- }
- return cnt;
+ proc_t *pp, p;
+ int cnt;
+ time_t now = time(0);
+ for (cnt=0, pp=skip_first(sv->proc_list) ; pp ; pp=skip_next(pp))
+ {
+ p = *pp;
+ if (p->exit_time == 0 || p->hold_time > now || p->pipefd >=0 || p->it_forked)
+ cnt++;
+ }
+ return cnt;
}
void check_service(service_t sv)
{
- /* check for exited processes and possibly run crash */
- proc_t *pp;
- time_t now = time(0);
+ /* check for exited processes and possibly run crash */
+ proc_t *pp;
+ time_t now = time(0);
- for (pp=skip_first(sv->proc_list) ; pp ; )
- {
- proc_t p;
- p = *pp;
- pp = skip_next(pp);
- if (p->exit_time == 0) {
- /* monitoring a normal child
- * we should have been alerted if the child exitted,
- * but just-in-case... try sig0
- */
- if (kill(p->pid, 0) == -1 && errno == ESRCH && !is_saved_pid(p->pid)) {
- p->status = 0; /* who knows. */
- p->exit_time = now;
- }
- }
- if (p->exit_time > 0 && p->hold_time == 0)
- {
- /* a newly exited process */
- if (p->is_crash)
- {
- /* this is a crash recover prog exitting. just set the hold time */
- p->hold_time = p->exit_time + sv->next_hold;
- }
- else if (WIFSIGNALED(p->status) || (WIFEXITED(p->status) && WEXITSTATUS(p->status) != 0))
- {
- /* exited badly */
- if (p->exit_time - p->start_time < 30) {
- if (sv->next_hold < MAXINT/2)
- sv->next_hold *= 2;
- } else
- sv->next_hold = 2;
- if (0 && sv->crash_prog)
- {
- /* FIXME */
- }
- else p->hold_time = p->exit_time + sv->next_hold;
- }
- else
- {
- if (sv->pidfile)
- {
- /* if this file is newer than start_time and contains a pid,
- * record that pid as this pid and shedule regular checks
- */
- int fd = open(sv->pidfile, 0);
- struct stat stb;
- char pidline[100];
- int n;
- int pid;
- if (fd >= 0
- && fstat(fd, &stb) != -1
- && stb.st_mtime >= p->start_time
- && (n=read(fd, pidline, sizeof(pidline)-1))> 0
- && (pidline[n]=0 , pid=atoi(pidline)) > 1
- && kill(pid, 0) != -1
- )
- {
- /* looks good ! */
- p->it_forked = pid;
- p->hold_time = 1;
- waituntil(now+5); /* check it in 5 seconds and periodically */
- }
- else
- {
- /* give the program a few seconds to write to the file
- * e.g. xdm forks, then creates the pid file
+ for (pp=skip_first(sv->proc_list) ; pp ; ) {
+ proc_t p;
+ p = *pp;
+ pp = skip_next(pp);
+ if (p->exit_time == 0) {
+ /* monitoring a normal child
+ * we should have been alerted if the child exitted,
+ * but just-in-case... try sig0
*/
- if (p->exit_time + 10 > now)
- {
- p->it_forked = -1;
- waituntil(p->exit_time + 11);
+ if (kill(p->pid, 0) == -1 && errno == ESRCH && !is_saved_pid(p->pid)) {
+ p->status = 0; /* who knows. */
+ p->exit_time = now;
}
- else
- {
- // give up waiting
- p->it_forked = 0;
+ }
+ if (p->exit_time > 0 && p->hold_time == 0) {
+ /* a newly exited process */
+ if (p->is_crash) {
+ /* this is a crash recover prog exitting. just set the hold time */
+ p->hold_time = p->exit_time + sv->next_hold;
+ }
+ else if (WIFSIGNALED(p->status) ||
+ (WIFEXITED(p->status) &&
+ WEXITSTATUS(p->status) != 0)) {
+ /* exited badly */
+ if (p->exit_time - p->start_time < 30) {
+ if (sv->next_hold < MAXINT/2)
+ sv->next_hold *= 2;
+ } else
+ sv->next_hold = 2;
+ if (0 && sv->crash_prog) {
+ /* FIXME */
+ }
+ else p->hold_time = p->exit_time + sv->next_hold;
+ }
+ else
+ {
+ if (sv->pidfile) {
+ /* if this file is newer than start_time and contains a pid,
+ * record that pid as this pid and shedule regular checks
+ */
+ int fd = open(sv->pidfile, 0);
+ struct stat stb;
+ char pidline[100];
+ int n;
+ int pid;
+ if (fd >= 0
+ && fstat(fd, &stb) != -1
+ && stb.st_mtime >= p->start_time
+ && (n=read(fd, pidline, sizeof(pidline)-1))> 0
+ && (pidline[n]=0 , pid=atoi(pidline)) > 1
+ && kill(pid, 0) != -1
+ ) {
+ /* looks good ! */
+ p->it_forked = pid;
+ p->hold_time = 1;
+ waituntil(now+5); /* check it in 5 seconds and periodically */
+ } else {
+ /* give the program a few seconds to write to the file
+ * e.g. xdm forks, then creates the pid file
+ */
+ if (p->exit_time + 10 > now) {
+ p->it_forked = -1;
+ waituntil(p->exit_time + 11);
+ } else {
+ // give up waiting
+ p->it_forked = 0;
- /* probably exited badly if it didn't run for long
- (keep in mind that the pidfile wasn't updated) */
- if (p->exit_time - p->start_time < 30) {
- if (sv->next_hold < MAXINT/2)
- sv->next_hold *= 2;
- } else
- sv->next_hold = 2;
+ /* probably exited badly if it didn't run for long
+ (keep in mind that the pidfile wasn't updated) */
+ if (p->exit_time - p->start_time < 30) {
+ if (sv->next_hold < MAXINT/2)
+ sv->next_hold *= 2;
+ } else
+ sv->next_hold = 2;
- p->hold_time = p->exit_time + sv->next_hold;
- }
- }
- if (fd >= 0) close(fd);
- } else
- sv->next_hold = 2;
+ p->hold_time = p->exit_time + sv->next_hold;
+ }
+ }
+ if (fd >= 0) close(fd);
+ } else
+ sv->next_hold = 2;
- }
- }
- else if (p->exit_time > 0 && p->it_forked > 0)
- {
- /* monitoring forked child
- * try sending sig0 to see if process still exists
- */
- if (kill(p->it_forked, 0)== -1 && errno == ESRCH)
- {
- p->it_forked = 0;
- p->exit_time = now;
- }
- else
- waituntil(now+30); /* wait 30 seconds and check again */
- }
- if (p->pipefd >= 0)
- {
- if (readyon(p->pipefd))
- {
- int n = read(p->pipefd, p->pipebuf+p->bufptr, sizeof(p->pipebuf)-p->bufptr-1);
- if (n<= 0)
- {
- close(p->pipefd);
- p->pipefd = -1;
+ }
}
- else
- {
- int i = 0;
- p->bufptr += n;
- while (i < p->bufptr)
- {
- while (i < p->bufptr && p->pipebuf[i] != '\n')
- i++;
- if (p->pipebuf[i] == '\n' || i > sizeof(p->pipebuf)-2)
- {
- /* ship out this much */
- int j;
- p->pipebuf[i] = '\0';
- dolog(sv, p, p->pipebuf);
- for (j=i+1 ; j<p->bufptr ; j++)
- p->pipebuf[j-i-1] = p->pipebuf[j];
- p-> bufptr -= i+1;
- i = 0;
+ else if (p->exit_time > 0 && p->it_forked > 0) {
+ /* monitoring forked child
+ * try sending sig0 to see if process still exists
+ */
+ if (kill(p->it_forked, 0)== -1 && errno == ESRCH) {
+ p->it_forked = 0;
+ p->exit_time = now;
+ } else
+ waituntil(now+30); /* wait 30 seconds and check again */
+ }
+ if (p->pipefd >= 0) {
+ if (readyon(p->pipefd)) {
+ int n = read(p->pipefd, p->pipebuf+p->bufptr, sizeof(p->pipebuf)-p->bufptr-1);
+ if (n<= 0) {
+ close(p->pipefd);
+ p->pipefd = -1;
+ } else {
+ int i = 0;
+ p->bufptr += n;
+ while (i < p->bufptr) {
+ while (i < p->bufptr && p->pipebuf[i] != '\n')
+ i++;
+ if (p->pipebuf[i] == '\n' ||
+ i > sizeof(p->pipebuf)-2) {
+ /* ship out this much */
+ int j;
+ p->pipebuf[i] = '\0';
+ dolog(sv, p, p->pipebuf);
+ for (j=i+1 ; j<p->bufptr ; j++)
+ p->pipebuf[j-i-1] = p->pipebuf[j];
+ p-> bufptr -= i+1;
+ i = 0;
+ } else
+ i++;
+ }
+ }
}
- else
- i++;
- }
+ if (p->pipefd >= 0)
+ listenon(p->pipefd);
}
- }
- if (p->pipefd >= 0)
- listenon(p->pipefd);
- }
- if (p->exit_time > 0 && p->hold_time < now && p->it_forked == 0
- && (p->pipefd == -1 || p->exit_time +30 <now))
- {
- /* clean up */
- if (p->pipefd>=0)
- {
- /* it has been 30 seconds since the parent exitted, time to
- * discard the pipe...
- */
- close(p->pipefd);
- p->pipefd = -1;
- }
- skip_delete(sv->proc_list, &p->pid);
- skip_delete(allprocs, &p->pid);
- free(p);
+ if (p->exit_time > 0 && p->hold_time < now && p->it_forked == 0
+ && (p->pipefd == -1 || p->exit_time +30 <now)) {
+ /* clean up */
+ if (p->pipefd>=0) {
+ /* it has been 30 seconds since the parent exitted, time to
+ * discard the pipe...
+ */
+ close(p->pipefd);
+ p->pipefd = -1;
+ }
+ skip_delete(sv->proc_list, &p->pid);
+ skip_delete(allprocs, &p->pid);
+ free(p);
+ }
+ else if (p->exit_time > 0 && p->hold_time > 2)
+ waituntil(p->hold_time+1);
}
- else if (p->exit_time > 0 && p->hold_time > 2)
- waituntil(p->hold_time+1);
- }
- (sv->class->c_check_service)(sv);
+ (sv->class->c_check_service)(sv);
}
int new_proc(service_t sv, char **env)
{
- /* fork, register new child
- * in child, call sv->class->new_child for final setup before exec
- */
- int pid;
- proc_t p;
- char **envp;
- extern char **environ;
- time_t now;
- int pipefd[2];
+ /* fork, register new child
+ * in child, call sv->class->new_child for final setup before exec
+ */
+ int pid;
+ proc_t p;
+ char **envp;
+ extern char **environ;
+ time_t now;
+ int pipefd[2];
- if (sv->enabled == 0)
- return -2;
- if (sv->max_proc > 0 && count_procs(sv) >= sv->max_proc)
- return -2; /* too many already */
+ if (sv->enabled == 0)
+ return -2;
+ if (sv->max_proc > 0 && count_procs(sv) >= sv->max_proc)
+ return -2; /* too many already */
- if (sv->class->prefork(sv))
- return -2;
+ if (sv->class->prefork(sv))
+ return -2;
- now = time(0);
- if (sv->watch_output)
- {
- if (pipe(pipefd)== -1)
- pipefd[0] = pipefd[1] = -1;
- }
- switch (pid = fork())
- {
- case -1:
- if (sv->watch_output)
- {
- close(pipefd[0]); close(pipefd[1]);
- }
- return -1; /* cannot fork */
- case 0: /* child */
- errors_to(ERROR_SYSLOG, NULL);
- if (sv->home_dir)
- {
- if (chdir(sv->home_dir)!=0)
- {
- error("Couldn't chdir to %s", sv->home_dir);
- exit(10);
- }
- }
- if (sv->username)
- {
- struct passwd *pw = getpwnam(sv->username);
- if (pw) {
- initgroups(sv->username, pw->pw_gid);
- setgid(pw->pw_gid);
- setuid(pw->pw_uid);
- } else {
- error("unknown user %s", sv->username);
- exit(10);
- }
- }
- (sv->class->new_child)(sv);
- if (!env)
- envp = environ;
- else
- {
- int cnt, i;
- cnt = 0;
- for (i=0 ; env[i] ; i++) cnt++;
- for (i=0 ; environ[i] ; i++) cnt++;
- envp = (char**)malloc((cnt+1) * sizeof(char*));
- cnt = 0;
- for (i=0 ; env[i] ; i++)
- envp[cnt++] = env[i];
- for (i=0 ; environ[i] ; i++)
- envp[cnt++] = environ[i];
- envp[cnt] = NULL;
- }
- if (sv->watch_output && pipefd[0] >= 0)
- {
- close(pipefd[0]);
- if (pipefd[1] != 1) close(1);
- if (pipefd[1] != 2) close(2);
- if (pipefd[1] == 0)
- {
- pipefd[1] = dup(pipefd[1]);
- close(0);
- }
- open("/dev/null", 0);
- dup(pipefd[1]);
- if (pipefd[1] > 2)
- {
- dup(pipefd[1]);
- close(pipefd[1]);
- }
+ now = time(0);
+ if (sv->watch_output) {
+ if (pipe(pipefd)== -1)
+ pipefd[0] = pipefd[1] = -1;
}
- execve(sv->program, sv->args, envp);
- exit(11);
- default: /* parent */
- p = (proc_t)malloc(sizeof(struct proc));
- if (sv->watch_output)
- {
- close(pipefd[1]);
- p->pipefd = pipefd[0];
- p->bufptr = 0;
- if (p->pipefd >= 0) listenon(p->pipefd);
- fcntl(p->pipefd, F_SETFD, 1);
+ switch (pid = fork()) {
+ case -1:
+ if (sv->watch_output) {
+ close(pipefd[0]); close(pipefd[1]);
+ }
+ return -1; /* cannot fork */
+ case 0: /* child */
+ errors_to(ERROR_SYSLOG, NULL);
+ if (sv->home_dir) {
+ if (chdir(sv->home_dir)!=0) {
+ error("Couldn't chdir to %s", sv->home_dir);
+ exit(10);
+ }
+ }
+ if (sv->username) {
+ struct passwd *pw = getpwnam(sv->username);
+ if (pw) {
+ initgroups(sv->username, pw->pw_gid);
+ setgid(pw->pw_gid);
+ setuid(pw->pw_uid);
+ } else {
+ error("unknown user %s", sv->username);
+ exit(10);
+ }
+ }
+ (sv->class->new_child)(sv);
+ if (!env)
+ envp = environ;
+ else {
+ int cnt, i;
+ cnt = 0;
+ for (i=0 ; env[i] ; i++) cnt++;
+ for (i=0 ; environ[i] ; i++) cnt++;
+ envp = (char**)malloc((cnt+1) * sizeof(char*));
+ cnt = 0;
+ for (i=0 ; env[i] ; i++)
+ envp[cnt++] = env[i];
+ for (i=0 ; environ[i] ; i++)
+ envp[cnt++] = environ[i];
+ envp[cnt] = NULL;
+ }
+ if (sv->watch_output && pipefd[0] >= 0) {
+ close(pipefd[0]);
+ if (pipefd[1] != 1) close(1);
+ if (pipefd[1] != 2) close(2);
+ if (pipefd[1] == 0) {
+ pipefd[1] = dup(pipefd[1]);
+ close(0);
+ }
+ open("/dev/null", 0);
+ dup(pipefd[1]);
+ if (pipefd[1] > 2) {
+ dup(pipefd[1]);
+ close(pipefd[1]);
+ }
+ }
+ execve(sv->program, sv->args, envp);
+ exit(11);
+ default: /* parent */
+ p = (proc_t)malloc(sizeof(struct proc));
+ if (sv->watch_output) {
+ close(pipefd[1]);
+ p->pipefd = pipefd[0];
+ p->bufptr = 0;
+ if (p->pipefd >= 0) listenon(p->pipefd);
+ fcntl(p->pipefd, F_SETFD, 1);
+ }
+ else
+ p->pipefd = -1;
+ p->pid = pid;
+ p->service = sv;
+ p->it_forked = 0;
+ p->is_crash = 0;
+ p->start_time = now;
+ p->hold_time = 0;
+ p->exit_time = 0;
+ skip_insert(sv->proc_list, p);
+ sv->start_cnt ++;
+ skip_insert(allprocs, p);
+ sv->class->new_parent(sv,p);
}
- else
- p->pipefd = -1;
- p->pid = pid;
- p->service = sv;
- p->it_forked = 0;
- p->is_crash = 0;
- p->start_time = now;
- p->hold_time = 0;
- p->exit_time = 0;
- skip_insert(sv->proc_list, p);
- sv->start_cnt ++;
- skip_insert(allprocs, p);
- sv->class->new_parent(sv,p);
- }
- return pid;
+ return pid;
}
void prepare_restart(void)
{
- service_t *sp;
- for (sp = skip_first(services) ; sp ; sp=skip_next(sp))
- {
- service_t sv = *sp;
- proc_t *pp;
- for (pp=skip_first(sv->proc_list) ; pp ; pp=skip_next(pp))
- {
- proc_t p = *pp;
- if (p->pipefd >= 0)
- fcntl(p->pipefd, F_SETFD, 0);
+ service_t *sp;
+ for (sp = skip_first(services) ; sp ; sp=skip_next(sp)) {
+ service_t sv = *sp;
+ proc_t *pp;
+ for (pp=skip_first(sv->proc_list) ; pp ; pp=skip_next(pp)) {
+ proc_t p = *pp;
+ if (p->pipefd >= 0)
+ fcntl(p->pipefd, F_SETFD, 0);
+ }
}
- }
}
static int proc_cmp(proc_t a, proc_t b, int *kp)
{
- int k;
- if (b) k=b->pid; else k = *kp;
- return k - a->pid;
+ int k;
+ if (b) k=b->pid; else k = *kp;
+ return k - a->pid;
}
service_t new_service(char *name, class_t class)
{
- service_t sv = (service_t)malloc(sizeof(struct service));
+ service_t sv = (service_t)malloc(sizeof(struct service));
- sv->service = strdup(name);
- sv->class = class;
- sv->max_proc = 1;
- sv->crash_prog = NULL;
- sv->home_dir = NULL;
- sv->username = NULL;
- sv->pidfile = NULL;
- sv->watch_output = 0;
- sv->enabled = 1;
- sv->start_cnt = 0;
- sv->program = NULL;
- sv->args = 0;
- sv->pending = 0;
- sv->proc_list = skip_new(proc_cmp, NULL, NULL);
- sv->next_hold = 2;
- (*class->copy_state)(NULL, sv);
- return sv;
+ sv->service = strdup(name);
+ sv->class = class;
+ sv->max_proc = 1;
+ sv->crash_prog = NULL;
+ sv->home_dir = NULL;
+ sv->username = NULL;
+ sv->pidfile = NULL;
+ sv->watch_output = 0;
+ sv->enabled = 1;
+ sv->start_cnt = 0;
+ sv->program = NULL;
+ sv->args = 0;
+ sv->pending = 0;
+ sv->proc_list = skip_new(proc_cmp, NULL, NULL);
+ sv->next_hold = 2;
+ (*class->copy_state)(NULL, sv);
+ return sv;
}
int process_opt(service_t sv, char *opt)
{
- /* max= crash= dir= user= enabled= */
+ /* max= crash= dir= user= enabled= */
- if (strncmp(opt, "max=", 4)==0)
- {
- sv->max_proc = atoi(opt+4);
- return 1;
- }
- else if (strncmp(opt, "crash=", 6)==0)
- {
- sv->crash_prog = strdup(opt+6);
- return 1;
- }
- else if (strncmp(opt, "dir=", 4)==0)
- {
- sv->home_dir = strdup(opt+4);
- return 1;
- }
- else if (strncmp(opt, "user=", 5)==0)
- {
- sv->username = strdup(opt+5);
- return 1;
- }
- else if (strncmp(opt, "enabled=", 8)==0)
- {
- if (strcmp(opt+8, "no")==0)
- sv->enabled = 0;
- else if (strcmp(opt+8, "yes")==0)
- sv->enabled = 1;
- else return -1;
- return 1;
- }
- else if (strncmp(opt, "pidfile=", 8)==0)
- {
- sv->pidfile = strdup(opt+8);
- return 1;
- }
- else if (strcmp(opt, "watch_output")==0)
- {
- sv->watch_output = 1;
- return 1;
- }
- else return 0;
+ if (strncmp(opt, "max=", 4)==0) {
+ sv->max_proc = atoi(opt+4);
+ return 1;
+ } else if (strncmp(opt, "crash=", 6)==0) {
+ sv->crash_prog = strdup(opt+6);
+ return 1;
+ } else if (strncmp(opt, "dir=", 4)==0) {
+ sv->home_dir = strdup(opt+4);
+ return 1;
+ } else if (strncmp(opt, "user=", 5)==0) {
+ sv->username = strdup(opt+5);
+ return 1;
+ } else if (strncmp(opt, "enabled=", 8)==0) {
+ if (strcmp(opt+8, "no")==0)
+ sv->enabled = 0;
+ else if (strcmp(opt+8, "yes")==0)
+ sv->enabled = 1;
+ else return -1;
+ return 1;
+ } else if (strncmp(opt, "pidfile=", 8)==0) {
+ sv->pidfile = strdup(opt+8);
+ return 1;
+ } else if (strcmp(opt, "watch_output")==0) {
+ sv->watch_output = 1;
+ return 1;
+ } else
+ return 0;
}
static int service_cmp(service_t a, service_t b, char *k)
{
- if (b) k = b->service;
- return strcmp(a->service, k);
+ if (b) k = b->service;
+ return strcmp(a->service, k);
}
void service_init(void)
{
- services = skip_new(service_cmp, NULL, NULL);
- allprocs = skip_new(proc_cmp, NULL, NULL);
+ services = skip_new(service_cmp, NULL, NULL);
+ allprocs = skip_new(proc_cmp, NULL, NULL);
}
void free_service(service_t sv)
{
- if (sv->service) free(sv->service);
- if (sv->crash_prog) free(sv->crash_prog);
- if (sv->classinfo) (sv->class->free_state)(sv);
- if (sv->home_dir) free(sv->home_dir);
- if (sv->username) free(sv->username);
- if (sv->program) free(sv->program);
- if (sv->pidfile) free(sv->pidfile);
- if (sv->args) strlistfree(sv->args);
- if (sv->proc_list) skip_free(sv->proc_list);
+ if (sv->service) free(sv->service);
+ if (sv->crash_prog) free(sv->crash_prog);
+ if (sv->classinfo) (sv->class->free_state)(sv);
+ if (sv->home_dir) free(sv->home_dir);
+ if (sv->username) free(sv->username);
+ if (sv->program) free(sv->program);
+ if (sv->pidfile) free(sv->pidfile);
+ if (sv->args) strlistfree(sv->args);
+ if (sv->proc_list) skip_free(sv->proc_list);
- free(sv);
+ free(sv);
}
service_t find_service(char *name)
{
- service_t *sp;
- if (name == NULL) return NULL;
- sp = skip_search(services, name);
- if (sp)
- return *sp;
- else
- return NULL;
+ service_t *sp;
+ if (name == NULL) return NULL;
+ sp = skip_search(services, name);
+ if (sp)
+ return *sp;
+ else
+ return NULL;
}
This should compare e1 with e2 or (if null) k (a key)
free should free an entry
errfn should do something with an error message
-
+
skip_new(cmp,free,errfn) -> list
skip_insert(list,entry) -> bool
skip_delete(list,key) -> bool
typedef struct node
{
- valueType value; /* must be first for skip_next to work */
- struct node *forward[1]; /* variable sized array of forward pointers */
+ valueType value; /* must be first for skip_next to work */
+ struct node *forward[1]; /* variable sized array of forward pointers */
} *node;
typedef struct list
{
- int level; /* Maximum level of the list
- (1 more than the number of levels in the list) */
- node header; /* pointer to head of list */
- int (*cmpfn)(); /* compares two values or a key an a value */
- void (*freefn)(); /* free a value */
- void (*errfn)(); /* when malloc error occurs */
+ int level; /* Maximum level of the list
+ (1 more than the number of levels in the list) */
+ node header; /* pointer to head of list */
+ int (*cmpfn)(); /* compares two values or a key an a value */
+ void (*freefn)(); /* free a value */
+ void (*errfn)(); /* when malloc error occurs */
} *list;
static void default_errfn(char *msg)
{
- write(2, msg, (int)strlen(msg));
- write(2, "\n", 2);
- abort();
+ write(2, msg, (int)strlen(msg));
+ write(2, "\n", 2);
+ abort();
}
static int randomsLeft = 0;
static int randomBits;
-list skip_new(cmpfn, freefn, errfn)
-int (*cmpfn)();
-void (*freefn)();
-void (*errfn)();
+list skip_new(
+ int (*cmpfn)(),
+ void (*freefn)(),
+ void (*errfn)())
{
- list l;
- int i;
-
- if (errfn == NULL)
- errfn = default_errfn;
- l = (list)malloc(sizeof(struct list));
- if (l == NULL)
- {
- (*errfn)("Malloc failed in skip_new");
- return NULL;
- }
- l->level = 0;
- l->header = newNodeOfLevel(MaxNumberOfLevels);
- if (l->header == NULL)
- {
- (*errfn)("Malloc failed in skip_new");
- return NULL;
- }
- for (i=0; i<MaxNumberOfLevels; i++)
- l->header->forward[i] = NULL;
- l->header->value = NULL;
- l->cmpfn = cmpfn;
- l->freefn = freefn;
- if (errfn)
- l->errfn = errfn;
- else
- l->errfn = default_errfn;
- return l;
+ list l;
+ int i;
+
+ if (errfn == NULL)
+ errfn = default_errfn;
+ l = (list)malloc(sizeof(struct list));
+ if (l == NULL)
+ {
+ (*errfn)("Malloc failed in skip_new");
+ return NULL;
+ }
+ l->level = 0;
+ l->header = newNodeOfLevel(MaxNumberOfLevels);
+ if (l->header == NULL)
+ {
+ (*errfn)("Malloc failed in skip_new");
+ return NULL;
+ }
+ for (i=0; i<MaxNumberOfLevels; i++)
+ l->header->forward[i] = NULL;
+ l->header->value = NULL;
+ l->cmpfn = cmpfn;
+ l->freefn = freefn;
+ if (errfn)
+ l->errfn = errfn;
+ else
+ l->errfn = default_errfn;
+ return l;
}
-void skip_free(l)
-list l;
+void skip_free(list l)
{
- register node p;
- p = l->header;
- while (p != NULL)
- {
- register node q;
- q = p->forward[0];
- if (p != l->header) /* header has no meaningful value */
- (*l->freefn)(p->value);
- free(p);
- p = q;
- }
- free(l);
+ register node p;
+ p = l->header;
+ while (p != NULL)
+ {
+ register node q;
+ q = p->forward[0];
+ if (p != l->header) /* header has no meaningful value */
+ (*l->freefn)(p->value);
+ free(p);
+ p = q;
+ }
+ free(l);
}
static int randomLevel()
{
- register int level = 0;
- register int b;
- do {
- if (randomsLeft == 0) {
+ register int level = 0;
+ register int b;
+ do {
+ if (randomsLeft == 0) {
#ifdef POSIX
- randomBits = lrand48();
+ randomBits = lrand48();
#else
- randomBits = random();
+ randomBits = random();
#endif
- randomsLeft = BitsInRandom/2;
- }
- b = randomBits&3;
- randomBits>>=2;
- randomsLeft--;
- if (!b) level++;
- } while (!b);
- return(level>MaxLevel ? MaxLevel : level);
+ randomsLeft = BitsInRandom/2;
+ }
+ b = randomBits&3;
+ randomBits>>=2;
+ randomsLeft--;
+ if (!b) level++;
+ } while (!b);
+ return(level>MaxLevel ? MaxLevel : level);
}
-boolean skip_insert(l, value)
-list l;
-valueType value;
+boolean skip_insert(list l, valueType value)
{
- int k;
- node update[MaxNumberOfLevels];
- node p,q;
- int cm=0;
-
- p = l->header;
- for (k=l->level ; k>=0 ; k--)
- {
- cm = 1;
- while ( p->forward[k] != NULL
- && (cm=(*l->cmpfn)(p->forward[k]->value, value, 0))<0)
- p = p->forward[k];
- update[k] = p;
- }
-
- if (cm == 0)
- return false;
-
- k = randomLevel();
- if (k> l->level)
- {
- k = ++l->level;
- update[k] = l->header;
- }
- q = newNodeOfLevel(k);
- if (q == NULL)
- {
- (*l->errfn)("Malloc failed in skip_insert");
- return false;
- }
- q->value = value;
- for ( ; k>=0 ; k--)
- {
- p = update[k];
- q->forward[k] = p->forward[k];
- p->forward[k] = q;
- }
- return true;
+ int k;
+ node update[MaxNumberOfLevels];
+ node p,q;
+ int cm=0;
+
+ p = l->header;
+ for (k=l->level ; k>=0 ; k--)
+ {
+ cm = 1;
+ while ( p->forward[k] != NULL
+ && (cm=(*l->cmpfn)(p->forward[k]->value, value, 0))<0)
+ p = p->forward[k];
+ update[k] = p;
+ }
+
+ if (cm == 0)
+ return false;
+
+ k = randomLevel();
+ if (k> l->level)
+ {
+ k = ++l->level;
+ update[k] = l->header;
+ }
+ q = newNodeOfLevel(k);
+ if (q == NULL)
+ {
+ (*l->errfn)("Malloc failed in skip_insert");
+ return false;
+ }
+ q->value = value;
+ for ( ; k>=0 ; k--)
+ {
+ p = update[k];
+ q->forward[k] = p->forward[k];
+ p->forward[k] = q;
+ }
+ return true;
}
-boolean skip_delete(l, key)
-list l;
-keyType key;
+boolean skip_delete(list l, keyType key)
{
- int k, m;
- node update[MaxNumberOfLevels];
- node p,q;
- int cm = 0;
-
- p = l->header;
-
- for (k=l->level ; k>=0 ; k--)
- {
- cm = 1;
- while ( p->forward[k] != NULL
- && (cm=(*l->cmpfn)(p->forward[k]->value, NULL, key))<0)
- p = p->forward[k];
- update[k] = p;
- }
-
- if (cm == 0)
- {
- q = update[0]->forward[0];
- m=l->level;
- for (k=0; k<=m && (p=update[k])->forward[k] == q ; k++)
- p->forward[k] = q->forward[k];
- if (l->freefn)
- (*l->freefn)(q->value);
- free(q);
- while (l->header->forward[m] == NULL && m > 0)
- m--;
- l->level = m;
- return true;
- }
- else
- return false;
+ int k, m;
+ node update[MaxNumberOfLevels];
+ node p,q;
+ int cm = 0;
+
+ p = l->header;
+
+ for (k=l->level ; k>=0 ; k--)
+ {
+ cm = 1;
+ while ( p->forward[k] != NULL
+ && (cm=(*l->cmpfn)(p->forward[k]->value, NULL, key))<0)
+ p = p->forward[k];
+ update[k] = p;
+ }
+
+ if (cm == 0)
+ {
+ q = update[0]->forward[0];
+ m=l->level;
+ for (k=0; k<=m && (p=update[k])->forward[k] == q ; k++)
+ p->forward[k] = q->forward[k];
+ if (l->freefn)
+ (*l->freefn)(q->value);
+ free(q);
+ while (l->header->forward[m] == NULL && m > 0)
+ m--;
+ l->level = m;
+ return true;
+ }
+ else
+ return false;
}
-valueType *skip_search(l, key)
-list l;
-keyType key;
+valueType *skip_search(list l, keyType key)
{
- int k;
- node p;
- int cm = 0;
-
- p = l->header;
- for (k=l->level ; k>=0 ; k--)
- {
- cm = 1;
- while ( p->forward[k] != NULL
- && (cm=(*l->cmpfn)(p->forward[k]->value, NULL, key))<0)
- p = p->forward[k];
- }
- if (cm != 0)
- return NULL;
- return &p->forward[0]->value;
+ int k;
+ node p;
+ int cm = 0;
+
+ p = l->header;
+ for (k=l->level ; k>=0 ; k--)
+ {
+ cm = 1;
+ while ( p->forward[k] != NULL
+ && (cm=(*l->cmpfn)(p->forward[k]->value, NULL, key))<0)
+ p = p->forward[k];
+ }
+ if (cm != 0)
+ return NULL;
+ return &p->forward[0]->value;
}
-valueType *skip_first(l)
-list l;
+valueType *skip_first(list l)
{
- node p;
+ node p;
- p = l->header;
- if (p->forward[0] == NULL)
- return NULL;
- return & p->forward[0]->value;
+ p = l->header;
+ if (p->forward[0] == NULL)
+ return NULL;
+ return & p->forward[0]->value;
}
-valueType *skip_next(c)
-valueType *c;
+valueType *skip_next(valueType *c)
{
- node p;
- p = (node)c;
- if (p->forward[0] == NULL)
- return NULL;
- return & p->forward[0]->value;
+ node p;
+ p = (node)c;
+ if (p->forward[0] == NULL)
+ return NULL;
+ return & p->forward[0]->value;
}
#include <string.h>
-int strnccmp(a,b, n)
+int strncasecmp(a,b, n)
char *a, *b;
int n;
{
- char ac=0, bc=0;
+ char ac=0, bc=0;
- while(n--)
- {
- ac = *a++;
- if (ac>='a' && ac <= 'z') ac -= 'a'-'A';
- bc = *b++;
- if (bc>='a' && bc <= 'z') bc -= 'a'-'A';
- if (ac == 0 || ac != bc) break;
- }
- if (ac<bc) return -1;
- if (ac > bc) return 1;
- return 0;
+ while(n--)
+ {
+ ac = *a++;
+ if (ac>='a' && ac <= 'z') ac -= 'a'-'A';
+ bc = *b++;
+ if (bc>='a' && bc <= 'z') bc -= 'a'-'A';
+ if (ac == 0 || ac != bc) break;
+ }
+ if (ac<bc) return -1;
+ if (ac > bc) return 1;
+ return 0;
}
-int strccmp(a,b)
+int strcasecmp(a,b)
char *a, *b;
{
- return strnccmp(a,b,(int)strlen(a)+1);
+ return strncasecmp(a,b,(int)strlen(a)+1);
}
char *strdup(char *s)
{
- if (s==NULL)
- return s;
- return (char *)strcpy(malloc(strlen(s)+1), s);
+ if (s==NULL)
+ return s;
+ return (char *)strcpy(malloc(strlen(s)+1), s);
}
char *strndup(char *s, int a)
{
- char *r;
- if (s == NULL)
- return s;
+ char *r;
+ if (s == NULL)
+ return s;
- r = (char*)malloc(a+1);
- strncpy(r, s, a);
- r[a] = 0;
- return r;
+ r = (char*)malloc(a+1);
+ strncpy(r, s, a);
+ r[a] = 0;
+ return r;
}
}
}
-
-
static int stream_prefork(service_t sv)
{
int f;
stream_t s = sv->classinfo;
if (s->sock < 0)
return -2;
-
+
s->newsock = accept(s->sock, NULL, 0);
if (s->newsock < 0)
return -2;
send_int(c(sv)->sock>=0);
}
-struct class stream_class =
-{ "stream", stream_opt, stream_register, stream_check,
- stream_copy, stream_freestate, stream_send,
- stream_unregister, stream_newparent, stream_newchild,
- stream_prefork
+struct class stream_class = {
+ .class = "stream",
+ .c_process_opt = stream_opt,
+ .register_service= stream_register,
+ .c_check_service= stream_check,
+ .copy_state = stream_copy,
+ .free_state = stream_freestate,
+ .send_class = stream_send,
+ .disable_service= stream_unregister,
+ .new_parent = stream_newparent,
+ .new_child = stream_newchild,
+ .prefork = stream_prefork,
};
-
char **strlistdup(char **l)
{
- int len = 0;
- char **rv;
- while (l[len]) len++;
-
- rv = (char**)malloc((len+1)*sizeof(char *));
- for (len=0 ; l[len]; len++)
- rv[len] = strdup(l[len]);
- rv[len] = NULL;
- return rv;
+ int len = 0;
+ char **rv;
+ while (l[len]) len++;
+
+ rv = (char**)malloc((len+1)*sizeof(char *));
+ for (len=0 ; l[len]; len++)
+ rv[len] = strdup(l[len]);
+ rv[len] = NULL;
+ return rv;
}
void strlistfree(char **l)
{
- int i;
- for (i=0 ; l[i] ; i++)
- free(l[i]);
- free(l);
+ int i;
+ for (i=0 ; l[i] ; i++)
+ free(l[i]);
+ free(l);
}
#include <stdio.h>
/*
- * split a string into an array of strings,
+ * split a string into an array of strings,
* separated by any chars in the fs string
* strings may contain chars from fs if quoted
* quotes may be escaped or quoted
*/
char **
-strsplit(s, fs)
-char *s, *fs;
+strsplit(char *s, char *fs)
{
register char *sp, *sp2, *delim, **ssp, *ns;
register unsigned i, num;
* 2.02 31oct95 metad: pidfile and watch_output options, minor improvements to logging
* metac: understand new protocol phrases for pidfile and watch_output
* 2.01 25oct95 metad: zero holdtimes when run command received
- * metac: improve listings: brief and long, hostname included
+ * metac: improve listings: brief and long, hostname included
*
*/