FOSSology  4.4.0
Open Source License Compliance by Open Source Software
logging.c
Go to the documentation of this file.
1 /*
2  SPDX-FileCopyrightText: © 2010, 2011, 2012 Hewlett-Packard Development Company, L.P.
3 
4  SPDX-License-Identifier: GPL-2.0-only
5 */
11 /* local includes */
12 #include <event.h>
13 #include <logging.h>
14 #include <scheduler.h>
15 
16 /* std library includes */
17 #define _GNU_SOURCE
18 #include <stdio.h>
19 #include <time.h>
20 
21 /* unix includes */
22 #include <sys/stat.h>
23 #include <sys/types.h>
24 #include <unistd.h>
25 
26 /* glib includes */
27 #include <glib.h>
28 
33 log_t* main_log = NULL;
34 
35 /* ************************************************************************** */
36 /* **** local functions ***************************************************** */
37 /* ************************************************************************** */
38 
43 typedef struct
44 {
46  gchar* msg;
48 
57 static void log_event(scheduler_t* scheduler, log_event_args* pass)
58 {
59  lprintf(pass->log, "%s", pass->msg);
60  g_free(pass->msg);
61  g_free(pass);
62 }
63 
64 /* ************************************************************************** */
65 /* **** logging functions *************************************************** */
66 /* ************************************************************************** */
67 
81 log_t* log_new(gchar* log_name, gchar* pro_name, pid_t pro_pid)
82 {
83  struct stat stats;
84  log_t* ret = g_new0(log_t, 1);
85 
86  /* set the process name */
87  if(pro_name == NULL)
88  ret->pro_name = g_strdup(SCHE_PRONAME);
89  else
90  ret->pro_name = g_strdup(pro_name);
91  ret->pro_pid = pro_pid;
92 
93  /* set the logs name */
94  if(strcmp(log_name, "stderr") != 0 && strcmp(log_name, "stdout") != 0 &&
95  (stat(log_name, &stats) == 0) && S_ISDIR(stats.st_mode))
96  ret->log_name = g_strdup_printf("%s/fossology.log", log_name);
97  else
98  ret->log_name = g_strdup(log_name);
99 
100  /* open the log file */
101  if (strcmp(ret->log_name, "stderr") == 0) { ret->log_file = stderr; }
102  else if(strcmp(ret->log_name, "stdout") == 0) { ret->log_file = stdout; }
103  else { ret->log_file = fopen(ret->log_name, "a"); }
104 
105  /* make sure that everything is valid */
106  if(ret->log_file == NULL)
107  {
108  ERROR("could not open log file \"%s\"", ret->log_name);
109  g_free(ret->pro_name);
110  g_free(ret->log_name);
111  return NULL;
112  }
113 
114  return ret;
115 }
116 
126 log_t* log_new_FILE(FILE* log_file, gchar* log_name, gchar* pro_name, pid_t pro_pid)
127 {
128  log_t* ret = g_new0(log_t, 1);
129 
130  if(pro_name == NULL)
131  ret->pro_name = g_strdup(SCHE_PRONAME);
132  else
133  ret->pro_name = g_strdup(pro_name);
134  ret->pro_pid = pro_pid;
135 
136  ret->log_name = g_strdup(log_name);
137  ret->log_file = log_file;
138 
139  V_JOB("NEW_LOG: log_name: \"%s\", pro_name: \"%s\", pro_pid: %d, log_file: %p\n",
140  ret->log_name, ret->pro_name, ret->pro_pid, ret->log_file);
141 
142  return ret;
143 }
144 
150 void log_destroy(log_t* log)
151 {
152  if(log->pro_name) g_free(log->pro_name);
153  if(log->log_name) g_free(log->log_name);
154 
155  if(log->log_file && log->log_file != stdout && log->log_file != stderr)
156  fclose(log->log_file);
157 
158  log->pro_name = NULL;
159  log->log_name = NULL;
160 
161  if(log->log_file != stdout && log->log_file != stderr)
162  log->log_file = NULL;
163 
164  g_free(log);
165 }
166 
180 int lprintf(log_t* log, const char* fmt, ...)
181 {
182  va_list args;
183  int rc;
184 
185  if(!fmt) return 0;
186 
187  va_start(args, fmt);
188  if(log == NULL || log->log_file == NULL)
189  {
190  rc = vlprintf(main_log, fmt, args);
191  }
192  else
193  {
194  rc = vlprintf(log, fmt, args);
195  }
196  va_end(args);
197 
198  return rc;
199 }
200 
213 int vlprintf(log_t* log, const char* fmt, va_list args)
214 {
215  /* static used to determine if a '\n' needs to be printed */
216  static int n_line = 1;
217 
218  /* locals */
219  time_t t = time(NULL);
220  char* tmp, * curr;
221  char time_buf[64];
222  int e_line;
223 
224  if(!fmt) return 0;
225  if(!log) return 0;
226 
227  strftime(time_buf, sizeof(time_buf),"%F %T",localtime(&t));
228 
229  tmp = g_strdup_vprintf(fmt, args);
230  e_line = tmp[strlen(tmp) - 1] == '\n';
231  curr = strtok(tmp, "\n");
232  while(curr != NULL)
233  {
234  if(n_line && fprintf(log->log_file, "%s %s [%d] :: ", time_buf,
235  log->pro_name, log->pro_pid) == 0)
236  return 0;
237 
238  if(fprintf(log->log_file, "%s", curr) == 0)
239  return 0;
240 
241  n_line = ((curr = strtok(NULL, "\n")) != NULL);
242  if(n_line && fprintf(log->log_file, "\n") == 0)
243  return 0;
244  }
245 
246  if(e_line)
247  {
248  n_line = 1;
249  if(fprintf(log->log_file, "\n") == 0)
250  return 0;
251  }
252 
253  fflush(log->log_file);
254  g_free(tmp);
255  return 1;
256 }
257 
270 int clprintf(log_t* log, char* s_name, uint16_t s_line, const char* fmt, ...)
271 {
272  va_list args;
273  int ret = 1;
274  log_event_args* pass;
275 
276  if(!fmt) return 0;
277  if(!log) return 0;
278 
279  va_start(args, fmt);
280  if(g_thread_self() != main_thread)
281  {
282  pass = g_new0(log_event_args, 1);
283  pass->log = log;
284  pass->msg = g_strdup_vprintf(fmt, args);
285  event_signal_ext(log_event, pass, "log_event", s_name, s_line);
286  }
287  else
288  {
289  ret = vlprintf(log, fmt, args);
290  }
291  va_end(args);
292 
293  return ret;
294 }
295 
296 
void event_signal_ext(void *func, void *args, char *name, char *s_name, uint16_t s_line)
Definition: event.c:200
Event handling operations.
log_t * main_log
Definition: logging.c:33
int lprintf(log_t *log, const char *fmt,...)
Main logging function.
Definition: logging.c:180
log_t * log_new_FILE(FILE *log_file, gchar *log_name, gchar *pro_name, pid_t pro_pid)
Creates a log file structure based on an already created FILE*.
Definition: logging.c:126
int vlprintf(log_t *log, const char *fmt, va_list args)
The provides the same functionality for lprintf as vprintf does for printf.
Definition: logging.c:213
int clprintf(log_t *log, char *s_name, uint16_t s_line, const char *fmt,...)
Definition: logging.c:270
static void log_event(scheduler_t *scheduler, log_event_args *pass)
Definition: logging.c:57
log_t * log_new(gchar *log_name, gchar *pro_name, pid_t pro_pid)
Creates a new log.
Definition: logging.c:81
void log_destroy(log_t *log)
Free memory associated with the log file.
Definition: logging.c:150
Log related operations.
#define ERROR(...)
Definition: logging.h:79
GThread * main_thread
Pointer to the main thread.
Definition: scheduler.c:60
Header file for the scheduler.
log_t * log
Log to use.
Definition: logging.c:45
gchar * msg
Message to log.
Definition: logging.c:46
Definition: logging.h:35
gchar * log_name
The name of the log file that will be printed to.
Definition: logging.h:36
gchar * pro_name
What should be printed as the process name.
Definition: logging.h:37
FILE * log_file
The log file itself.
Definition: logging.h:39
pid_t pro_pid
The pid of the process.
Definition: logging.h:38
char * s_name
Sample source file name.
Definition: testEvent.c:27
uint16_t s_line
Sample source line number.
Definition: testEvent.c:28