CUBRID Engine  latest
util_func.c
Go to the documentation of this file.
1 /*
2  * Copyright 2008 Search Solution Corporation
3  * Copyright 2016 CUBRID Corporation
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 /*
20  * util_func.c : miscellaneous utility functions
21  *
22  */
23 
24 #ident "$Id$"
25 
26 #include "config.h"
27 
28 #include <stdio.h>
29 #include <string.h>
30 #include <signal.h>
31 #include <assert.h>
32 #include <chrono>
33 #include <time.h>
34 #include <stdarg.h>
35 #include <sys/timeb.h>
36 #if !defined (WINDOWS)
37 #include <sys/time.h>
38 #endif /* !WINDOWS */
39 
40 #include "util_func.h"
41 #include "porting.h"
42 #include "error_code.h"
43 #include "utility.h"
44 #include "system_parameter.h"
45 #include "environment_variable.h"
46 
47 #define UTIL_LOG_MAX_HEADER_LEN (40)
48 #define UTIL_LOG_MAX_MSG_SIZE (1024)
49 #define UTIL_LOG_BUFFER_SIZE \
50  (UTIL_LOG_MAX_MSG_SIZE + UTIL_LOG_MAX_HEADER_LEN)
51 
52 #define UTIL_LOG_FILENAME "cubrid_utility.log"
53 
54 static char *util_Log_filename = NULL;
55 static char util_Log_filename_buf[PATH_MAX];
57 
58 static FILE *util_log_file_backup (FILE * fp, const char *path);
59 static FILE *util_log_file_fopen (const char *path);
60 static FILE *fopen_and_lock (const char *path);
61 static int util_log_header (char *buf, size_t buf_len);
62 static int util_log_write_internal (const char *msg, const char *prefix_str);
63 
64 // *INDENT-OFF*
65 template <typename Duration>
66 static void util_get_seconds_and_rest_since_epoch (std::chrono::seconds &secs, Duration &rest);
67 // *INDENT-ON*
68 
69 /*
70  * hashpjw() - returns hash value of given string
71  * return: hash value
72  * s(in)
73  *
74  * Note:
75  * This function is adapted from the hashpjw function in Aho, Sethi, and
76  * Ullman (Red Dragon), p. 436. Unlike that version, this one does not
77  * mod the result; consequently, the result could be any 32-bit value.
78  * The caller should mod the result with a value appropriate for its
79  * environment.
80  *
81  */
82 unsigned int
83 hashpjw (const char *s)
84 {
85  unsigned int h, g;
86 
87  assert (s != NULL);
88 
89  for (h = 0; *s != '\0'; ++s)
90  {
91  h = (h << 4) + (*s);
92 
93  g = (h & 0xf0000000);
94 
95  if (g != 0)
96  {
97  h ^= g >> 24;
98  h ^= g;
99  }
100  }
101  return h;
102 }
103 
104 /*
105  * util_compare_filepath -
106  * return:
107  * file1(in):
108  * file2(in):
109  */
110 int
111 util_compare_filepath (const char *file1, const char *file2)
112 {
113 #if defined (WINDOWS)
114  char path1[PATH_MAX], path2[PATH_MAX];
115  char *p;
116 
117  if (GetLongPathName (file1, path1, sizeof (path1)) == 0 || GetLongPathName (file2, path2, sizeof (path2)) == 0)
118  {
119  return (stricmp (file1, file2));
120  }
121 
122  for (p = path1; *p; p++)
123  if (*p == '/')
124  *p = '\\';
125  for (p = path2; *p; p++)
126  if (*p == '/')
127  *p = '\\';
128 
129  return (stricmp (path1, path2));
130 #else /* WINDOWS */
131  return (strcmp (file1, file2));
132 #endif /* !WINDOWS */
133 }
134 
135 /*
136  * Signal Handling
137  */
138 
139 static void system_interrupt_handler (int sig);
140 static void system_quit_handler (int sig);
141 
142 /*
143  * user_interrupt_handler, user_quit_handler -
144  * These variables contain pointers to the user specified handler
145  * functions for the interrupt and quit signals.
146  * If they are NULL, no handlers have been defined.
147  */
150 
151 /*
152  * system_interrupt_handler - Internal system handler for SIGINT
153  * return: none
154  * sig(in): signal no
155  *
156  * Note: Calls the user interrupt handler after re-arming the signal handler.
157  */
158 static void
160 {
163  {
164  (*user_interrupt_handler) ();
165  }
166 }
167 
168 
169 /*
170  * system_quit_handler - Internal system handler for SIGQUIT
171  * return: none
172  * sig(in): signal no
173  *
174  * Note: Calls the user quit handler after re-arming the signal handler.
175  */
176 static void
178 {
179 #if !defined(WINDOWS)
180  (void) os_set_signal_handler (SIGQUIT, system_quit_handler);
181  if (user_quit_handler != NULL)
182  (*user_quit_handler) ();
183 #endif
184 }
185 
186 /*
187  * util_disarm_signal_handlers - Disarms the user interrpt and quit handlers
188  * if any were specified
189  * return: none
190  */
191 void
193 {
195  {
197  if (os_set_signal_handler (SIGINT, SIG_IGN) != SIG_IGN)
198  {
199  (void) os_set_signal_handler (SIGINT, SIG_DFL);
200  }
201  }
202 #if !defined(WINDOWS)
203  if (user_quit_handler != NULL)
204  {
206  if (os_set_signal_handler (SIGQUIT, SIG_IGN) != SIG_IGN)
207  {
208  (void) os_set_signal_handler (SIGQUIT, SIG_DFL);
209  }
210  }
211 #endif
212 }
213 
214 /*
215  * util_arm_signal_handlers - Install signal handlers for the two most
216  * important signals SIGINT and SIGQUIT
217  * return: none
218  * sigint_handler(in): SIGINT signal handler
219  * sigquit_handler(in): SIGQUIT signal handler
220  */
221 void
222 util_arm_signal_handlers (SIG_HANDLER sigint_handler, SIG_HANDLER sigquit_handler)
223 {
224  /* first disarm any existing handlers */
226 
227  if (sigint_handler != NULL)
228  {
230  user_interrupt_handler = sigint_handler;
231  }
232 #if !defined(WINDOWS)
233  if (sigquit_handler != NULL)
234  {
235  /* Is this kind of test necessary for the quit signal ? */
236  (void) os_set_signal_handler (SIGQUIT, system_quit_handler);
237  user_quit_handler = sigquit_handler;
238  }
239 #endif
240 }
241 
242 /*
243  * The returned char** is null terminated char* array;
244  * ex: "a,b" --> { "a", "b", NULL }
245  */
246 char **
247 util_split_string (const char *str, const char *delim)
248 {
249  char *t, *o;
250  char *save, *v;
251  char **r = NULL;
252  int count = 1;
253 
254  if (str == NULL)
255  {
256  return NULL;
257  }
258 
259  o = strdup (str);
260  if (o == NULL)
261  {
262  return NULL;
263  }
264 
265  for (t = o;; t = NULL)
266  {
267  v = strtok_r (t, delim, &save);
268  if (v == NULL)
269  {
270  break;
271  }
272  char **const realloc_r = (char **) realloc (r, sizeof (char *) * (count + 1));
273  if (realloc_r == NULL)
274  {
275  free (o);
276  return NULL;
277  }
278  else
279  {
280  r = realloc_r;
281  }
282  r[count - 1] = strdup (v);
283  r[count] = NULL;
284  count++;
285  }
286 
287  free (o);
288  return r;
289 }
290 
291 void
293 {
294  int i;
295 
296  for (i = 0; array[i] != NULL; i++)
297  {
298  free (array[i]);
299  }
300  free (array);
301 }
302 
303 /*
304  * util_str_to_time_since_epoch () - convert time string
305  * return: time since epoch or 0 on error
306  *
307  * NOTE: it only accepts YYYY-DD-MM hh:mm:ss format.
308  */
309 time_t
311 {
312  int status = NO_ERROR;
313  int date_index = 0;
314  char *save_ptr, *token, *date_string;
315  const char *delim = "-: ";
316  struct tm time_data, tmp_time_data;
317  time_t result_time;
318 
319  if (str == NULL)
320  {
321  return 0;
322  }
323 
324  date_string = strdup (str);
325  if (date_string == NULL)
326  {
327  return 0;
328  }
329 
330  token = strtok_r (date_string, delim, &save_ptr);
331  while (status == NO_ERROR && token != NULL)
332  {
333  switch (date_index)
334  {
335  case 0: /* year */
336  time_data.tm_year = atoi (token) - 1900;
337  if (time_data.tm_year < 0)
338  {
339  status = ER_GENERIC_ERROR;
340  }
341  break;
342  case 1: /* month */
343  time_data.tm_mon = atoi (token) - 1;
344  if (time_data.tm_mon < 0 || time_data.tm_mon > 11)
345  {
346  status = ER_GENERIC_ERROR;
347  }
348  break;
349  case 2: /* month-day */
350  time_data.tm_mday = atoi (token);
351  if (time_data.tm_mday < 1 || time_data.tm_mday > 31)
352  {
353  status = ER_GENERIC_ERROR;
354  }
355  break;
356  case 3: /* hour */
357  time_data.tm_hour = atoi (token);
358  if (time_data.tm_hour < 0 || time_data.tm_hour > 23)
359  {
360  status = ER_GENERIC_ERROR;
361  }
362  break;
363  case 4: /* minute */
364  time_data.tm_min = atoi (token);
365  if (time_data.tm_min < 0 || time_data.tm_min > 59)
366  {
367  status = ER_GENERIC_ERROR;
368  }
369  break;
370  case 5: /* second */
371  time_data.tm_sec = atoi (token);
372  if (time_data.tm_sec < 0 || time_data.tm_sec > 59)
373  {
374  status = ER_GENERIC_ERROR;
375  }
376  break;
377  default:
378  status = ER_GENERIC_ERROR;
379  break;
380  }
381  date_index++;
382  token = strtok_r (NULL, delim, &save_ptr);
383  }
384  time_data.tm_isdst = -1;
385 
386  free (date_string);
387 
388  if (date_index != 6 || status != NO_ERROR)
389  {
390  return 0;
391  }
392 
393  tmp_time_data = time_data;
394 
395  result_time = mktime (&tmp_time_data);
396  if (result_time < (time_t) 0)
397  {
398  return 0;
399  }
400 
401  time_data.tm_isdst = tmp_time_data.tm_isdst;
402  result_time = mktime (&time_data);
403  if (result_time < (time_t) 0)
404  {
405  return 0;
406  }
407 
408  return result_time;
409 }
410 
411 void
412 util_shuffle_string_array (char **array, int count)
413 {
414  struct timeval t;
415  int i, j;
416  double r;
417  struct drand48_data buf;
418  char *temp;
419 
420  gettimeofday (&t, NULL);
421 
422  /* tv_usec returned by gettimeofday on WINDOWS is millisec * 1000 and seeding it would result in generating an even
423  * random number at first. To avoid such a pattern in generating a random number, tv_usec/1000 is used on WINDOWS. */
424 #if defined (WINDOWS)
425  srand48_r (t.tv_usec / 1000, &buf);
426 #else /* WINDOWS */
427  srand48_r (t.tv_usec, &buf);
428 #endif /* !WINDOWS */
429 
430  /* Fisher-Yates shuffle */
431  for (i = count - 1; i > 0; i--)
432  {
433  drand48_r (&buf, &r);
434  j = (int) ((i + 1) * r);
435 
436  temp = array[j];
437  array[j] = array[i];
438  array[i] = temp;
439  }
440 }
441 
442 /*
443  * util_log_write_result () -
444  *
445  * error (in) :
446  */
447 int
449 {
450  if (error == NO_ERROR)
451  {
452  return util_log_write_internal ("SUCCESS\n", NULL);
453  }
454  else
455  {
456  /* skip failed log */
457  }
458 
459  return 0;
460 }
461 
462 /*
463  * util_log_write_errid () -
464  *
465  * message_id (in) :
466  */
467 int
468 util_log_write_errid (int message_id, ...)
469 {
470  int n;
471  char msg_buf[UTIL_LOG_MAX_MSG_SIZE];
472  const char *format;
473  va_list arg_list;
474 
475  format = utility_get_generic_message (message_id);
476  va_start (arg_list, message_id);
477  n = vsnprintf (msg_buf, UTIL_LOG_MAX_MSG_SIZE, format, arg_list);
478  if (n >= UTIL_LOG_MAX_MSG_SIZE)
479  {
480  msg_buf[UTIL_LOG_MAX_MSG_SIZE - 1] = '\0';
481  }
482  va_end (arg_list);
483 
484  return util_log_write_internal (msg_buf, "FAILURE: ");
485 }
486 
487 /*
488  * util_log_write_errstr () -
489  *
490  * format (in) :
491  */
492 int
493 util_log_write_errstr (const char *format, ...)
494 {
495  int n;
496  char msg_buf[UTIL_LOG_MAX_MSG_SIZE];
497  va_list arg_list;
498 
499  va_start (arg_list, format);
500  n = vsnprintf (msg_buf, UTIL_LOG_MAX_MSG_SIZE, format, arg_list);
501  if (n >= UTIL_LOG_MAX_MSG_SIZE)
502  {
503  msg_buf[UTIL_LOG_MAX_MSG_SIZE - 1] = '\0';
504  }
505  va_end (arg_list);
506 
507  return util_log_write_internal (msg_buf, "FAILURE: ");
508 }
509 
510 /*
511  * util_log_write_warnstr () -
512  *
513  * format (in) :
514  */
515 int
516 util_log_write_warnstr (const char *format, ...)
517 {
518  int n;
519  char msg_buf[UTIL_LOG_MAX_MSG_SIZE];
520  va_list arg_list;
521 
522  va_start (arg_list, format);
523  n = vsnprintf (msg_buf, UTIL_LOG_MAX_MSG_SIZE, format, arg_list);
524  if (n >= UTIL_LOG_MAX_MSG_SIZE)
525  {
526  msg_buf[UTIL_LOG_MAX_MSG_SIZE - 1] = '\0';
527  }
528  va_end (arg_list);
529 
530  return util_log_write_internal (msg_buf, "WARNING: ");
531 }
532 
533 /*
534  * util_log_write_command () -
535  *
536  * argc (in) :
537  * argv (in) :
538  */
539 int
541 {
542  int i;
543  size_t remained_buf_length, str_len;
544  char command_buf[UTIL_LOG_MAX_MSG_SIZE];
545  char *p;
546 
547  memset (command_buf, '\0', UTIL_LOG_MAX_MSG_SIZE);
548  p = command_buf;
549  remained_buf_length = UTIL_LOG_MAX_MSG_SIZE - 1;
550 
551  for (i = 0; i < argc && remained_buf_length > 0; i++)
552  {
553  str_len = strlen (argv[i]);
554  if (str_len > remained_buf_length)
555  {
556  break;
557  }
558  strcpy (p, argv[i]);
559  remained_buf_length -= str_len;
560  p += str_len;
561  if (i < argc - 1 && remained_buf_length > 0)
562  {
563  /* add white space */
564  *p = ' ';
565  p++;
566  remained_buf_length--;
567  }
568  else if (i == argc - 1 && remained_buf_length > 0)
569  {
570  *p = '\n';
571  p++;
572  remained_buf_length--;
573  }
574  }
575 
576  return util_log_write_internal (command_buf, NULL);
577 }
578 
579 /*
580  * util_log_write_internal () -
581  *
582  * msg (in) :
583  * prefix_str(in) :
584  *
585  */
586 static int
587 util_log_write_internal (const char *msg, const char *prefix_str)
588 {
589  char *p;
590  int ret = -1;
591  int len, n;
592  FILE *fp;
593 
594  if (util_Log_filename == NULL)
595  {
598  }
599 
600  p = util_Log_buffer;
601  len = UTIL_LOG_BUFFER_SIZE;
602  n = util_log_header (p, len);
603  len -= n;
604  p += n;
605 
606  if (len > 0)
607  {
608  n = snprintf (p, len, "%s%s", (prefix_str ? prefix_str : ""), msg);
609  if (n >= len)
610  {
611  p[len - 1] = '\0';
612  }
613  }
614 
616  if (fp == NULL)
617  {
618  return -1;
619  }
620 
621  ret = fprintf (fp, "%s", util_Log_buffer);
622  fclose (fp);
623 
624  return ret;
625 }
626 
627 /*
628  * util_log_header () -
629  *
630  * buf (out) :
631  *
632  */
633 static int
634 util_log_header (char *buf, size_t buf_len)
635 {
636  struct tm tm, *tm_p;
637  time_t sec;
638  int len;
639  char *p;
640  const char *pid;
641  int millisec;
642 
643  if (buf == NULL)
644  {
645  return 0;
646  }
647 
648  /* current time */
649  util_get_second_and_ms_since_epoch (&sec, &millisec);
650 
651  tm_p = localtime_r (&sec, &tm);
652 
653  len = (int) strftime (buf, buf_len, "%y-%m-%d %H:%M:%S", tm_p);
654  p = buf + len;
655  buf_len -= len;
656 
658  len += snprintf (p, buf_len, ".%03d (%s) ", millisec, ((pid == NULL) ? " " : pid));
659 
661 
662  return len;
663 }
664 
665 /*
666  * util_log_file_fopen () -
667  *
668  * path (in) :
669  *
670  */
671 static FILE *
672 util_log_file_fopen (const char *path)
673 {
674  FILE *fp;
675 
676  assert (path != NULL);
677 
678  fp = fopen_and_lock (path);
679  if (fp != NULL)
680  {
681  fseek (fp, 0, SEEK_END);
682  if (ftell (fp) > prm_get_integer_value (PRM_ID_ER_LOG_SIZE))
683  {
684  fp = util_log_file_backup (fp, path);
685  }
686  }
687 
688  return fp;
689 }
690 
691 /*
692  * util_log_file_backup ()
693  * fp (in) :
694  * path (in) :
695  *
696  */
697 static FILE *
698 util_log_file_backup (FILE * fp, const char *path)
699 {
700  char backup_file[PATH_MAX];
701 
702  assert (fp != NULL);
703  assert (path != NULL);
704 
705  fclose (fp);
706  sprintf (backup_file, "%s.bak", path);
707  (void) unlink (backup_file);
708  (void) rename (path, backup_file);
709 
710  return fopen_and_lock (path);
711 }
712 
713 /*
714  * fopen_and_lock ()
715  * path (in) :
716  *
717  */
718 static FILE *
719 fopen_and_lock (const char *path)
720 {
721 #define MAX_RETRY_COUNT 10
722 
723  int retry_count = 0;
724  FILE *fp;
725 
726 retry:
727  fp = fopen (path, "a+");
728  if (fp != NULL)
729  {
730  if (lockf (fileno (fp), F_TLOCK, 0) < 0)
731  {
732  fclose (fp);
733 
734  if (retry_count < MAX_RETRY_COUNT)
735  {
736  SLEEP_MILISEC (0, 100);
737  retry_count++;
738  goto retry;
739  }
740 
741  return NULL;
742  }
743  }
744 
745  return fp;
746 }
747 
748 /*
749  * util_bsearch () - generic binary search function. besides searching for key, it also returns the right key position
750  * even when it is not found. the caller may then decide to insert the key.
751  * if you only want to find key if it exists, it's better to use bsearch.
752  *
753  * return : position of found key or the right position if key would be inserted.
754  * key (in) : point to key value
755  * base (in) : pointer to base array
756  * n_elems (in) : number of elements in array
757  * size_elem (in) : memory size of one element
758  * func_compare (in) : compare function
759  * out_found (out) : output true if key was found, false otherwise
760  *
761  * note: the array of elements should be ordered by func_compare. duplicate keys are not allowed.
762  */
763 int
764 util_bsearch (const void *key, const void *base, int n_elems, unsigned int sizeof_elem,
765  int (*func_compare) (const void *, const void *), bool * out_found)
766 {
767  int min = 0;
768  int max = n_elems - 1;
769  int mid = 0;
770  int compare = 0;
771 
772  const void *elem;
773 
774  *out_found = false;
775 
776  /* binary search */
777  /* keep searching and reducing the range until key is found, or until the range is reduced to 0 */
778  while (min <= max)
779  {
780  /* get range midpoint */
781  mid = (min + max) >> 1;
782 
783  /* get mid element */
784  elem = (char *) base + (mid * sizeof_elem);
785 
786  /* compare with key */
787  compare = func_compare (elem, key);
788 
789  /* did we find key? */
790  if (compare == 0)
791  {
792  *out_found = true;
793  return mid;
794  }
795  /* not found */
796  /* reduce the search range */
797  if (compare > 0)
798  {
799  /* search in lower range */
800  max = mid - 1;
801  }
802  else
803  {
804  /* search in upper range */
805  /* we also have to increment mid. if range is reduced to 0, the right position for key is next. */
806  min = ++mid;
807  }
808  }
809 
810  /* not found */
811  /* mid is the right position for key */
812  return mid;
813 }
814 
815 // *INDENT-OFF*
816 template <typename Duration>
817 void
818 util_get_seconds_and_rest_since_epoch (std::chrono::seconds &secs, Duration &rest)
819 {
820  using clock_t = std::chrono::system_clock;
821  using timept_secs = std::chrono::time_point<clock_t, std::chrono::seconds>;
822  auto now_timepoint = clock_t::now ();
823  timept_secs now_in_secs = std::chrono::time_point_cast<std::chrono::seconds> (now_timepoint);
824  secs = now_in_secs.time_since_epoch ();
825  rest = std::chrono::duration_cast<Duration> (now_timepoint - now_in_secs);
826 }
827 
828 void
829 util_get_second_and_ms_since_epoch (time_t * secs, int *msec)
830 {
831  assert (secs != NULL && msec != NULL);
832  std::chrono::seconds secs_since_epoch;
833  std::chrono::milliseconds rest_in_msec;
834  util_get_seconds_and_rest_since_epoch<std::chrono::milliseconds> (secs_since_epoch, rest_in_msec);
835  *secs = static_cast<time_t> (secs_since_epoch.count ());
836  *msec = static_cast<int> (rest_in_msec.count ());
837  assert (*msec < 1000);
838 }
839 // *INDENT-ON*
char * envvar_logdir_file(char *path, size_t size, const char *filename)
#define SLEEP_MILISEC(sec, msec)
Definition: util_func.h:40
#define NO_ERROR
Definition: error_code.h:46
static FILE * fopen_and_lock(const char *path)
Definition: util_func.c:719
static FILE * util_log_file_backup(FILE *fp, const char *path)
Definition: util_func.c:698
static SIG_HANDLER user_interrupt_handler
Definition: util_func.c:148
int argc
Definition: dynamic_load.c:951
void util_disarm_signal_handlers(void)
Definition: util_func.c:192
static void system_quit_handler(int sig)
Definition: util_func.c:177
int util_log_write_command(int argc, char *argv[])
Definition: util_func.c:540
void util_arm_signal_handlers(SIG_HANDLER sigint_handler, SIG_HANDLER sigquit_handler)
Definition: util_func.c:222
static void system_interrupt_handler(int sig)
Definition: util_func.c:159
#define UTIL_PID_ENVVAR_NAME
Definition: util_func.h:34
int util_log_write_errid(int message_id,...)
Definition: util_func.c:468
unsigned int hashpjw(const char *s)
Definition: util_func.c:83
int util_log_write_result(int error)
Definition: util_func.c:448
static int util_log_write_internal(const char *msg, const char *prefix_str)
Definition: util_func.c:587
#define UTIL_LOG_MAX_MSG_SIZE
Definition: util_func.c:48
#define assert(x)
int prm_get_integer_value(PARAM_ID prm_id)
#define ER_GENERIC_ERROR
Definition: error_code.h:49
void util_shuffle_string_array(char **array, int count)
Definition: util_func.c:412
#define min(a, b)
static void util_get_seconds_and_rest_since_epoch(std::chrono::seconds &secs, Duration &rest)
Definition: util_func.c:818
#define NULL
Definition: freelistheap.h:34
pid_t pid
Definition: dynamic_load.c:955
void util_free_string_array(char **array)
Definition: util_func.c:292
int util_compare_filepath(const char *file1, const char *file2)
Definition: util_func.c:111
int count(int &result, const cub_regex_object &reg, const std::string &src, const int position, const INTL_CODESET codeset)
#define UTIL_LOG_MAX_HEADER_LEN
Definition: util_func.c:47
int util_log_write_warnstr(const char *format,...)
Definition: util_func.c:516
char ** util_split_string(const char *str, const char *delim)
Definition: util_func.c:247
const char * utility_get_generic_message(int message_index)
Definition: util_common.c:88
#define max(a, b)
void(* SIG_HANDLER)(void)
Definition: util_func.h:60
void util_get_second_and_ms_since_epoch(time_t *secs, int *msec)
Definition: util_func.c:829
const char * envvar_get(const char *name)
static void error(const char *msg)
Definition: gencat.c:331
#define MAX_RETRY_COUNT
static int util_log_header(char *buf, size_t buf_len)
Definition: util_func.c:634
const char ** argv
Definition: dynamic_load.c:952
#define strlen(s1)
Definition: intl_support.c:43
static FILE * util_log_file_fopen(const char *path)
Definition: util_func.c:672
static char * util_Log_filename
Definition: util_func.c:54
int util_log_write_errstr(const char *format,...)
Definition: util_func.c:493
int i
Definition: dynamic_load.c:954
char * strdup(const char *str)
Definition: porting.c:901
static SIG_HANDLER user_quit_handler
Definition: util_func.c:149
static char util_Log_filename_buf[PATH_MAX]
Definition: util_func.c:55
#define UTIL_LOG_FILENAME
Definition: util_func.c:52
time_t util_str_to_time_since_epoch(char *str)
Definition: util_func.c:310
#define UTIL_LOG_BUFFER_SIZE
Definition: util_func.c:49
SIGNAL_HANDLER_FUNCTION os_set_signal_handler(const int sig_no, SIGNAL_HANDLER_FUNCTION sig_handler)
Definition: porting.c:1333
const char ** p
Definition: dynamic_load.c:945
int util_bsearch(const void *key, const void *base, int n_elems, unsigned int sizeof_elem, int(*func_compare)(const void *, const void *), bool *out_found)
Definition: util_func.c:764
static char util_Log_buffer[UTIL_LOG_BUFFER_SIZE]
Definition: util_func.c:56