PageRenderTime 52ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/sutil.c

https://gitlab.com/clearos/compat-suva
C | 637 lines | 485 code | 143 blank | 9 comment | 118 complexity | fb019ba494b90e495be777d0423b292c MD5 | raw file
  1. // Suva utility (general-purpose) support routines
  2. #ifdef HAVE_CONFIG_H
  3. #include "config.h"
  4. #endif
  5. // $Id: sutil.c,v 1.31 2004/03/25 20:43:14 darryl Exp $
  6. #include <unistd.h>
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <stdarg.h>
  10. #include <string.h>
  11. #include <signal.h>
  12. #include <sys/types.h>
  13. #include <sys/stat.h>
  14. #include <sys/socket.h>
  15. #include <sys/ioctl.h>
  16. #include <net/if.h>
  17. #include <netinet/in.h>
  18. #include <ctype.h>
  19. #include <pwd.h>
  20. #include <grp.h>
  21. #include <fcntl.h>
  22. #include <syslog.h>
  23. #include <time.h>
  24. #include <assert.h>
  25. #include <errno.h>
  26. #include "suva_conf.h"
  27. #include "suva.h"
  28. #include "sutil.h"
  29. #include "mem.h"
  30. extern int errno;
  31. //! External SuvaConfig structure
  32. extern struct SuvaConfig_t SuvaConfig;
  33. //! Static output buffer
  34. static char output_buffer[MAX_BUFFER];
  35. int pid_lock(pid_t pid)
  36. {
  37. int fd;
  38. struct flock pidlock;
  39. char pidfile[MAX_PATH];
  40. sprintf(pidfile, "%s%s%d", SD_BASE, SF_PIDLOCK, pid);
  41. if((fd = open(pidfile, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP)) < 0)
  42. {
  43. output(1, "%s: open(%s): %s.", __func__, pidfile, strerror(errno));
  44. return -1;
  45. }
  46. memset(&pidlock, '\0', sizeof(struct flock));
  47. pidlock.l_type = F_WRLCK;
  48. if(fcntl(fd, F_SETLK, &pidlock) < 0)
  49. {
  50. output(1, "%s: fcntl(%s): %s.", __func__, pidfile, strerror(errno));
  51. close(fd);
  52. unlink(pidfile);
  53. return -1;
  54. }
  55. if(write(fd, &pid, sizeof(pid)) != sizeof(pid))
  56. {
  57. output(1, "%s: write(%s, %d): %s.", __func__, pidfile, pid, strerror(errno));
  58. close(fd);
  59. unlink(pidfile);
  60. return -1;
  61. }
  62. output(5, "%s: locked %s.", __func__, pidfile);
  63. return fd;
  64. }
  65. void pid_unlock(pid_t pid)
  66. {
  67. char pidfile[MAX_PATH];
  68. sprintf(pidfile, "%s%s%d", SD_BASE, SF_PIDLOCK, pid);
  69. if(unlink(pidfile) < 0)
  70. output(1, "%s: unlink(%s): %s.", __func__, pidfile, strerror(errno));
  71. else
  72. output(5, "%s: un-locked %s.", __func__, pidfile);
  73. }
  74. int pid_status(pid_t pid)
  75. {
  76. int fd;
  77. struct stat pidstat;
  78. struct flock pidlock;
  79. char pidfile[MAX_PATH];
  80. sprintf(pidfile, "%s%s%d", SD_BASE, SF_PIDLOCK, pid);
  81. if((fd = open(pidfile, O_RDWR)) < 0)
  82. {
  83. if(errno == ENOENT)
  84. return PID_STALE;
  85. output(1, "%s: open(%s): %s.", __func__, pidfile, strerror(errno));
  86. return -1;
  87. }
  88. memset(&pidlock, '\0', sizeof(struct flock));
  89. pidlock.l_type = F_WRLCK;
  90. if(fcntl(fd, F_GETLK, &pidlock) < 0)
  91. {
  92. output(1, "%s: fcntl(%s): %s.", __func__, pidfile, strerror(errno));
  93. memset(&pidlock, '\0', sizeof(struct flock));
  94. }
  95. if(fstat(fd, &pidstat) < 0)
  96. {
  97. output(1, "%s: fstat(%s): %s.\n", __func__, pidfile, strerror(errno));
  98. close(fd);
  99. return -1;
  100. }
  101. close(fd);
  102. if(pidlock.l_pid)
  103. return PID_RUN;
  104. return PID_STALE;
  105. }
  106. //#if defined SCO_PACKET_DUMP || defined SCO_SUVA_DEBUG
  107. void print_hex(char *header, unsigned char *s, int n)
  108. {
  109. int i, j, k, p, o, r = 0, fd;
  110. unsigned long offset = (unsigned long)s;
  111. char line_this[70], line_last[70], buffer[20], s_offset[12], log[MAX_PATH];
  112. #ifdef SCO_EMBED
  113. sprintf(log, "/mnt/tmp/suva-debug.%d", getpid());
  114. #else
  115. sprintf(log, "/tmp/suva-debug.%d", getpid());
  116. #endif
  117. if((fd = open(log, O_CREAT | O_WRONLY | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP)) < 0)
  118. {
  119. output(1, "Couldn't open debug log: %s.", log);
  120. return;
  121. }
  122. if(header)
  123. {
  124. write(fd, header, strlen(header));
  125. write(fd, "\n", 1);
  126. }
  127. memset(line_last, '\0', 70);
  128. for(i = 0; i < n; i += j)
  129. {
  130. k = 0; p = 0; o = 0;
  131. memset(line_this, '\0', 70);
  132. sprintf(s_offset, "%08lX ", offset);
  133. for(j = i; j < (i + 16) && j < n; j++)
  134. {
  135. sprintf(buffer, "%02X ", s[j]);
  136. strcat(line_this, buffer);
  137. if(++k == 4)
  138. {
  139. o = (o) ? 0 : 1;
  140. strcat(line_this, " ");
  141. k = 0;
  142. p++;
  143. }
  144. }
  145. for(o = 16 - (j - i); o > 0; o--)
  146. strcat(line_this, " ");
  147. for(o = 0; o < 4 - p; o++)
  148. strcat(line_this, " ");
  149. for(j = i; j < (i + 16) && j < n; j++)
  150. {
  151. sprintf(buffer, "%c", (isprint(s[j])) ? s[j] : '.');
  152. strcat(line_this, buffer);
  153. }
  154. #ifndef SCO_EMBED
  155. if(strcmp(line_this, line_last) == 0)
  156. r++;
  157. else
  158. {
  159. if(r)
  160. {
  161. output(1, "Last line repeated %d times.");
  162. r = 0;
  163. }
  164. #endif
  165. //output(1, "%s%s", s_offset, line_this);
  166. write(fd, s_offset, strlen(s_offset));
  167. write(fd, line_this, strlen(line_this));
  168. write(fd, "\n", 1);
  169. #ifndef SCO_EMBED
  170. strcpy(line_last, line_this);
  171. }
  172. #endif
  173. j -= i;
  174. offset += 16;
  175. }
  176. write(fd, "\n", 1);
  177. close(fd);
  178. }
  179. //#endif
  180. uid_t get_uid(const char *user_id)
  181. {
  182. #ifndef SCO_EMBED
  183. struct passwd *p_pw = NULL;
  184. if(!user_id)
  185. return -1;
  186. if(isdigit(user_id[0]))
  187. p_pw = getpwuid(atoi(user_id));
  188. if(!p_pw && !(p_pw = getpwnam(user_id)))
  189. return -1;
  190. return p_pw->pw_uid;
  191. #else
  192. return 0;
  193. #endif
  194. }
  195. gid_t get_gid(const char *group_id)
  196. {
  197. #ifndef SCO_EMBED
  198. struct group *p_gr = NULL;
  199. struct passwd *p_pw = NULL;
  200. if(!group_id)
  201. return -1;
  202. if(isdigit(group_id[0]))
  203. p_pw = getpwuid(atoi(group_id));
  204. if(!p_pw && !(p_pw = getpwnam(group_id)))
  205. return -1;
  206. if(isdigit(group_id[0]))
  207. p_gr = getgrgid(atoi(group_id));
  208. if(!p_gr && !(p_gr = getgrnam(group_id)))
  209. return -1;
  210. // Will cause a 'comparison between signed and unsigned' warning:
  211. if(p_pw->pw_gid != p_gr->gr_gid)
  212. return -1;
  213. return p_pw->pw_gid;
  214. #else
  215. return 0;
  216. #endif
  217. }
  218. char **arg_array(char **array, const char *arg)
  219. {
  220. int q = 0;
  221. char *arg_start, *arg_end, *arg_tmp;
  222. arg_start = arg_end = arg_tmp = strdup(arg);
  223. while(arg_start[0])
  224. {
  225. if(arg_start[0] == ' ')
  226. {
  227. arg_end = ++arg_start;
  228. continue;
  229. }
  230. if(arg_start[0] == '"')
  231. {
  232. q = 1;
  233. arg_end = ++arg_start;
  234. continue;
  235. }
  236. if(((arg_end[0] == ' ' || !arg_end[0]) && !q) || (arg_end[0] == '"' && q))
  237. {
  238. if(!arg_end[0])
  239. {
  240. array = array_push(array, arg_start);
  241. break;
  242. }
  243. q = 0;
  244. arg_end[0] = '\0';
  245. array = array_push(array, arg_start);
  246. arg_start = ++arg_end;
  247. continue;
  248. }
  249. arg_end++;
  250. }
  251. free(arg_tmp);
  252. return array;
  253. }
  254. char **dir_array(char **array, const char *dir)
  255. {
  256. char *dir_start, *dir_end, *dir_tmp, buffer[MAX_BUFFER];
  257. buffer[0] = '/';
  258. dir_start = dir_end = dir_tmp = strdup(dir);
  259. while(dir_start[0])
  260. {
  261. if(dir_start[0] == ' ')
  262. {
  263. dir_end = ++dir_start;
  264. continue;
  265. }
  266. if(dir_end[0] == '.' || !dir_end[0])
  267. {
  268. buffer[1] = '\0';
  269. if(!dir_end[0])
  270. {
  271. strncat(buffer, dir_start,
  272. MAX_BUFFER - strlen(dir_start) - 2);
  273. array = array_push(array, buffer);
  274. break;
  275. }
  276. dir_end[0] = '\0';
  277. strncat(buffer, dir_start, MAX_BUFFER - strlen(dir_start) - 2);
  278. array = array_push(array, buffer);
  279. dir_start = ++dir_end;
  280. continue;
  281. }
  282. dir_end++;
  283. }
  284. free(dir_tmp);
  285. return array;
  286. }
  287. char **env_array(char **array, const char *format, ...)
  288. {
  289. va_list ap;
  290. FILE *h_f = NULL;
  291. char line[MAX_BUFFER];
  292. char buffer[MAX_BUFFER];
  293. va_start(ap, format);
  294. vsnprintf(buffer, MAX_BUFFER, format, ap);
  295. va_end(ap);
  296. if(!(h_f = fopen(buffer, "r")))
  297. {
  298. output(1, "Unable to open environment file %s: %s.",
  299. buffer, strerror(errno));
  300. return NULL;
  301. }
  302. while(!feof(h_f))
  303. {
  304. if(!fgets(buffer, MAX_BUFFER, h_f))
  305. break;
  306. memset(line, '\0', sizeof(line));
  307. if(sscanf(buffer, "%1023[A-z0-9/:_=\" -]", line))
  308. array = array_push(array, line);
  309. }
  310. fclose(h_f);
  311. return array;
  312. }
  313. char **array_push(char **array, const char *string)
  314. {
  315. register int i = 0;
  316. while(array && array[i])
  317. i++;
  318. array = (char **)realloc(array, (i + 2) * sizeof(char *));
  319. ASSERT(array);
  320. array[i] = strdup(string);
  321. array[i + 1] = '\0';
  322. return array;
  323. }
  324. char **array_reverse(char **array)
  325. {
  326. int len = 0;
  327. char **new_array = NULL;
  328. while(array && array[len]) len++;
  329. if(!len)
  330. return array;
  331. while(--len >= 0)
  332. new_array = array_push(new_array, array[len]);
  333. array_free(array);
  334. return new_array;
  335. }
  336. void array_free(char **array)
  337. {
  338. register int i;
  339. for(i = 0; array && array[i]; i++)
  340. free(array[i]);
  341. free(array);
  342. }
  343. void output(int level, const char *format, ...)
  344. {
  345. va_list ap;
  346. if(level > SuvaConfig.log_level && level != 100 && level != 1024)
  347. return;
  348. va_start(ap, format);
  349. vsnprintf(output_buffer, MAX_BUFFER, format, ap);
  350. va_end(ap);
  351. if(level < 0 && !(SuvaConfig.flags & SCF_SUVLET))
  352. {
  353. fprintf(stdout, "%s\n", output_buffer);
  354. return;
  355. }
  356. else if(level == 100)
  357. {
  358. int fd;
  359. char log[MAX_PATH];
  360. sprintf(log, "/tmp/suva-debug.%d", getpid());
  361. if((fd = open(log, O_CREAT | O_WRONLY | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP)) < 0)
  362. return;
  363. write(fd, output_buffer, strlen(output_buffer));
  364. write(fd, "\n", 1);
  365. close(fd);
  366. return;
  367. }
  368. else if(level == 1024 && !(SuvaConfig.flags & SCF_SUVLET))
  369. {
  370. if((SuvaConfig.flags & SCF_QUIET))
  371. return;
  372. fprintf(stdout, "%s\n", output_buffer);
  373. return;
  374. }
  375. if((SuvaConfig.flags & SCF_DEBUG))
  376. {
  377. if((SuvaConfig.flags & SCF_SUVAD))
  378. {
  379. fprintf(stderr, "[%d] %s\n", getpid(), output_buffer);
  380. return;
  381. }
  382. fprintf(stderr, "%s\n", output_buffer);
  383. }
  384. else if((SuvaConfig.flags & SCF_SUVLET))
  385. {
  386. int fd;
  387. char log[MAX_PATH];
  388. sprintf(log, "/tmp/suvlet.%d", getpid());
  389. if((fd = open(log, O_CREAT | O_WRONLY | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP)) < 0)
  390. return;
  391. write(fd, output_buffer, strlen(output_buffer));
  392. write(fd, "\n", 1);
  393. close(fd);
  394. // syslog(SuvaConfig.log_facility | LOG_NOTICE, output_buffer);
  395. return;
  396. }
  397. else
  398. syslog(SuvaConfig.log_facility | LOG_NOTICE, output_buffer);
  399. }
  400. char *get_output(void)
  401. {
  402. char *s;
  403. if((s = memchr(output_buffer, '\n', MAX_BUFFER - 1)))
  404. *s = '\0';
  405. return output_buffer;
  406. }
  407. unsigned long get_ifip(char *ifname)
  408. {
  409. int s;
  410. struct ifreq ifr;
  411. struct sockaddr_in addr;
  412. if((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
  413. return 0;
  414. strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name) - 1);
  415. ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0';
  416. if(ioctl(s, SIOCGIFADDR, &ifr) < 0)
  417. {
  418. close(s);
  419. return 0;
  420. }
  421. close(s);
  422. addr = *((struct sockaddr_in *)&ifr.ifr_addr);
  423. return addr.sin_addr.s_addr;
  424. }
  425. #define SWAP(n) ((n << 24) | ((n & 65280) << 8) | ((n & 16711680) >> 8) | (n >> 24))
  426. void swap(void *src, size_t len)
  427. {
  428. register unsigned char *a, *b, tmp;
  429. a = (unsigned char *)src;
  430. b = a + len;
  431. while(a < b)
  432. {
  433. tmp = *a; *a++ = *--b; *b = tmp;
  434. }
  435. }
  436. char *legal_name(char *name, int len)
  437. {
  438. int i, j = 0, c, l = 0;
  439. char *new_name = malloc(len);
  440. if(!new_name)
  441. return NULL;
  442. memset(new_name, '\0', len);
  443. for(i = 0; i < len; i++, c = 0)
  444. {
  445. if(isalnum(name[i]))
  446. c = name[i];
  447. else if(name[i] == '_')
  448. c = name[i];
  449. else if(name[i] == '.' && l != '.')
  450. c = name[i];
  451. else if(!name[i])
  452. break;
  453. if(c)
  454. {
  455. l = c;
  456. new_name[j++] = c;
  457. }
  458. }
  459. memcpy(name, new_name, len);
  460. free(new_name);
  461. return name;
  462. }
  463. char *legal_string(char *name, int len)
  464. {
  465. int i, j = 0, c, l = 0;
  466. char *new_name = malloc(len);
  467. if(!new_name)
  468. return NULL;
  469. memset(new_name, '\0', len);
  470. for(i = 0; i < len; i++, c = 0)
  471. {
  472. if(isalnum(name[i]))
  473. c = name[i];
  474. else if(name[i] == '_')
  475. c = name[i];
  476. else if(name[i] == '-')
  477. c = name[i];
  478. else if(name[i] == '.' && l != '.')
  479. c = name[i];
  480. else if(name[i] == ' ' && l != ' ')
  481. c = name[i];
  482. else if(!name[i])
  483. break;
  484. if(c)
  485. {
  486. l = c;
  487. new_name[j++] = c;
  488. }
  489. }
  490. memcpy(name, new_name, len);
  491. free(new_name);
  492. return name;
  493. }