<Begin schedule.h>
#define NUMEVENTS 100 #define MAXFDS 20 char * host = "crabapple"; char * port = "5432"; char * tty = ""; char * option = ""; char * dbname = "jim"; char* LOGFILE = "/usr/schedule/schedlog"; void update(char*,char*);<Begin schedule.c>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <bits/signum.h>
#include <string.h>
#include <time.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <bits/waitflags.h>
#include <libpq-fe.h>
#include <sqlca.h>
#include "schedule.h"
struct {
char days[8];
char time[6];
char program[101];
char checkprog[101];
char didrun[2];
} schedule[NUMEVENTS];
PGconn *conn;
FILE *LOG;
void
openlog()
{
LOG = fopen(LOGFILE,"w");
if(!LOG){
exit(EXIT_FAILURE);
}
}
void logit(char * message)
{
fprintf(LOG,"%s\n",message);
return;
}
int read_config()
{
int i;
PGresult *res;
char buf[100];
conn = PQsetdb(host,port,tty,option,dbname);
if(PQstatus(conn) == CONNECTION_BAD){
logit("Connection to database failed.");
sprintf(buf, "%s", PQerrorMessage(conn));
logit(buf);
exit(EXIT_FAILURE);
}
res = PQexec(conn,"BEGIN");
if(PQresultStatus(res) != PGRES_COMMAND_OK){
logit("Begin command failed.");
exit(EXIT_FAILURE);
}
PQclear(res);
res = PQexec(conn,"declare mycursor cursor for select * from schedule where didrun = 'N'");
if(PQresultStatus(res) != PGRES_COMMAND_OK){
logit("Cursor command failed.");
exit(EXIT_FAILURE);
}
PQclear(res);
res = PQexec(conn,"FETCH ALL IN mycursor");
if(PQresultStatus(res) != PGRES_TUPLES_OK){
logit("Fetch failed.");
exit(EXIT_FAILURE);
}
for(i = 0; i < NUMEVENTS; i++){
strcpy(schedule[i].didrun,"Y");
}
for(i = 0;i < PQntuples(res);i++){
strncpy(schedule[i].days,PQgetvalue(res,i,0),7);
schedule[i].days[PQgetlength(res,i,0) + 4] = '\0';
strncpy(schedule[i].time,PQgetvalue(res,i,1),5);
schedule[i].time[PQgetlength(res,i,1) + 4] = '\0';
strncpy(schedule[i].program,PQgetvalue(res,i,2),100);
schedule[i].program[PQgetlength(res,i,2) + 4] = '\0';
strncpy(schedule[i].checkprog,PQgetvalue(res,i,3),100);
schedule[i].checkprog[PQgetlength(res,i,3) + 4] = '\0';
strncpy(schedule[i].didrun,PQgetvalue(res,i,4),1);
schedule[i].didrun[1] = '\0';
}
schedule[i].days[0] = '\0';
PQclear(res);
res = PQexec(conn,"CLOSE mycursor");
PQclear(res);
res = PQexec(conn,"END");
PQclear(res);
PQfinish(conn);
return 0;
}
void
update(char *prog,char *state)
{
char buf[200];
PGresult *res;
conn = PQsetdb(host,port,tty,option,dbname);
if(PQstatus(conn) == CONNECTION_BAD){
logit("Connection to database failed.");
exit(EXIT_FAILURE);
}
sprintf(buf,"update schedule set didrun = \'%s\' \
where program = \'%s\'",state,prog);
res = PQexec(conn,"BEGIN");
if(PQresultStatus(res) != PGRES_COMMAND_OK){
exit(EXIT_FAILURE);
}
PQclear(res);
res = PQexec(conn,buf);
if(PQresultStatus(res) != PGRES_COMMAND_OK){
exit(EXIT_FAILURE);
}
PQclear(res);
PQexec(conn,"COMMIT");
PQfinish(conn);
return;
}
void
dofork(int j)
{
int k,hour,min;
char msg[120];
pid_t pid;
time_t t;
struct tm *tmp;
time(&t);
tmp = localtime(&t);
hour = tmp->tm_hour;
min = tmp->tm_min;
pid = fork();
if(pid == 0) { /* This is the child. */
update(schedule[j].program,"P");
k = system(schedule[j].checkprog);
if(k == 0){
;
} else {
update(schedule[j].program,"N");
sprintf(msg,"%s failed at %02d:%02d",schedule[j].checkprog,hour,min);
logit(msg);
exit(EXIT_FAILURE);
}
k = system(schedule[j].program);
time(&t);
tmp = localtime(&t);
hour = tmp->tm_hour;
min = tmp->tm_min;
if(k == 0){
update(schedule[j].program,"Y");
sprintf(msg,"%s succeeded at %02d:%02d",schedule[j].program,hour,min);
logit(msg);
exit(EXIT_SUCCESS);
} else {
update(schedule[j].program,"N");
sprintf(msg,"%s FAILED at %02d:%02d",schedule[j].program,hour,min);
logit(msg);
exit(EXIT_FAILURE);
}
} else { /* This is the parent */
sleep(30); /* Give the child some time */
read_config();
return;
}
}
void
scheduler(void)
{
int j = 0,day,hour,min,k,l;
time_t t;
struct tm *tmp;
while(1){
time(&t);
tmp = localtime(&t);
hour = tmp->tm_hour;
min = tmp->tm_min;
day = tmp->tm_wday;
if(schedule[j].days[day] == 'N'){
j++;
if(schedule[j].days[0] == '\0'){
j = 0;
sleep(60);
read_config();
continue;
}
continue;
}
sscanf(schedule[j].time,"%02d:%02d",&k,&l);
if((hour > k) || ((k == hour) && (min >= l))){
if(schedule[j].didrun[0] == 'N'){
dofork(j);
j++;
if(schedule[j].days[0] == '\0'){
j = 0;
sleep(60);
read_config();
continue;
}
continue;
} else {
j++;
if(schedule[j].days[0] == '\0'){
j = 0;
sleep(60);
read_config();
continue;
}
continue;
}
}
j++;
if(schedule[j].days[0] == '\0'){
j = 0;
sleep(60);
read_config();
}
}
}
void
do_exit(int signo)
{
char buf[100];
time_t t;
int hour,min;
struct tm *tmp;
if(signo != SIGUSR1){
;
}
time(&t);
tmp = localtime(&t);
hour = tmp->tm_hour;
min = tmp->tm_min;
sprintf(buf,"Killed at %02d:%02d.",hour,min);
logit(buf);
exit(EXIT_SUCCESS);
}
void
sig_child(int signo)
{
pid_t pid;
int stat;
if(signo != SIGCHLD){
;
}
signal(SIGCHLD,sig_child);
while((pid = waitpid(-1, &stat, WNOHANG)) > 0);
return;
}
void setup()
{
signal(SIGHUP,SIG_IGN);
signal(SIGINT,SIG_IGN);
signal(SIGQUIT,SIG_IGN);
signal(SIGILL,SIG_IGN);
signal(SIGTRAP,SIG_IGN);
signal(SIGABRT,SIG_IGN);
signal(SIGIOT,SIG_IGN);
signal(SIGBUS,SIG_IGN);
signal(SIGFPE,SIG_IGN);
signal(SIGKILL,SIG_IGN);
signal(SIGUSR1,do_exit);
signal(SIGSEGV,SIG_IGN);
signal(SIGUSR2,SIG_IGN);
signal(SIGPIPE,SIG_IGN);
signal(SIGALRM,SIG_IGN);
signal(SIGTERM,SIG_IGN);
signal(SIGCHLD,sig_child);
}
void daemonize()
{
int i;
pid_t pid;
if((pid = fork()) != 0){
exit(EXIT_SUCCESS);
}
setsid();
if((pid = fork()) != 0){
exit(EXIT_SUCCESS);
}
chdir("/");
umask(0);
for(i = 0; i < MAXFDS; i++){
close(i);
}
}
int
main(void)
{
int j;
system("at -f /usr/schedule/reset.sh midnight");
daemonize();
setup();
openlog();
j = read_config();
if(j != 0){
exit(EXIT_FAILURE);
}
scheduler();
exit(EXIT_SUCCESS);
}
<Begin Makefile>
schedule: schedule.c gcc -g -W -Wall -ansi -pedantic schedule.c -o schedule -lpq