You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

util.c 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542
  1. #include <sys/param.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <time.h>
  6. #include <fcntl.h>
  7. #include <netdb.h>
  8. #include <errno.h>
  9. #include <unistd.h>
  10. #ifdef HAVE_LIBUTIL_H
  11. #include <libutil.h>
  12. #endif
  13. #include <stdarg.h>
  14. #include <sys/file.h>
  15. #include "util.h"
  16. #include "cfg_file.h"
  17. int
  18. event_make_socket_nonblocking (int fd)
  19. {
  20. if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1) {
  21. return -1;
  22. }
  23. return 0;
  24. }
  25. static int
  26. make_socket_ai (struct addrinfo *ai)
  27. {
  28. struct linger linger;
  29. int fd, on = 1, r;
  30. int serrno;
  31. /* Create listen socket */
  32. fd = socket(AF_INET, SOCK_STREAM, 0);
  33. if (fd == -1) {
  34. return (-1);
  35. }
  36. if (event_make_socket_nonblocking(fd) < 0)
  37. goto out;
  38. if (fcntl(fd, F_SETFD, 1) == -1) {
  39. goto out;
  40. }
  41. setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, sizeof(on));
  42. setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(on));
  43. linger.l_onoff = 1;
  44. linger.l_linger = 5;
  45. setsockopt(fd, SOL_SOCKET, SO_LINGER, (void *)&linger, sizeof(linger));
  46. r = bind(fd, ai->ai_addr, ai->ai_addrlen);
  47. if (r == -1) {
  48. if (errno != EINPROGRESS) {
  49. goto out;
  50. }
  51. }
  52. return (fd);
  53. out:
  54. serrno = errno;
  55. close(fd);
  56. errno = serrno;
  57. return (-1);
  58. }
  59. int
  60. make_socket (const char *address, u_short port)
  61. {
  62. int fd;
  63. struct addrinfo ai, *aitop = NULL;
  64. char strport[NI_MAXSERV];
  65. int ai_result;
  66. memset(&ai, 0, sizeof (ai));
  67. ai.ai_family = AF_INET;
  68. ai.ai_socktype = SOCK_STREAM;
  69. ai.ai_flags = AI_PASSIVE;
  70. snprintf(strport, sizeof (strport), "%d", port);
  71. if ((ai_result = getaddrinfo(address, strport, &ai, &aitop)) != 0) {
  72. return (-1);
  73. }
  74. fd = make_socket_ai(aitop);
  75. freeaddrinfo(aitop);
  76. return (fd);
  77. }
  78. int
  79. make_unix_socket (const char *path, struct sockaddr_un *addr)
  80. {
  81. size_t len = strlen (path);
  82. int sock;
  83. if (len > sizeof (addr->sun_path) - 1) return -1;
  84. #ifdef FREEBSD
  85. addr->sun_len = sizeof (struct sockaddr_un);
  86. #endif
  87. addr->sun_family = AF_UNIX;
  88. strncpy (addr->sun_path, path, len);
  89. sock = socket (PF_LOCAL, SOCK_STREAM, 0);
  90. if (sock != -1) {
  91. if (bind (sock, (struct sockaddr *) addr, sizeof (struct sockaddr_un)) == -1) return -1;
  92. }
  93. return sock;
  94. }
  95. void
  96. read_cmd_line (int argc, char **argv, struct config_file *cfg)
  97. {
  98. int ch;
  99. while ((ch = getopt(argc, argv, "hfc:")) != -1) {
  100. switch (ch) {
  101. case 'f':
  102. cfg->no_fork = 1;
  103. break;
  104. case 'c':
  105. if (optarg && cfg->cfg_name) {
  106. free (cfg->cfg_name);
  107. cfg->cfg_name = strdup (optarg);
  108. }
  109. break;
  110. case 'h':
  111. case '?':
  112. default:
  113. /* Show help message and exit */
  114. printf ("Rspamd version " RVERSION "\n"
  115. "Usage: rspamd [-h] [-n] [-f] [-c config_file]\n"
  116. "-h: This help message\n"
  117. "-f: Do not daemonize main process\n"
  118. "-c: Specify config file (./rspamd.conf is used by default)\n");
  119. exit (0);
  120. break;
  121. }
  122. }
  123. }
  124. int
  125. write_pid (struct rspamd_main *main)
  126. {
  127. pid_t pid;
  128. main->pfh = pidfile_open (main->cfg->pid_file, 0644, &pid);
  129. if (main->pfh == NULL) {
  130. return -1;
  131. }
  132. pidfile_write (main->pfh);
  133. return 0;
  134. }
  135. void
  136. init_signals (struct sigaction *signals, sig_t sig_handler)
  137. {
  138. /* Setting up signal handlers */
  139. /* SIGUSR1 - reopen config file */
  140. /* SIGUSR2 - worker is ready for accept */
  141. sigemptyset(&signals->sa_mask);
  142. sigaddset(&signals->sa_mask, SIGTERM);
  143. sigaddset(&signals->sa_mask, SIGINT);
  144. sigaddset(&signals->sa_mask, SIGHUP);
  145. sigaddset(&signals->sa_mask, SIGCHLD);
  146. sigaddset(&signals->sa_mask, SIGUSR1);
  147. sigaddset(&signals->sa_mask, SIGUSR2);
  148. signals->sa_handler = sig_handler;
  149. sigaction (SIGTERM, signals, NULL);
  150. sigaction (SIGINT, signals, NULL);
  151. sigaction (SIGHUP, signals, NULL);
  152. sigaction (SIGCHLD, signals, NULL);
  153. sigaction (SIGUSR1, signals, NULL);
  154. sigaction (SIGUSR2, signals, NULL);
  155. }
  156. void
  157. pass_signal_worker (struct workq *workers, int signo)
  158. {
  159. struct rspamd_worker *cur;
  160. TAILQ_FOREACH (cur, workers, next) {
  161. kill (cur->pid, signo);
  162. }
  163. }
  164. void convert_to_lowercase (char *str, unsigned int size)
  165. {
  166. while (size--) {
  167. *str = tolower (*str);
  168. str ++;
  169. }
  170. }
  171. #ifndef HAVE_SETPROCTITLE
  172. static char *title_buffer = 0;
  173. static size_t title_buffer_size = 0;
  174. static char *title_progname, *title_progname_full;
  175. int
  176. setproctitle(const char *fmt, ...)
  177. {
  178. if (!title_buffer || !title_buffer_size) {
  179. errno = ENOMEM;
  180. return -1;
  181. }
  182. memset (title_buffer, '\0', title_buffer_size);
  183. ssize_t written;
  184. if (fmt) {
  185. ssize_t written2;
  186. va_list ap;
  187. written = snprintf (title_buffer, title_buffer_size, "%s: ", title_progname);
  188. if (written < 0 || (size_t) written >= title_buffer_size)
  189. return -1;
  190. va_start (ap, fmt);
  191. written2 =
  192. vsnprintf (title_buffer + written,
  193. title_buffer_size - written, fmt, ap);
  194. va_end (ap);
  195. if (written2 < 0
  196. || (size_t) written2 >= title_buffer_size - written)
  197. return -1;
  198. } else {
  199. written =
  200. snprintf (title_buffer, title_buffer_size, "%s",
  201. title_progname);
  202. if (written < 0 || (size_t) written >= title_buffer_size)
  203. return -1;
  204. }
  205. written = strlen (title_buffer);
  206. memset (title_buffer + written, '\0', title_buffer_size - written);
  207. return 0;
  208. }
  209. /*
  210. It has to be _init function, because __attribute__((constructor))
  211. functions gets called without arguments.
  212. */
  213. int
  214. init_title(int argc, char *argv[], char *envp[])
  215. {
  216. char *begin_of_buffer = 0, *end_of_buffer = 0;
  217. int i;
  218. for (i = 0; i < argc; ++i) {
  219. if (!begin_of_buffer)
  220. begin_of_buffer = argv[i];
  221. if (!end_of_buffer || end_of_buffer + 1 == argv[i])
  222. end_of_buffer = argv[i] + strlen (argv[i]);
  223. }
  224. for (i = 0; envp[i]; ++i) {
  225. if (!begin_of_buffer)
  226. begin_of_buffer = envp[i];
  227. if (!end_of_buffer || end_of_buffer + 1 == envp[i])
  228. end_of_buffer = envp[i] + strlen(envp[i]);
  229. }
  230. if (!end_of_buffer)
  231. return 0;
  232. char **new_environ = g_malloc ((i + 1) * sizeof (envp[0]));
  233. if (!new_environ)
  234. return 0;
  235. for (i = 0; envp[i]; ++i) {
  236. if (!(new_environ[i] = strdup (envp[i])))
  237. goto cleanup_enomem;
  238. }
  239. new_environ[i] = 0;
  240. if (program_invocation_name) {
  241. title_progname_full = strdup (program_invocation_name);
  242. if (!title_progname_full)
  243. goto cleanup_enomem;
  244. char *p = strrchr (title_progname_full, '/');
  245. if (p)
  246. title_progname = p + 1;
  247. else
  248. title_progname = title_progname_full;
  249. program_invocation_name = title_progname_full;
  250. program_invocation_short_name = title_progname;
  251. }
  252. environ = new_environ;
  253. title_buffer = begin_of_buffer;
  254. title_buffer_size = end_of_buffer - begin_of_buffer;
  255. return 0;
  256. cleanup_enomem:
  257. for (--i; i >= 0; --i) {
  258. free(new_environ[i]);
  259. }
  260. free(new_environ);
  261. return 0;
  262. }
  263. #endif
  264. #ifndef HAVE_PIDFILE
  265. extern char * __progname;
  266. static int _pidfile_remove(struct pidfh *pfh, int freeit);
  267. static int
  268. pidfile_verify(struct pidfh *pfh)
  269. {
  270. struct stat sb;
  271. if (pfh == NULL || pfh->pf_fd == -1)
  272. return (-1);
  273. /*
  274. * Check remembered descriptor.
  275. */
  276. if (fstat(pfh->pf_fd, &sb) == -1)
  277. return (errno);
  278. if (sb.st_dev != pfh->pf_dev || sb.st_ino != pfh->pf_ino)
  279. return (-1);
  280. return (0);
  281. }
  282. static int
  283. pidfile_read(const char *path, pid_t *pidptr)
  284. {
  285. char buf[16], *endptr;
  286. int error, fd, i;
  287. fd = open(path, O_RDONLY);
  288. if (fd == -1)
  289. return (errno);
  290. i = read(fd, buf, sizeof(buf) - 1);
  291. error = errno; /* Remember errno in case close() wants to change it. */
  292. close(fd);
  293. if (i == -1)
  294. return (error);
  295. else if (i == 0)
  296. return (EAGAIN);
  297. buf[i] = '\0';
  298. *pidptr = strtol(buf, &endptr, 10);
  299. if (endptr != &buf[i])
  300. return (EINVAL);
  301. return (0);
  302. }
  303. struct pidfh *
  304. pidfile_open(const char *path, mode_t mode, pid_t *pidptr)
  305. {
  306. struct pidfh *pfh;
  307. struct stat sb;
  308. int error, fd, len, count;
  309. struct timespec rqtp;
  310. pfh = g_malloc(sizeof(*pfh));
  311. if (pfh == NULL)
  312. return (NULL);
  313. if (path == NULL)
  314. len = snprintf(pfh->pf_path, sizeof(pfh->pf_path),
  315. "/var/run/%s.pid", __progname);
  316. else
  317. len = snprintf(pfh->pf_path, sizeof(pfh->pf_path),
  318. "%s", path);
  319. if (len >= (int)sizeof(pfh->pf_path)) {
  320. free(pfh);
  321. errno = ENAMETOOLONG;
  322. return (NULL);
  323. }
  324. /*
  325. * Open the PID file and obtain exclusive lock.
  326. * We truncate PID file here only to remove old PID immediatelly,
  327. * PID file will be truncated again in pidfile_write(), so
  328. * pidfile_write() can be called multiple times.
  329. */
  330. fd = open(pfh->pf_path,
  331. O_WRONLY | O_CREAT | O_TRUNC | O_NONBLOCK, mode);
  332. flock (fd, LOCK_EX | LOCK_NB);
  333. if (fd == -1) {
  334. count = 0;
  335. rqtp.tv_sec = 0;
  336. rqtp.tv_nsec = 5000000;
  337. if (errno == EWOULDBLOCK && pidptr != NULL) {
  338. again:
  339. errno = pidfile_read(pfh->pf_path, pidptr);
  340. if (errno == 0)
  341. errno = EEXIST;
  342. else if (errno == EAGAIN) {
  343. if (++count <= 3) {
  344. nanosleep(&rqtp, 0);
  345. goto again;
  346. }
  347. }
  348. }
  349. free(pfh);
  350. return (NULL);
  351. }
  352. /*
  353. * Remember file information, so in pidfile_write() we are sure we write
  354. * to the proper descriptor.
  355. */
  356. if (fstat(fd, &sb) == -1) {
  357. error = errno;
  358. unlink(pfh->pf_path);
  359. close(fd);
  360. free(pfh);
  361. errno = error;
  362. return (NULL);
  363. }
  364. pfh->pf_fd = fd;
  365. pfh->pf_dev = sb.st_dev;
  366. pfh->pf_ino = sb.st_ino;
  367. return (pfh);
  368. }
  369. int
  370. pidfile_write(struct pidfh *pfh)
  371. {
  372. char pidstr[16];
  373. int error, fd;
  374. /*
  375. * Check remembered descriptor, so we don't overwrite some other
  376. * file if pidfile was closed and descriptor reused.
  377. */
  378. errno = pidfile_verify(pfh);
  379. if (errno != 0) {
  380. /*
  381. * Don't close descriptor, because we are not sure if it's ours.
  382. */
  383. return (-1);
  384. }
  385. fd = pfh->pf_fd;
  386. /*
  387. * Truncate PID file, so multiple calls of pidfile_write() are allowed.
  388. */
  389. if (ftruncate(fd, 0) == -1) {
  390. error = errno;
  391. _pidfile_remove(pfh, 0);
  392. errno = error;
  393. return (-1);
  394. }
  395. snprintf(pidstr, sizeof(pidstr), "%u", getpid());
  396. if (pwrite(fd, pidstr, strlen(pidstr), 0) != (ssize_t)strlen(pidstr)) {
  397. error = errno;
  398. _pidfile_remove(pfh, 0);
  399. errno = error;
  400. return (-1);
  401. }
  402. return (0);
  403. }
  404. int
  405. pidfile_close(struct pidfh *pfh)
  406. {
  407. int error;
  408. error = pidfile_verify(pfh);
  409. if (error != 0) {
  410. errno = error;
  411. return (-1);
  412. }
  413. if (close(pfh->pf_fd) == -1)
  414. error = errno;
  415. free(pfh);
  416. if (error != 0) {
  417. errno = error;
  418. return (-1);
  419. }
  420. return (0);
  421. }
  422. static int
  423. _pidfile_remove(struct pidfh *pfh, int freeit)
  424. {
  425. int error;
  426. error = pidfile_verify(pfh);
  427. if (error != 0) {
  428. errno = error;
  429. return (-1);
  430. }
  431. if (unlink(pfh->pf_path) == -1)
  432. error = errno;
  433. if (flock(pfh->pf_fd, LOCK_UN) == -1) {
  434. if (error == 0)
  435. error = errno;
  436. }
  437. if (close(pfh->pf_fd) == -1) {
  438. if (error == 0)
  439. error = errno;
  440. }
  441. if (freeit)
  442. free(pfh);
  443. else
  444. pfh->pf_fd = -1;
  445. if (error != 0) {
  446. errno = error;
  447. return (-1);
  448. }
  449. return (0);
  450. }
  451. int
  452. pidfile_remove(struct pidfh *pfh)
  453. {
  454. return (_pidfile_remove(pfh, 1));
  455. }
  456. #endif