/*************************************************************************** * Copyright (C) 2006 by Torben H. Nielsen * * torben@t-hoerup.dk * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ /* daemon.[hc] indeholder alle daemon relaterede functioner incl. * getConfig(); * daemonize(); * writelog(); */ #include #include #include #include #include #include #include #include #include #include "daemon.h" static const char *months[] = { "Jan","Feb","Mar","Apr","May","Jun", "Jul","Aug","Sep","Oct","Nov","Dec" }; // write message to the logfile void log_message(char *message) { FILE *logfile; char buf[30]; long n = time(NULL); struct tm *now; now = localtime(&n); sprintf(buf, "%02d:%02d:%02d %s %02d %02d", now->tm_hour, now->tm_min, now->tm_sec,months[now->tm_mon], now->tm_mday,now->tm_year % 100); if (CONFIG->debug) { printf("%s: %s\n", buf, message); fflush(stdout); } else { logfile = fopen(CONFIG->logfile, "a"); if (!logfile) return; fprintf(logfile, "%s: %s\n", buf, message); fclose(logfile); } } void signal_handler(int sig) { switch(sig) { case SIGHUP: log_message("hangup signal catched"); break; case SIGTERM: log_message("terminate signal catched...exiting"); unlink(CONFIG->lock); daemon_shutdown(0); break; } } void daemonize() { int i, lfp; char str[10]; if (getppid() == 1) /* already a daemon */ return; i=fork(); if (i<0) /* fork error */ daemon_shutdown(FORK_ERROR); if (i>0) /* parent exits */ daemon_shutdown(0); /* child daemon continues */ setsid(); /* obtain a new process group */ for (i=getdtablesize(); i>=0; --i) close(i); /*close all descriptors*/ i=open("/dev/null", O_RDWR); /* handle std. io */ dup(i); dup(i); umask(027); /* set newly created file permissions */ chdir(CONFIG->rundir); /* change running directory*/ //attempt to create lockfile and put a file-lock on it lfp=open(CONFIG->lock, O_RDWR|O_CREAT, 0640); if (lfp<0) /* can not open */ daemon_shutdown(CANT_OPEN_LOCK); if (lockf(lfp,F_TLOCK,0) < 0) /* can not lock */ daemon_shutdown(ALREADY_LOCKED); /* first instance continues */ sprintf(str, "%d\n", getpid() ); /* record pid to lockfile */ write(lfp, str, strlen(str) ); signal(SIGCHLD, SIG_IGN); /* ignore child */ signal(SIGTSTP, SIG_IGN); /* ignore tty signals */ signal(SIGTTOU, SIG_IGN); signal(SIGTTIN, SIG_IGN); signal(SIGHUP, signal_handler); /* catch hangup signal */ signal(SIGTERM, signal_handler); /* catch kill signal */ log_message("downloadd started ..."); } void read_config_file(char *configfile) { char buf[120]; FILE *input = 0; int pos; char *cptr; // first populate config with default values strcpy(CONFIG->logfile, "/tmp/downloadd.log"); strcpy(CONFIG->lock, "/tmp/downloadd.lock"); strcpy(CONFIG->rundir, "/tmp"); strcpy(CONFIG->dbuser, "myuser"); strcpy(CONFIG->dbpass, "mypass"); strcpy(CONFIG->dbhost, "localhost"); strcpy(CONFIG->dbname, "downloadd"); CONFIG->dbport = 3306; // first try to open the file if (configfile && strlen(configfile) >0) { input = fopen(configfile, "r"); if (input) { while (!feof(input)) { fgets(buf, 120, input); pos = strlen(buf); if (strlen(buf)>0 && buf[pos-1] == '\n') buf[pos-1] = 0; //ignore trailing newline if (strlen(buf)==0 || buf[0] == '#' || buf[0] == ';') continue; cptr = strchr(buf, ' '); cptr++; if(strncmp(buf,"logfile ",8)==0) { strcpy(CONFIG->logfile, cptr); } else if (strncmp(buf,"lock ",5)==0) { strcpy(CONFIG->lock, cptr); } else if (strncmp(buf, "rundir ",7)==0) { strcpy(CONFIG->rundir, cptr); } else if (strncmp(buf, "dbuser ",7)==0) { strcpy(CONFIG->dbuser,cptr); } else if (strncmp(buf, "dbpass ",7)==0) { strcpy(CONFIG->dbpass,cptr); } else if (strncmp(buf, "dbhost ",7)==0) { strcpy(CONFIG->dbhost,cptr); } else if (strncmp(buf, "dbname ",7)==0) { strcpy(CONFIG->dbname,cptr); } else if (strncmp(buf, "dbport ",7)==0) { CONFIG->dbport = atoi(cptr); } else { printf("unknown config directive: %s\n", buf); fflush(stdout); } //make the buffer look empty buf[0] = 0; } } else { sprintf(buf,"Could not open config file %s, using default values.", configfile); log_message(buf); } } else { log_message( "No config file specified. Using default values."); } //at the end we should at least validate lock, logfile & rundir } void daemon_shutdown(int errorlevel) { log_message("Shutting down..."); exit(errorlevel); }