StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
rtsLogUnix.c
1 #include <stdio.h>
2 #include <netdb.h>
3 #include <sys/socket.h>
4 #include <netinet/in.h>
5 #include <unistd.h>
6 #include <sys/types.h>
7 #include <sys/stat.h>
8 #include <fcntl.h>
9 #include <stdarg.h>
10 #include <arpa/inet.h>
11 #include <string.h>
12 #include <syslog.h>
13 #include <stdlib.h>
14 #include <time.h>
15 
16 #if defined(__linux__) || defined(__APPLE__)
17 #else /* Solaris */
18 #include <procfs.h>
19 #endif
20 
21 
22 #include <rtsLog.h>
23 
24 
25 #ifdef __cplusplus
26 extern "C" {
27 #endif
28 
29 volatile int tonkoLogLevel = 2 ;
30 
31 
32 
33 #ifdef RTS_LOG_DEFAULT_NET
34 static int output_flag = RTS_LOG_NET ;
35 #else
36 static int output_flag = RTS_LOG_STDERR ;
37 #endif
38 
39 static const char *getCmd(void) ;
40 static int odesc = -1 ;
41 static int handchange ;
42 static FILE *fdesc = 0 ;
43 
44 /* defaults */
45 #ifdef RTS_PROJECT_PP
46 static char servER[80] = "130.199.20.88" ;
47 #else
48 static char servER[80] = RTS_LOG_HOST ;
49 #endif
50 
51 static int port = RTS_LOG_PORT ;
52 
53 static char cmd[1024] ;
54 
55 /*
56  Thread issues:
57 
58  The routine itself should be thread safe however no guarantees
59  are made to the operating system calls:
60  sendto
61  sprintf
62  strlen
63  perror
64  The current (2.6) Solaris mentions that they should be.
65 
66  Additionally, the destination node:port as well as the log severity
67  level are COMMON (by design) to all threads.
68 */
69 
70 int rtsLogOutput(int flag)
71 {
72  output_flag = flag ;
73  return flag ;
74 }
75 
76 void rtsLogAddCmd(const char *cmd_in)
77 {
78  strncpy(cmd,cmd_in,sizeof(cmd)-1) ;
79  return ;
80 }
81 
82 int rtsLogAddDest(const char *host, int newport)
83 {
84  /* mark as changed by hand */
85  handchange = 1 ;
86 
87  /* set the statics */
88  strncpy(servER,host,sizeof(servER)-1) ;
89  port = newport ;
90  /* mark as not connected so that next send reconnects
91  with the new values */
92  if(odesc >= 0) close(odesc) ;
93  odesc = -1 ;
94 
95 
96  return 0 ;
97 }
98 
99 int rtsLogAddFile(char *fname)
100 {
101  if(fdesc) fclose(fdesc) ;
102  fdesc = 0 ;
103 
104  if(fname) {
105  fdesc = fopen(fname,"w") ;
106  }
107 
108  if(fdesc) return 0 ;
109 
110  return -1 ;
111 
112 }
113 
114 
115 static char _g_fname[256];
116 static char *jml_fname = NULL;
117 void rtsLogAddJmlFile (char *fname)
118 {
119  strcpy(_g_fname, fname);
120  jml_fname = _g_fname;
121 }
122 
123 int rtsLogUnix_v(const char *str, ...)
124 {
125  /* common to all threads */
126  static int sockAddrSize ;
127  static struct sockaddr_in serverAddr ;
128  static const char *cmd_l ;
129  /* thread dependant */
130  int ret ;
131  char buffer[10240] ;
132  char *string = buffer ;
133  unsigned int *cou = (unsigned int *)buffer ;
134  int len ;
135  int err = 0 ;
136  va_list ap ;
137  int colored ;
138  int to_file = 0 ;
139 
140  retry_connect: ;
141 
142  if((output_flag & RTS_LOG_NET) && (odesc<0)) { /* set the socket up */
143  char *rts_host ;
144  int bufsize ;
145 
146 // if(port==0) port = RTS_LOG_PORT ;
147 
148  if(!handchange && (rts_host=getenv("RTS_LOG_HOST"))) {
149  strncpy(servER,rts_host,sizeof(servER)-1) ;
150  }
151 
152 
153  cmd_l = 0 ;
154 
155  sockAddrSize = sizeof(struct sockaddr_in) ;
156  memset((char *)&serverAddr,0,sockAddrSize) ;
157  serverAddr.sin_family = AF_INET ;
158  serverAddr.sin_port = htons(port) ;
159 
160  /* hostname */
161  if((serverAddr.sin_addr.s_addr = inet_addr(servER)) == (unsigned int)-1) {
162  perror(servER);
163  return -1 ;
164  }
165 
166  odesc = socket(AF_INET, SOCK_DGRAM,0) ;
167  if(odesc < 0) {
168  perror("socket") ;
169  return -1 ;
170  }
171 
172  bufsize = 8*1024*1024 ;
173  for(;;) {
174  ret = setsockopt(odesc,SOL_SOCKET,SO_SNDBUF,(char *)&bufsize,sizeof(bufsize)) ;
175  if(ret == 0) break ;
176  bufsize /= 2 ;
177  }
178  //printf("2: set sockbuff to %d bytes\n",bufsize) ;
179 
180  cmd_l = getCmd() ; // get the name of the running executable
181  }
182 
183  len = 4 ; /* to account for the counter */
184 
185  colored = 0 ;
186  if(strncmp(str,"COLOR",5)==0) { // COLORED output!
187 
188  str += 5 ;
189 
190  if(strncmp(str,DBG,strlen(DBG))==0) {
191  ; // don't color
192  }
193  else if(strncmp(str,NOTE,strlen(NOTE))==0) {
194  ; // don't color
195  }
196  else if(strncmp(str,WARN,strlen(WARN))==0) {
197  colored = 1 ;
198  sprintf(string+len,"%s",ANSI_CYAN) ;
199  len += strlen(string+len) ;
200  }
201  else if(strncmp(str,CRIT,strlen(CRIT))==0) {
202  colored = 1 ;
203  to_file = 1 ;
204  sprintf(string+len,"%s%s%s",ANSI_RED,ANSI_BOLD,ANSI_REVERSE) ;
205  len += strlen(string+len) ;
206  }
207  else if(strncmp(str,ERR,strlen(ERR))==0) {
208  colored = 1 ;
209  to_file = 1 ;
210  sprintf(string+len,"%s",ANSI_RED) ;
211  len += strlen(string+len) ;
212  }
213  else if(strncmp(str,CAUTION,strlen(CAUTION))==0) {
214  colored = 1 ;
215  to_file = 1 ;
216  sprintf(string+len,"%s%s",ANSI_MAGENTA,ANSI_REVERSE) ;
217  len += strlen(string+len) ;
218  }
219  else if(strncmp(str,TERR,strlen(TERR))==0) {
220  colored = 1 ;
221  to_file = 1 ;
222  sprintf(string+len,"%s",ANSI_GREEN) ;
223  len += strlen(string+len) ;
224  }
225  else if(strncmp(str,OPER,strlen(OPER))==0) {
226  colored = 1 ;
227  to_file = 1 ;
228  sprintf(string+len,"%s%s",ANSI_BLUE,ANSI_REVERSE) ;
229  len += strlen(string+len) ;
230  }
231  else if(strncmp(str,"U_",2)==0) {
232  colored = 1 ;
233  to_file = 1 ;
234  sprintf(string+len,"%s",ANSI_REVERSE) ;
235  len += strlen(string+len) ;
236  }
237  else if(strncmp(str,INFO,strlen(INFO))==0) {
238  colored = 1 ;
239  to_file = 1 ;
240  sprintf(string+len,"%s",ANSI_BLUE) ;
241  len += strlen(string+len) ;
242  }
243  else {
244  //colored = 1 ;
245  //sprintf(string+len,"%s",ANSI_BLUE) ;
246  //len += strlen(string+len) ;
247  }
248 
249  }
250 
251  if(cmd[0]) {
252  sprintf(string+len,"(%s): ",cmd) ;
253  len += strlen(string+len) ;
254  }
255  else if(cmd_l) {
256  sprintf(string+len,"(%s): ",cmd_l) ;
257  len += strlen(string+len) ;
258  }
259 
260 
261 
262 
263  va_start(ap, str) ;
264  vsprintf(string+len,str,ap) ;
265  len += strlen(string+len) ;
266 
267  if(colored) {
268  char *end ;
269  int nl_cou = 0 ;
270 
271  end = string + len ; // points at 0 now...
272  while(*(end-1) == '\n') {
273  nl_cou++ ;
274  len-- ;
275  *(end-1) = 0 ;
276  end-- ;
277  }
278  sprintf(end,"%s",ANSI_RESET) ;
279  len += strlen(end) ;
280 
281  while(nl_cou) {
282  strcat(string+len,"\n") ;
283  len += strlen(string+len) ;
284  nl_cou-- ;
285  }
286  }
287 
288  //fprintf(stderr,"********** len from calc %d, len now %d\n",len,strlen(buffer+4)+4) ;
289  //len = strlen(buffer+4)+4 ;
290 
291  *cou = 0xFFFFFFFF ; /* special handling by server! */
292 
293  /* send it to the right place via UDP */
294 
295  if((odesc >= 0) && (output_flag & RTS_LOG_NET)) {
296  ret = sendto(odesc,(char *)buffer,len,0,
297  (struct sockaddr *)&serverAddr,sockAddrSize) ;
298  //fprintf(stderr,"**** sendto returns %d, should %d\n",ret,len) ;
299 
300  if(ret < 0) {
301  syslog(LOG_USER|LOG_ERR,"LOG sendto returned %d [%m]\n",ret) ;
302  close(odesc) ;
303  odesc = -1 ;
304  if(err == 0) { // reconnect only once!
305  err = 1 ;
306  goto retry_connect ;
307  }
308  }
309  }
310 
311  /* and/or to stderr */
312  if(output_flag & RTS_LOG_STDERR) {
313  fprintf(stderr,"%s",(char *)buffer+4) ;
314  }
315 
316 
317  if(fdesc && to_file && (output_flag & RTS_LOG_FILE)) {
318  time_t t = time(0) ;
319  struct tm *tm = localtime(&t) ;
320 
321  if(fdesc) fprintf(fdesc,"%02d:%02d:%02d: %s",tm->tm_hour,tm->tm_min,tm->tm_sec,(char*)buffer+4) ;
322  }
323 
324  if(jml_fname) {
325  time_t t = time(0) ;
326  struct tm *tm = localtime(&t) ;
327 
328  FILE *f = fopen(jml_fname, "a");
329  if(f) fprintf(f,"%02d:%02d:%02d: %s",tm->tm_hour,tm->tm_min,tm->tm_sec,(char*)buffer+4) ;
330  fclose(f);
331 
332  }
333 
334  return 0 ;
335 }
336 
337 static const char *getCmd(void)
338 {
339 
340 
341  static const char *str = "(no-name)" ;
342 #if defined(__linux__) || defined(__APPLE__)
343  FILE *file ;
344  static char name[128] ;
345  char *ptr ;
346 
347  file = fopen("/proc/self/cmdline","r") ;
348  if(file==NULL) return str ;
349 
350  fscanf(file,"%120s",name) ; /* make sure we don't overwrite name */
351  fclose(file) ;
352 
353  if((ptr = strrchr(name,'/'))) {
354  return ptr+1 ;
355  }
356  else {
357  return name ;
358  }
359 #else // solaris
360  int fd, ret ;
361  static struct psinfo ps ;
362 
363  fd = open("/proc/self/psinfo",O_RDONLY,0666) ;
364  if(fd < 0) return str ;
365 
366  ret = read(fd,(char *)&ps,sizeof(ps)) ;
367  close(fd) ;
368 
369  if(ret != sizeof(ps)) {
370  return str ;
371  }
372 
373  return ps.pr_fname ;
374 #endif
375 }
376 
377 #ifdef __cplusplus
378 }
379 #endif
380