Advertisement
Guest User

daemonize of z-connector

a guest
Dec 4th, 2012
100
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Diff 9.25 KB | None | 0 0
  1. # HG changeset patch
  2. # User alexey@ubuntu64.COLLEGE
  3. # Date 1354602095 -25200
  4. # Node ID 5b943f6164c5be8617e28b0b26aaf64de49621fa
  5. # Parent  076d182af50930013519233ea1a8ee067c6538f6
  6. daemonize && syslog
  7.  
  8. diff --git a/Unix/log.c b/Unix/log.c
  9. --- a/Unix/log.c
  10. +++ b/Unix/log.c
  11. @@ -1,38 +1,92 @@
  12.  #include "common.h"
  13. -#include "log.h"
  14. +#include "log.h"
  15. +#ifndef WIN32
  16. +#include <syslog.h>
  17. +#endif
  18.  
  19.  // global logging level
  20.  int LogLevel = 0;
  21.  
  22.  // log file object
  23. -FILE *logFile = NULL;
  24. +FILE *logFile;
  25. +int useSyslog;
  26.  
  27.  void OpenLog(const char *fileName)
  28. -{
  29. -   logFile = (strcmp(fileName, "-") == 0) ? stdout : fopen(fileName, "a");
  30. +{
  31. +    useSyslog = 0;
  32. +    logFile = NULL;
  33. +    if ( strcmp(fileName, "-")==0 )
  34. +    {
  35. +        logFile = stdout;
  36. +    }
  37. +    else if ( strcmp(fileName, "syslog")==0 )
  38. +    {
  39. +        useSyslog = 1;
  40. +#ifndef WIN32
  41. +        openlog ( "z-agent", LOG_PID, LOG_DAEMON );
  42. +#endif
  43. +    }
  44. +    else
  45. +    {
  46. +        logFile = fopen(fileName, "a");
  47. +    }
  48.  
  49. -   if (logFile == NULL)
  50. -   {
  51. -       printf("Failed to open log file (%s): %s\n", fileName, strerror(errno));
  52. +   if ( !logFile )
  53. +   {
  54. +        if ( !useSyslog )
  55. +            printf("Failed to open log file (%s): %s\n", fileName, strerror(errno));
  56. +#ifdef WIN32
  57. +        else
  58. +            printf("Logging ty syslog on Windows not supported. Sorry\n");
  59. +#endif
  60.     }
  61.  }
  62.  
  63.  void CloseLog()
  64.  {
  65. -   if (logFile != NULL && logFile != stdout)
  66. -       fclose(logFile);
  67. -   logFile = NULL;
  68. +   if (logFile != NULL && logFile != stdout && !useSyslog )
  69. +   {
  70. +        if (!useSyslog)
  71. +            fclose(logFile);
  72. +   }
  73. +
  74. +   logFile = NULL;
  75. +#ifndef WIN32
  76. +    if ( useSyslog )
  77. +        closelog();
  78. +#endif
  79.  }
  80.  
  81.  void Log(int level, const char *fmt, ...)
  82. -{
  83. +{
  84. +#ifndef WIN32
  85. +    const int levels[] = { LOG_EMERG, LOG_WARNING, LOG_INFO, LOG_DEBUG };
  86. +#endif
  87.     va_list ap;
  88.  
  89.     if (level > LogLevel) return;
  90. +
  91. +#ifndef WIN32
  92. +    if ( useSyslog )
  93. +    {
  94. +        vsyslog ( levels[level], fmt, ap );
  95. +        return;
  96. +    }
  97. +#endif
  98.  
  99.      va_start(ap, fmt);
  100. -   vfprintf((logFile != NULL) ? logFile : stdout, fmt, ap);
  101. -   va_end(ap);
  102. +    vfprintf((logFile != NULL) ? logFile : stdout, fmt, ap);
  103. +    va_end(ap);
  104.  
  105. -   fflush((logFile != NULL) ? logFile : stdout);
  106. +    fflush((logFile != NULL) ? logFile : stdout);
  107. +}
  108. +
  109. +void Error(const char *fmt, ...)
  110. +{
  111. +    va_list ap;
  112. +    va_start(ap, fmt);
  113. +    vfprintf( stderr, fmt, ap);
  114. +    va_end(ap);
  115. +    fflush(stderr);
  116. +    exit (1);
  117.  }
  118. diff --git a/Unix/log.h b/Unix/log.h
  119. --- a/Unix/log.h
  120. +++ b/Unix/log.h
  121. @@ -6,11 +6,13 @@
  122.  void OpenLog(const char *fileName);
  123.  void CloseLog();
  124.  
  125. -void Log(int level, const char *fmt, ...);
  126. +void Log(int level, const char *fmt, ...);
  127. +void Error(const char *fmt, ...);
  128.  
  129.  #define ERR(s, ...) Log(0, "[E] " s, ##__VA_ARGS__)
  130.  #define WARN(s, ...) Log(1, "[W] " s, ##__VA_ARGS__)
  131.  #define INFO(s, ...) Log(2, "[I] " s, ##__VA_ARGS__)
  132. -#define DBG(s, ...) Log(3, "[D] " s, ##__VA_ARGS__)
  133. +#define DBG(s, ...) Log(3, "[D] " s, ##__VA_ARGS__)
  134. +#define FATAL(s, ...) Error( "[FATAL] " s, ##__VA_ARGS__)
  135.  
  136.  #endif
  137. \ No newline at end of file
  138. diff --git a/Unix/main.c b/Unix/main.c
  139. --- a/Unix/main.c
  140. +++ b/Unix/main.c
  141. @@ -24,7 +24,7 @@
  142.  void DumpBuffer(const char *data, int length)
  143.  {
  144.     char line[49];
  145. -   int i, j;
  146. +   int i;
  147.  
  148.     line[48] = '\0';
  149.  
  150. @@ -119,7 +119,6 @@
  151.  {
  152.     struct hostent *srv;
  153.     int dev = -1;
  154. -   FILE* log = NULL;
  155.     SOCKET sock = SOCKET_ERROR;
  156.     struct sockaddr_in srvaddr;
  157.     int keepalive = 1, hasCert, retCode;
  158. @@ -186,11 +185,11 @@
  159.     {
  160.         WARN("Failed to enable keep-alives\n");
  161.     }
  162. -  
  163. +
  164.     srvaddr.sin_family = AF_INET;
  165.     srvaddr.sin_port = htons((u_short) port);
  166.     memcpy(&srvaddr.sin_addr, srv->h_addr_list[0], 4);
  167. -  
  168. +
  169.     INFO("Connecting to server...\n");
  170.  
  171.     if (0 != connect(sock, (const struct sockaddr *) &srvaddr, sizeof(srvaddr)))
  172. @@ -241,8 +240,8 @@
  173.             RETURN(3);
  174.         }
  175.     }
  176. -  
  177. -  
  178. +
  179. +
  180.     IsTerminating = 0;
  181.  
  182.     signal(SIGTERM, sig_handler);
  183. @@ -280,18 +279,22 @@
  184.     struct arg_file *cert = arg_file0(NULL, "cert", NULL, "personal certificate");
  185.     struct arg_file *key = arg_file0(NULL, "key", NULL, "personal certificate key");
  186.     struct arg_file *cacert = arg_file0(NULL, "cacert", NULL, "CA certificate");
  187. -   struct arg_file *log = arg_file0("lL", "log", NULL, "file to write log to (defaults to stdout)");
  188. +   struct arg_file *log = arg_file0("lL", "log", NULL, "file to write log to (defaults to stdout or syslog)");
  189.     struct arg_lit *debug = arg_lit0(NULL, "debug", "log debugging information");
  190. -    struct arg_lit *help = arg_lit0("h", "help", "print this help and exit");
  191. +#ifndef WIN32
  192. +    struct arg_file *daemon = arg_file0("bB", "pid", NULL, "daemonize and write the pid into given pidfile");
  193. +#endif
  194. +    struct arg_lit *help = arg_lit0("h", "help", "print this help and exit");
  195.      struct arg_end *end = arg_end(20);
  196.  
  197. -   void* argTable[] = {device, server, port, cert, key, cacert, log, debug, help, end};
  198. -
  199. -#ifdef WIN32
  200. +#ifdef WIN32
  201. +    void* argTable[] = {device, server, port, cert, key, cacert, log, debug, help, end};
  202.     WSADATA wsa;
  203.     WORD wsaVersion = MAKEWORD(2, 2);
  204.     int wsaError;
  205. -   DWORD win32err;
  206. +   DWORD win32err;
  207. +#else
  208. +    void* argTable[] = {device, server, port, cert, key, cacert, log, debug, daemon, help, end};
  209.  #endif
  210.  
  211.     int retCode, nErrors;
  212. @@ -316,7 +319,15 @@
  213.          CLEAN_RETURN(0);
  214.      }
  215.  
  216. -   LogLevel = (IS_ARG_SET(debug)) ? 3 : 2;
  217. +   LogLevel = (IS_ARG_SET(debug)) ? 3 : 2;
  218. +
  219. +#ifndef WIN32
  220. +   int IDaemon = 0;
  221. +   int iPid = -1;
  222. +   const char * sPidFN = SAFE_FILE (daemon, "");
  223. +   if ( HAS_STR(sPidFN) )
  224. +        IDaemon = 1;
  225. +#endif
  226.  
  227.      if (nErrors > 0)
  228.     {
  229. @@ -325,7 +336,8 @@
  230.  
  231.          CLEAN_RETURN(2);
  232.      }
  233. -
  234. +
  235. +    const char * defLog = "-";
  236.  #ifdef WIN32
  237.     hStoppingEvent = CreateEvent(NULL, TRUE, FALSE, "Local\\Z-Agent-Stop");
  238.     if (hStoppingEvent == NULL)
  239. @@ -361,17 +373,108 @@
  240.         CloseHandle(hStoppingEvent);
  241.         CLEAN_RETURN(3);
  242.     }
  243. +#else
  244. +    if (IDaemon)
  245. +    {
  246. +        // first, look if we can create and lock the PID
  247. +        iPid = open ( sPidFN, O_CREAT | O_WRONLY, S_IREAD | S_IWRITE );
  248. +        if ( iPid<0 )
  249. +            FATAL ( "failed to create pid file '%s': %s\n", sPidFN, strerror(errno) );
  250. +
  251. +        struct flock tLock;
  252. +        tLock.l_type = F_WRLCK;
  253. +        tLock.l_whence = SEEK_SET;
  254. +        tLock.l_start = 0;
  255. +        tLock.l_len = 0;
  256. +        if ( fcntl ( iPid, F_SETLK, &tLock )==-1 )
  257. +            FATAL ( "failed to lock pid file '%s': %s (daemon already running?)\n", sPidFN, strerror(errno) );
  258. +
  259. +        // prepare to detach
  260. +        int iDevNull = open ( "/dev/null", O_RDWR );
  261. +        close ( STDIN_FILENO );
  262. +       close ( STDOUT_FILENO );
  263. +       dup2 ( iDevNull, STDIN_FILENO );
  264. +       dup2 ( iDevNull, STDOUT_FILENO );
  265. +
  266. +       // unlock the pid (will relock again in child)
  267. +       tLock.l_type = F_UNLCK;
  268. +        fcntl ( iPid, F_SETLK, &tLock );
  269. +
  270. +        // Fork #1 - detach from controlling terminal
  271. +        switch ( fork() )
  272. +        {
  273. +            case -1:
  274. +                // error
  275. +                FATAL ( "fork() failed (reason: %s)\n", strerror ( errno ) );
  276. +            case 0:
  277. +                // daemonized child - or new and free watchdog :)
  278. +                break;
  279. +
  280. +            default:
  281. +               exit ( 0 );
  282. +        }
  283. +
  284. +        // became the session leader
  285. +        if ( setsid()==-1 )
  286. +        {
  287. +            FATAL ( "fork() failed (reason: %s)\n", strerror ( errno ) );
  288. +        }
  289. +
  290. +        // Fork #2 - detach from session leadership (may be not necessary, however)
  291. +        switch ( fork() )
  292. +        {
  293. +            case -1:
  294. +                // error
  295. +                FATAL ( "fork() failed (reason: %s)\n", strerror ( errno ) );
  296. +                exit ( 1 );
  297. +            case 0:
  298. +                // daemonized child - or new and free watchdog :)
  299. +                break;
  300. +
  301. +            default:
  302. +                // the parent
  303. +                exit ( 0 );
  304. +        }
  305. +
  306. +       // relock the pid
  307. +        tLock.l_type = F_WRLCK;
  308. +        if ( fcntl ( iPid, F_SETLK, &tLock )==-1 )
  309. +            FATAL ( "failed to re-lock pid file '%s': %s\n", sPidFN, strerror(errno) );
  310. +
  311. +        // write our pid into pidfile
  312. +       char sPid[16];
  313. +       snprintf ( sPid, sizeof(sPid), "%d\n", (int)getpid() );
  314. +       int iPidLen = strlen(sPid);
  315. +
  316. +       lseek(iPid, 0, SEEK_SET);
  317. +       if ( iPidLen!=write ( iPid, sPid, iPidLen ) )
  318. +            FATAL ( "failed to write to pid file '%s' (errno=%d, msg=%s)\n", sPidFN, errno, strerror(errno) );
  319. +
  320. +       if ( ftruncate ( iPid, iPidLen ) )
  321. +            FATAL ( "failed to truncate pid file '%s' (errno=%d, msg=%s)\n", sPidFN, errno, strerror(errno) );
  322. +
  323. +        close ( STDERR_FILENO );
  324. +       dup2 ( iDevNull, STDERR_FILENO );
  325. +       defLog = "syslog";
  326. +
  327. +    }
  328.  #endif
  329.  
  330. -   retCode = main_impl(device->filename[0],
  331. +   retCode = main_impl(device->filename[0],
  332.                         server->sval[0], SAFE_INT(port, 9087),
  333. -                       SAFE_FILE(cert, ""), SAFE_FILE(key, ""), SAFE_FILE(cacert, ""),
  334. -                       SAFE_FILE(log, "-"));
  335. +                       SAFE_FILE(cert, ""), SAFE_FILE(key, ""), SAFE_FILE(cacert, ""),
  336. +                       SAFE_FILE(log, defLog));
  337.  
  338.  #ifdef WIN32
  339.     WSACleanup();
  340.  
  341.     CloseHandle(hStoppingEvent);
  342. +#else
  343. +    if ( iPid>=0 )
  344. +    {
  345. +       close ( iPid );
  346. +       unlink ( sPidFN );
  347. +    }
  348.  #endif
  349.  
  350.     CLEAN_RETURN(retCode);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement