diff --git a/main.c b/main.c index b539132..ec54857 100644 --- a/main.c +++ b/main.c @@ -17,6 +17,8 @@ #include #include #include + + #define DAEMON #else #include #include "win_service.h" @@ -61,6 +63,10 @@ struct params params = { const static char help_text[] = { " -i, --ip, Listening IP, default 0.0.0.0\n" " -p, --port Listening port, default 1080\n" + #ifdef DAEMON + " -D, --daemon Daemonize\n" + " -w, --pidfile Write PID to file\n" + #endif #ifdef __linux__ " -E, --transparent Transparent proxy mode\n" #endif @@ -114,6 +120,10 @@ const static char help_text[] = { const struct option options[] = { + #ifdef DAEMON + {"daemon", 0, 0, 'D'}, + {"pidfile", 1, 0, 'w'}, + #endif {"no-domain", 0, 0, 'N'}, {"no-ipv6", 0, 0, 'X'}, {"no-udp", 0, 0, 'U'}, @@ -439,11 +449,40 @@ void *add(void **root, int *n, size_t ss) } +#ifdef DAEMON +int init_pid_file(const char *fname) +{ + params.pid_fd = open(fname, O_RDWR | O_CREAT, 0640); + if (params.pid_fd < 0) { + return -1; + } + if (lockf(params.pid_fd, F_TLOCK, 0) < 0) { + return -1; + } + params.pid_file = fname; + char pid_str[21]; + snprintf(pid_str, sizeof(pid_str), "%d", getpid()); + + write(params.pid_fd, pid_str, strlen(pid_str)); + return 0; +} +#endif + + void clear_params(void) { #ifdef _WIN32 WSACleanup(); #endif + #ifdef DAEMON + if (params.pid_fd > 0) { + lockf(params.pid_fd, F_ULOCK, 0); + close(params.pid_fd); + } + if (params.pid_file) { + unlink(params.pid_file); + } + #endif if (params.mempool) { mem_destroy(params.mempool); params.mempool = 0; @@ -515,6 +554,9 @@ int main(int argc, char **argv) params.baddr.sin6_family = AF_INET; } + char *pid_file = 0; + bool daemonize = 0; + int rez; int invalid = 0; @@ -548,7 +590,16 @@ int main(int argc, char **argv) params.transparent = 1; break; #endif + + #ifdef DAEMON + case 'D': + daemonize = 1; + break; + case 'w': + pid_file = optarg; + break; + #endif case 'h': printf(help_text); clear_params(); @@ -954,6 +1005,16 @@ int main(int argc, char **argv) } srand((unsigned int)time(0)); + #ifdef DAEMON + if (daemonize && daemon(0, 0) < 0) { + clear_params(); + return -1; + } + if (pid_file && init_pid_file(pid_file) < 0) { + clear_params(); + return -1; + } + #endif int status = run((struct sockaddr_ina *)¶ms.laddr); clear_params(); return status; diff --git a/params.h b/params.h index d63ff1a..902b384 100644 --- a/params.h +++ b/params.h @@ -117,7 +117,9 @@ struct params { bool transparent; struct mphdr *mempool; - char *protect_path; + const char *protect_path; + const char *pid_file; + int pid_fd; }; extern struct params params;