1 |
/*************************************************************************** |
2 |
* Copyright (C) 2006 by Torben H. Nielsen * |
3 |
* torben@t-hoerup.dk * |
4 |
* * |
5 |
* This program is free software; you can redistribute it and/or modify * |
6 |
* it under the terms of the GNU General Public License as published by * |
7 |
* the Free Software Foundation; either version 2 of the License, or * |
8 |
* (at your option) any later version. * |
9 |
* * |
10 |
* This program is distributed in the hope that it will be useful, * |
11 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of * |
12 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * |
13 |
* GNU General Public License for more details. * |
14 |
* * |
15 |
* You should have received a copy of the GNU General Public License * |
16 |
* along with this program; if not, write to the * |
17 |
* Free Software Foundation, Inc., * |
18 |
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * |
19 |
***************************************************************************/ |
20 |
|
21 |
/* daemon.[hc] indeholder alle daemon relaterede functioner incl. |
22 |
* getConfig(); |
23 |
* daemonize(); |
24 |
* writelog(); |
25 |
*/ |
26 |
|
27 |
#include <stdlib.h> |
28 |
#include <stdio.h> |
29 |
#include <fcntl.h> |
30 |
#include <signal.h> |
31 |
#include <unistd.h> |
32 |
#include <string.h> |
33 |
#include <time.h> |
34 |
#include <sys/types.h> |
35 |
#include <sys/stat.h> |
36 |
|
37 |
#include "daemon.h" |
38 |
|
39 |
|
40 |
static const char *months[] = { |
41 |
"Jan","Feb","Mar","Apr","May","Jun", |
42 |
"Jul","Aug","Sep","Oct","Nov","Dec" |
43 |
}; |
44 |
|
45 |
// write message to the logfile |
46 |
void log_message(char *message) |
47 |
{ |
48 |
FILE *logfile; |
49 |
char buf[30]; |
50 |
long n = time(NULL); |
51 |
struct tm *now; |
52 |
now = localtime(&n); |
53 |
|
54 |
sprintf(buf, "%02d:%02d:%02d %s %02d %02d", |
55 |
now->tm_hour, now->tm_min, now->tm_sec,months[now->tm_mon], |
56 |
now->tm_mday,now->tm_year % 100); |
57 |
|
58 |
if (CONFIG->debug) { |
59 |
printf("%s: %s\n", buf, message); |
60 |
fflush(stdout); |
61 |
} else { |
62 |
logfile = fopen(CONFIG->logfile, "a"); |
63 |
if (!logfile) |
64 |
return; |
65 |
fprintf(logfile, "%s: %s\n", buf, message); |
66 |
fclose(logfile); |
67 |
} |
68 |
} |
69 |
|
70 |
|
71 |
void signal_handler(int sig) |
72 |
{ |
73 |
switch(sig) { |
74 |
case SIGHUP: |
75 |
log_message("hangup signal catched"); |
76 |
break; |
77 |
case SIGTERM: |
78 |
log_message("terminate signal catched...exiting"); |
79 |
unlink(CONFIG->lock); |
80 |
daemon_shutdown(0); |
81 |
break; |
82 |
} |
83 |
} |
84 |
|
85 |
|
86 |
void daemonize() |
87 |
{ |
88 |
int i, lfp; |
89 |
char str[10]; |
90 |
|
91 |
if (getppid() == 1) /* already a daemon */ |
92 |
return; |
93 |
|
94 |
i=fork(); |
95 |
|
96 |
if (i<0) /* fork error */ |
97 |
daemon_shutdown(FORK_ERROR); |
98 |
if (i>0) /* parent exits */ |
99 |
daemon_shutdown(0); |
100 |
/* child daemon continues */ |
101 |
|
102 |
setsid(); /* obtain a new process group */ |
103 |
|
104 |
for (i=getdtablesize(); i>=0; --i) |
105 |
close(i); /*close all descriptors*/ |
106 |
|
107 |
i=open("/dev/null", O_RDWR); /* handle std. io */ |
108 |
dup(i); |
109 |
dup(i); |
110 |
|
111 |
umask(027); /* set newly created file permissions */ |
112 |
|
113 |
chdir(CONFIG->rundir); /* change running directory*/ |
114 |
|
115 |
//attempt to create lockfile and put a file-lock on it |
116 |
lfp=open(CONFIG->lock, O_RDWR|O_CREAT, 0640); |
117 |
if (lfp<0) /* can not open */ |
118 |
daemon_shutdown(CANT_OPEN_LOCK); |
119 |
if (lockf(lfp,F_TLOCK,0) < 0) /* can not lock */ |
120 |
daemon_shutdown(ALREADY_LOCKED); |
121 |
|
122 |
/* first instance continues */ |
123 |
sprintf(str, "%d\n", getpid() ); /* record pid to lockfile */ |
124 |
write(lfp, str, strlen(str) ); |
125 |
signal(SIGCHLD, SIG_IGN); /* ignore child */ |
126 |
signal(SIGTSTP, SIG_IGN); /* ignore tty signals */ |
127 |
signal(SIGTTOU, SIG_IGN); |
128 |
signal(SIGTTIN, SIG_IGN); |
129 |
signal(SIGHUP, signal_handler); /* catch hangup signal */ |
130 |
signal(SIGTERM, signal_handler); /* catch kill signal */ |
131 |
log_message("downloadd started ..."); |
132 |
} |
133 |
|
134 |
|
135 |
void read_config_file(char *configfile) { |
136 |
char buf[120]; |
137 |
FILE *input = 0; |
138 |
int pos; |
139 |
char *cptr; |
140 |
|
141 |
// first populate config with default values |
142 |
strcpy(CONFIG->logfile, "/tmp/downloadd.log"); |
143 |
strcpy(CONFIG->lock, "/tmp/downloadd.lock"); |
144 |
strcpy(CONFIG->rundir, "/tmp"); |
145 |
|
146 |
strcpy(CONFIG->dbuser, "myuser"); |
147 |
strcpy(CONFIG->dbpass, "mypass"); |
148 |
strcpy(CONFIG->dbhost, "localhost"); |
149 |
strcpy(CONFIG->dbname, "downloadd"); |
150 |
CONFIG->dbport = 3306; |
151 |
|
152 |
// first try to open the file |
153 |
if (configfile && strlen(configfile) >0) { |
154 |
input = fopen(configfile, "r"); |
155 |
|
156 |
if (input) { |
157 |
while (!feof(input)) { |
158 |
fgets(buf, 120, input); |
159 |
|
160 |
pos = strlen(buf); |
161 |
if (strlen(buf)>0 && buf[pos-1] == '\n') |
162 |
buf[pos-1] = 0; //ignore trailing newline |
163 |
|
164 |
if (strlen(buf)==0 || buf[0] == '#' || buf[0] == ';') |
165 |
continue; |
166 |
cptr = strchr(buf, ' '); |
167 |
cptr++; |
168 |
if(strncmp(buf,"logfile ",8)==0) { |
169 |
strcpy(CONFIG->logfile, cptr); |
170 |
} else if (strncmp(buf,"lock ",5)==0) { |
171 |
strcpy(CONFIG->lock, cptr); |
172 |
} else if (strncmp(buf, "rundir ",7)==0) { |
173 |
strcpy(CONFIG->rundir, cptr); |
174 |
} else if (strncmp(buf, "dbuser ",7)==0) { |
175 |
strcpy(CONFIG->dbuser,cptr); |
176 |
} else if (strncmp(buf, "dbpass ",7)==0) { |
177 |
strcpy(CONFIG->dbpass,cptr); |
178 |
} else if (strncmp(buf, "dbhost ",7)==0) { |
179 |
strcpy(CONFIG->dbhost,cptr); |
180 |
} else if (strncmp(buf, "dbname ",7)==0) { |
181 |
strcpy(CONFIG->dbname,cptr); |
182 |
} else if (strncmp(buf, "dbport ",7)==0) { |
183 |
CONFIG->dbport = atoi(cptr); |
184 |
} else { |
185 |
printf("unknown config directive: %s\n", buf); |
186 |
fflush(stdout); |
187 |
} |
188 |
//make the buffer look empty |
189 |
buf[0] = 0; |
190 |
} |
191 |
} else { |
192 |
sprintf(buf,"Could not open config file %s, using default values.", configfile); |
193 |
log_message(buf); |
194 |
} |
195 |
} else { |
196 |
log_message( "No config file specified. Using default values."); |
197 |
} |
198 |
|
199 |
//at the end we should at least validate lock, logfile & rundir |
200 |
} |
201 |
|
202 |
void daemon_shutdown(int errorlevel) { |
203 |
log_message("Shutting down..."); |
204 |
exit(errorlevel); |
205 |
} |