root/fwknop/tags/fwknop-1.8.4-pre2/fwknop_funcs.c

Revision 629, 8.6 kB (checked in by mbr, 2 years ago)

first cut at recursive variable resolution

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /*
2 ********************************************************************************
3 *
4 *  File: fwknop_funcs.c
5 *
6 *  Purpose: fwknop_funcs.c contains several functions that are needed by
7 *           the fwkmd and fwkwd daemons, so putting these functions in
8 *           a single file make sense.
9 *
10 *  Author: Michael Rash (mbr@cipherdyne.org)
11 *
12 *  Version: 0.1
13 *
14 *  Copyright (C) 2004 Michael Rash (mbr@cipherdyne.org)
15 *
16 *  License (GNU Public License):
17 *
18 *     This program is distributed in the hope that it will be useful,
19 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
20 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 *     GNU General Public License for more details.
22 *
23 *     You should have received a copy of the GNU General Public License
24 *     along with this program; if not, write to the Free Software
25 *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
26 *     USA
27 *
28 ********************************************************************************
29 *
30 *  $Id$
31 */
32
33 /* includes */
34 #include "fwknop.h"
35
36 /* shared functions */
37 void slogr(const char *ident, const char *msg) {
38     openlog(ident, LOG_DAEMON, LOG_LOCAL7);
39     syslog(LOG_INFO, "%s", msg);
40     closelog();
41     return;
42 }
43
44 void check_unique_pid(const char *pid_file, const char *prog_name)
45 {
46     FILE *pidfile_ptr;
47     pid_t pid;
48     char pid_line[MAX_PID_SIZE+1];
49
50 #ifdef DEBUG
51     fprintf(stderr,
52         "[+] check_unique_pid(): opening pid file %s\n", pid_file);
53 #endif
54
55     if ((pidfile_ptr = fopen(pid_file, "r")) == NULL) {
56         /* the pid file must not exist (or we can't read it), so
57          * return... write_pid() will create it */
58         return;
59     }
60
61     /* read the first line of the pid_file, which will contain the
62      * process id of any running fwkmd process */
63     if (fgets(pid_line, MAX_PID_SIZE+1, pidfile_ptr) == NULL) {
64         return;
65     }
66
67     /* turn the pid_line into an integer */
68     pid = atoi(pid_line);
69
70     /* close the pid_file now that we have read it */
71     fclose(pidfile_ptr);
72
73 #ifdef DEBUG
74     fprintf(stderr,
75         "[+] check_unique_pid(): checking pid: %d with kill 0\n", pid);
76 #endif
77
78     if (kill(pid, 0) == 0) {  /* another prog_name is already running */
79         fprintf(stderr, "[*] %s is already running as pid: %d\n",
80             prog_name, pid);
81         exit(EXIT_FAILURE);
82     } else {
83         return;
84     }
85
86     return; /* for completness */
87 }
88
89 void write_pid(const char *pid_file, const pid_t pid)
90 {
91     FILE *pidfile_ptr;
92
93     if ((pidfile_ptr = fopen(pid_file, "w")) == NULL) {
94         /* could not open the pid file */
95         fprintf(stderr, "[*] Could not open the pid file: %s", pid_file);
96         exit(EXIT_FAILURE);
97     }
98
99     /* write the pid to the pid file */
100     if (fprintf(pidfile_ptr, "%d\n", pid) == 0) {
101         fprintf(stderr, "[*] pid: %d could not be written to pid file: %s",
102                 pid, pid_file);
103         exit(EXIT_FAILURE);
104     }
105
106     /* the pid_file now that we have read it */
107     fclose(pidfile_ptr);
108
109     return;
110 }
111
112 int find_char_var(char *search_str, char *charvar, char *line)
113 {
114     char *index_tmp;
115     int char_ctr = 0, i;
116
117     index_tmp = line;
118
119     /* look for specific variables in the config
120      * file that match the search_str */
121
122     for (i=0; i < strlen(search_str); i++)
123         if (index_tmp[i] != search_str[i])
124             return 0;
125
126 #ifdef DEBUG
127     fprintf(stderr, "[+] find_char_var(): found %s in line: %s",
128             search_str, line);
129 #endif
130
131     /* increment the pointer past the variable name */
132     while (*index_tmp != ' ') index_tmp++;
133
134     /* increment the pointer past the whitespace
135      * before the variable value */
136     while (*index_tmp == ' ') index_tmp++;
137
138     /* make sure that the variable has a semicolon
139      * at the end of the line */
140
141     /* get the number of characters in the variable
142      * before the ending semicolon */
143     while (index_tmp[char_ctr] != ';' && index_tmp[char_ctr] != '\0' &&
144            index_tmp[char_ctr] != '\n')
145         char_ctr++;
146
147     if (index_tmp[char_ctr] != ';') {
148         fprintf(stderr,
149             "[*] find_char_var(): No ending semicolon found for: %s.\n",
150             search_str);
151         exit(EXIT_FAILURE);
152     }
153
154     if (char_ctr > MAX_GEN_LEN-1) {
155         fprintf(stderr,
156                 "[*] find_char_var(): the config line for %s is too long.  Exiting.\n",
157                 search_str);
158         exit(EXIT_FAILURE);
159     }
160
161     strncpy(charvar, index_tmp, char_ctr);
162     charvar[char_ctr] = '\0'/* replace the ';' with the NULL character */
163     return 1;
164 }
165
166 void *safe_malloc(const unsigned int len)
167 {
168     void *buf = NULL;
169     buf = malloc(len);
170     if (buf == NULL) {
171         fprintf(stderr, "[*] Could not malloc() %d bytes\n", len);
172         exit(EXIT_FAILURE);
173     }
174     return buf;
175 }
176
177 int has_sub_var(char *var_name, char *value, char *sub_var,
178     char *pre_str, char *post_str)
179 {
180     unsigned int i, sub_var_ctr = 0, found_sub_var = 0;
181     unsigned int pre_str_ctr = 0, found_pre_str = 1;
182     unsigned int post_str_ctr = 0, found_post_str = 0;
183     unsigned int found_one_var = 0;
184
185     sub_var[0]  = '\0';
186     pre_str[0]  = '\0';
187     post_str[0] = '\0';
188
189     for (i=0; i < strlen(value); i++) {
190         if (found_sub_var) {
191             if (! isdigit(value[i])
192                     && ! isalpha(value[i]) && value[i] != '_') {
193                 found_sub_var  = 0;
194                 found_post_str = 1;
195                 found_one_var  = 1;
196             } else {
197                 if (! found_one_var) {
198                     sub_var[sub_var_ctr] = value[i];
199                     sub_var_ctr++;
200                 }
201             }
202         }
203
204         if (found_pre_str && value[i] != '$') {
205             pre_str[pre_str_ctr] = value[i];
206             pre_str_ctr++;
207         }
208
209         if (found_post_str) {
210             post_str[post_str_ctr] = value[i];
211             post_str_ctr++;
212         }
213
214         if (value[i] == '$') {
215             found_sub_var = 1;
216             found_pre_str = 0;
217             pre_str[pre_str_ctr] = '\0';
218         }
219     }
220     if (sub_var_ctr >= MAX_GEN_LEN - 1) {
221         printf("[*] Sub-var length exceeds maximum of %d chars within var: %s\n",
222                 MAX_GEN_LEN, var_name);
223         exit(EXIT_FAILURE);
224     }
225     if (sub_var[0] != '\0') {
226         sub_var[sub_var_ctr]   = '\0';
227         post_str[post_str_ctr] = '\0';
228         if (strncmp(sub_var, var_name, MAX_GEN_LEN) == 0) {
229             printf("[*] Cannot have identical var to sub-var: %s\n",
230                     sub_var);
231             exit(EXIT_FAILURE);
232         }
233         return 1;
234     }
235
236     return 0;
237 }
238
239 void expand_sub_var_value(char *value, const char *sub_var,
240     const char *pre_str, const char *post_str)
241 {
242     if (strlen(sub_var) + strlen(pre_str) + strlen(post_str)
243             > MAX_GEN_LEN) {
244         printf("[*] Variable value too long: %s%s%s\n",
245             sub_var, pre_str, post_str);
246         exit(EXIT_FAILURE);
247     }
248     strlcpy(value, pre_str, MAX_GEN_LEN);
249     strlcat(value, sub_var, MAX_GEN_LEN);
250     strlcat(value, post_str, MAX_GEN_LEN);
251     return;
252 }
253
254 /*
255  * Do everything required to cleanly become a daemon: fork(), start
256  * a new session, chdir "/", and close un-needed standard filehandles.
257  */
258 void daemonize_process(const char *pid_file)
259 {
260     pid_t child_pid, sid;
261
262     if ((child_pid = fork()) < 0) {
263         fprintf(stderr, "[*] Could not fork()");
264         exit(EXIT_FAILURE);
265     }
266
267     if (child_pid > 0) {
268 #ifdef DEBUG
269         fprintf(stderr, "[+] writing pid: %d to pid file: %s\n",
270                 child_pid, pid_file);
271 #endif
272         write_pid(pid_file, child_pid);
273         exit(EXIT_SUCCESS);   /* exit the parent process */
274     }
275
276     /*
277      * Now we are in the child process
278      */
279
280     /* start a new session */
281     if ((sid = setsid()) < 0) {
282         fprintf(stderr, "[*] setsid() Could not start a new session");
283         exit(EXIT_FAILURE);
284     }
285
286     /* make "/" the current directory */
287     if ((chdir("/")) < 0) {
288         fprintf(stderr, "[*] Could not chdir() to /");
289         exit(EXIT_FAILURE);
290     }
291
292     /* reset the our umask (for completeness) */
293     umask(0);
294
295     /* close un-needed file handles */
296     close(STDIN_FILENO);
297     close(STDOUT_FILENO);
298     close(STDERR_FILENO);
299
300     return;
301 }
302
303 void send_alert_email(const char *shCmd, const char *mailCmd,
304         const char *mail_str)
305 {
306     char mail_line[MAX_MSG_LEN] = "";
307     pid_t child_pid;
308
309     snprintf(mail_line, MAX_MSG_LEN, "%s %s",
310             mailCmd, mail_str);
311     mail_line[MAX_MSG_LEN-1] = '\0';
312     if ((child_pid = fork()) < 0)
313         /* could not fork */
314         exit(EXIT_FAILURE);
315     else if (child_pid > 0)
316         wait(NULL);  /* mail better work */
317     else
318         execle(shCmd, shCmd, "-c", mail_line, NULL, NULL);  /* don't use env */
319     return;
320 }
Note: See TracBrowser for help on using the browser.