Patch from Christian Meyer:
[oweals/busybox.git] / networking / udhcp / common.c
1 /* common.c
2  *
3  * Functions to assist in the writing and removing of pidfiles.
4  *
5  * Russ Dill <Russ.Dill@asu.edu> Soptember 2001
6  * Rewrited by Vladimir Oleynik <dzo@simtreas.ru> (C) 2003
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  */
22
23 #include <fcntl.h>
24 #include <unistd.h>
25 #include <errno.h>
26 #include <string.h>
27 #include <stdlib.h>
28 #include <signal.h>
29 #include <sys/socket.h>
30
31 #include "common.h"
32
33
34 static int daemonized;
35
36 #ifdef CONFIG_FEATURE_UDHCP_SYSLOG
37
38 void udhcp_logging(int level, const char *fmt, ...)
39 {
40         int e = errno;
41         va_list p;
42         va_list p2;
43
44         va_start(p, fmt);
45         __va_copy(p2, p);
46         if(!daemonized) {
47                 vprintf(fmt, p);
48                 putchar('\n');
49                 errno = e;
50         }
51         vsyslog(level, fmt, p2);
52         va_end(p);
53 }
54
55 void start_log(const char *client_server)
56 {
57         openlog(bb_applet_name, LOG_PID | LOG_CONS, LOG_LOCAL0);
58         udhcp_logging(LOG_INFO, "%s (v%s) started", client_server, VERSION);
59 }
60
61 #else
62
63 static char *syslog_level_msg[] = {
64         [LOG_EMERG]   = "EMERGENCY!",
65         [LOG_ALERT]   = "ALERT!",
66         [LOG_CRIT]    = "critical!",
67         [LOG_WARNING] = "warning",
68         [LOG_ERR]     = "error",
69         [LOG_INFO]    = "info",
70         [LOG_DEBUG]   = "debug"
71 };
72
73 void udhcp_logging(int level, const char *fmt, ...)
74 {
75         int e = errno;
76         va_list p;
77
78         va_start(p, fmt);
79         if(!daemonized) {
80                 printf("%s, ", syslog_level_msg[level]);
81                 errno = e;
82                 vprintf(fmt, p);
83                 putchar('\n');
84         }
85         va_end(p);
86 }
87
88 void start_log(const char *client_server)
89 {
90         udhcp_logging(LOG_INFO, "%s (v%s) started", client_server, VERSION);
91 }
92 #endif
93
94 static const char *saved_pidfile;
95
96 static void exit_fun(void)
97 {
98         if (saved_pidfile) unlink(saved_pidfile);
99 }
100
101 void background(const char *pidfile)
102 {
103         int pid_fd = -1;
104
105         if (pidfile) {
106                 pid_fd = open(pidfile, O_CREAT | O_WRONLY, 0644);
107                 if (pid_fd < 0) {
108                         LOG(LOG_ERR, "Unable to open pidfile %s: %m", pidfile);
109                 } else {
110                         lockf(pid_fd, F_LOCK, 0);
111                         if(!saved_pidfile)
112                                 atexit(exit_fun);       /* set atexit one only */
113                         saved_pidfile = pidfile;        /* but may be rewrite */
114                 }
115         }
116         while (pid_fd >= 0 && pid_fd < 3) pid_fd = dup(pid_fd); /* don't let daemon close it */
117         if (daemon(0, 0) == -1) {
118                 perror("fork");
119                 exit(1);
120         }
121         daemonized++;
122         if (pid_fd >= 0) {
123                 FILE *out;
124
125                 if ((out = fdopen(pid_fd, "w")) != NULL) {
126                         fprintf(out, "%d\n", getpid());
127                         fclose(out);
128                 }
129                 lockf(pid_fd, F_UNLCK, 0);
130                 close(pid_fd);
131         }
132 }
133
134 /* Signal handler */
135 int udhcp_signal_pipe[2];
136 static void signal_handler(int sig)
137 {
138         if (send(udhcp_signal_pipe[1], &sig, sizeof(sig), MSG_DONTWAIT) < 0) {
139                 LOG(LOG_ERR, "Could not send signal: %m");
140         }
141 }
142
143 void udhcp_set_signal_pipe(int sig_add)
144 {
145         socketpair(AF_UNIX, SOCK_STREAM, 0, udhcp_signal_pipe);
146         signal(SIGUSR1, signal_handler);
147         signal(SIGTERM, signal_handler);
148         if(sig_add)
149                 signal(sig_add, signal_handler);
150 }