The Assimilation Project  based on Assimilation version 0.5.1440692045
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
misc.c
Go to the documentation of this file.
1 
26 #define _GNU_SOURCE /* Needed for the F_[SG]ETPIPE_SZ definitions */
27 #include <projectcommon.h>
28 #include <stdlib.h>
29 #ifdef HAVE_UNISTD_H
30 # include <unistd.h>
31 #endif
32 #include <ctype.h>
33 #ifdef HAVE_SYS_UTSNAME_H
34 # include <sys/utsname.h>
35 #endif
36 #include <errno.h>
37 #include <string.h>
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 #ifdef HAVE_FCNTL_H
41 # include <fcntl.h>
42 #endif
43 #ifndef WIN32
44 #include <sys/time.h>
45 #include <sys/resource.h>
46 #endif
47 #include <signal.h>
48 #include <misc.h>
49 
50 void assimilation_logger(const gchar *log_domain, GLogLevelFlags log_level,
51  const gchar *message, gpointer user_data);
52 const char * assim_syslogid = "assim";
53 FSTATIC void catch_pid_signal(int signum);
54 FSTATIC char * _shell_array_value(GSList* arrayvalue);
55 FSTATIC gboolean _assim_proxy_io_watch(GIOChannel*, GIOCondition, gpointer);
56 
58 #ifdef HAVE_UNAME
59 char *
60 proj_get_sysname(void)
61 {
62  struct utsname un; // System name, etc.
63  char * dupname;
64  uname(&un);
65  dupname = g_strdup(un.nodename);
66  if (dupname) {
67  char * dupp;
68  for (dupp = dupname; *dupp; ++dupp) {
69  *dupp = tolower(*dupp);
70  }
71  }
72  return dupname;
73 }
74 #else
75 # ifdef HAVE_GETCOMPUTERNAME
76 char *
77 proj_get_sysname(void)
78 {
79 // BOOL WINAPI GetComputerName(_Out_ LPTSTR lpBuffer, _Inout_ LPDWORD lpnSize);
80 
81  char sn[MAX_COMPUTERNAME_LENGTH + 1];
82  DWORD snsize = sizeof(sn);
83  BOOL ret;
84 
85  ret = GetComputerName((LPSTR) sn, &snsize);
86  if (ret) {
87  char * dupname = g_strdup(sn);
88  char * dupp;
89  for (dupp = dupname; *dupp; ++dupp) {
90  *dupp = tolower(*dupp);
91  }
92  return(dupname);
93  }
94 
95  return g_strdup("GetComputerName failed");
96 }
97 # else
98 # error "Need some function to get our computer name!"
99 # endif
100 #endif
101 
102 #ifndef WIN32
103 void
105 daemonize_me( gboolean stay_in_foreground,
106  const char* dirtorunin,
107  char* pidfile,
108  int minclosefd)
109 {
110  struct rlimit nofile_limits;
111  int nullperms[] = { O_RDONLY, O_WRONLY, O_WRONLY};
112  unsigned j;
113  getrlimit(RLIMIT_NOFILE, &nofile_limits);
114 
115  // g_warning("%s.%d: pid file is %s", __FUNCTION__, __LINE__, pidfile);
116  if (pidfile) {
117  if (are_we_already_running(pidfile, NULL) == PID_RUNNING) {
118  g_message("Already running.");
119  exit(0);
120  }
121  }
122 
123 #ifdef HAS_FORK
124  if (!stay_in_foreground) {
125  int k;
126  int childpid;
127 
128  (void)setsid();
129 
130 
131  for (k=0; k < 2; ++k) {
132  childpid = fork();
133  if (childpid < 0) {
134  g_error("Cannot fork [%s %d]", g_strerror(errno), errno);
135  exit(1);
136  }
137  if (childpid > 0) {
138  exit(0);
139  }
140  // Otherwise, we're the child.
141  // NOTE: probably can't drop a core in '/'
142  }
143  }
144 #endif
145  if (chdir(dirtorunin ? dirtorunin : "/" )) {
146  g_warning("%s.%d: Cannot change directory to [%s]", __FUNCTION__
147  , __LINE__, dirtorunin);
148  }
149  umask(027);
150  // Need to do this after forking and before closing our file descriptors
151  if (pidfile) {
152  if (are_we_already_running(pidfile, NULL) == PID_RUNNING) {
153  g_message("%s.%d: Already running.", __FUNCTION__, __LINE__);
154  exit(0);
155  }
156  // Exit if we can't create the requested pidfile
157  if (!create_pid_file(pidfile)) {
158  exit(1);
159  }
160  }
161  // Now make sure we don't have any funky file descriptors hanging around here...
162  if (!stay_in_foreground) {
163  int nullfd;
164  for (j=0; j < DIMOF(nullperms); ++j) {
165  close(j);
166  nullfd = open("/dev/null", nullperms[j]);
167 
168  if (nullfd < 0) {
169  g_error("%s.%d: Cannot open /dev/null(!)", __FUNCTION__, __LINE__);
170  exit(1);
171  }
172 
173  // Even more paranoia
174  if (nullfd != (int)j) {
175  if (dup2(nullfd, j) != (int)j) {
176  g_error("dup2(%d,%d) failed. World coming to end.", nullfd, j);
177  }
178  (void)close(nullfd);
179  }
180  }
181  }
182  if (minclosefd < (int)DIMOF(nullperms)) {
183  minclosefd = DIMOF(nullperms);
184  }
185  // A bit paranoid - but not so much as you might think...
186  for (j=minclosefd; j < nofile_limits.rlim_cur; ++j) {
187  close(j);
188  }
189 }
190 #else
191 void
192 daemonize_me( gboolean stay_in_foreground,
193  const char* dirtorunin,
194  const char* pidfile)
195 {
196  if (pidfile) {
197  if (are_we_already_running(pidfile, NULL) == PID_RUNNING) {
198  g_message("Already running.");
199  exit(0);
200  }
201  }
202  // Exit if we can't create the requested pidfile
203  if (!create_pid_file(pidfile)) {
204  exit(1);
205  }
206 }
207 #endif
208 
209 static gboolean syslog_opened = FALSE;
210 void
211 assimilation_openlog(const char* logname)
212 {
213 #ifndef WIN32
214  const int syslog_options = LOG_PID|LOG_NDELAY;
215  const int syslog_facility = LOG_DAEMON;
216 
217  if (!syslog_opened) {
218  g_log_set_handler (NULL, G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION
219  , assimilation_logger, NULL);
220  }
221  assim_syslogid = strrchr(logname, '/');
222  if (assim_syslogid && assim_syslogid[1] != '\0') {
223  assim_syslogid += 1;
224  }else{
225  assim_syslogid = logname;
226  }
227  if (syslog_opened) {
228  closelog();
229  }
230  g_log_set_fatal_mask (NULL, G_LOG_LEVEL_ERROR);
231  openlog(assim_syslogid, syslog_options, syslog_facility);
232  syslog_opened = TRUE;
233 #endif
234 }
235 void
236 assimilation_logger(const gchar *log_domain,
237  GLogLevelFlags log_level,
238  const gchar *message,
239  gpointer ignored)
240 {
241 #ifdef WIN32
242 #define LOG_INFO 6
243 #define LOG_DEBUG 7
244 #define LOG_NOTICE 5
245 #define LOG_WARNING 4
246 #define LOG_ERR 3
247 #define LOG_CRIT 2
248 #define LOG_ALERT 1
249 #define LOG_EMERG 0
250 #endif
251  int syslogprio = LOG_INFO;
252  const char * prefix = "INFO:";
253 
254  (void)ignored;
255  if (!syslog_opened) {
257  }
258  if (log_level & G_LOG_LEVEL_DEBUG) {
259  syslogprio = LOG_DEBUG;
260  prefix = "DEBUG";
261  }
262  if (log_level & G_LOG_LEVEL_INFO) {
263  syslogprio = LOG_INFO;
264  prefix = "INFO";
265  }
266  if (log_level & G_LOG_LEVEL_MESSAGE) {
267  syslogprio = LOG_NOTICE;
268  prefix = "NOTICE";
269  }
270  if (log_level & G_LOG_LEVEL_WARNING) {
271  syslogprio = LOG_WARNING;
272  prefix = "WARN";
273  }
274  if (log_level & G_LOG_LEVEL_CRITICAL) {
275  syslogprio = LOG_ERR;
276  prefix = "ERROR";
277  }
278  if (log_level & G_LOG_LEVEL_ERROR) {
279  syslogprio = LOG_EMERG; // Or maybe LOG_CRIT ?
280  prefix = "EMERG";
281  }
282 #ifndef WIN32
283  syslog(syslogprio, "%s:%s %s", prefix
284  , log_domain == NULL ? "" : log_domain
285  , message);
286 #else
287  {
288  char msg[256];
289  g_snprintf(msg, sizeof(msg), "%s: %s:%s %s\n",assim_syslogid, prefix
290  , log_domain == NULL ? "" : log_domain
291  , message);
292  OutputDebugString((LPCSTR) msg);
293  }
294 #endif
295  fprintf(stderr, "%s: %s:%s %s\n", assim_syslogid, prefix
296  , log_domain == NULL ? "" : log_domain
297  , message);
298 }
299 
300 #ifdef WIN32
301 #define SEP '\\'
302 //@todo: these will be replaced when windows functionality cathes up
303 #define PROCSELFEXE "/"
304 #define PROCOTHEREXE "/"
305 #else
306 #define SEP '/'
307 #define PROCSELFEXE "/proc/self/exe"
308 #define PROCOTHEREXE "/proc/%d/exe"
309 #endif
310 #define MAXPIDLEN 16
311 #define MAXPATH 256
312 
313 static gboolean created_pid_file = FALSE;
314 
317 are_we_already_running( const char * pidfile
318 , int* pidarg)
319 {
320  char * pidcontents; // Contents of the pid file
321  int pid; // Pid from the pid file
322  char* ourexepath; // Pathname of our executable
323  char* ourexecmd; // command name of our executable
324  char* pidexepath; // Pathname of the 'pid' executable
325  char* pidexecmd; // command name the 'pid' executable
326 #ifdef WIN32
327  char w_ourexepath[MAXPATH];
328  int nSize = MAXPATH-1, ret;
329 #endif
330  char pidexename[sizeof(PROCOTHEREXE)+16]; // Name of /proc entry for 'pid'
331 
332  //g_debug("%s.%d: PID file path [%s]", __FUNCTION__, __LINE__, pidfile);
333  if (pidarg) {
334  *pidarg = 0;
335  }
336 
337  // Does the pid file exist?
338  if (!g_file_test(pidfile, G_FILE_TEST_IS_REGULAR)) {
339  //g_debug("%s.%d: PID file [%s] does not exist", __FUNCTION__, __LINE__, pidfile);
340  return PID_NOTRUNNING;
341  }
342  // Can we read it?
343  if (!g_file_get_contents(pidfile, &pidcontents, NULL, NULL)) {
344  //g_debug("%s.%d: PID file [%s] cannot be read", __FUNCTION__, __LINE__, pidfile);
345  return PID_NOTRUNNING;
346  }
347  // We assume it's passably well-formed...
348  pid = atoi(pidcontents);
349  g_free(pidcontents); pidcontents = NULL;
350  // Is it a legitimate pid value?
351  if (pid < 2) {
352  //g_debug("%s.%d: PID file [%s] contains pid %d", __FUNCTION__, __LINE__, pidfile, pid);
353  return PID_NOTRUNNING;
354  }
355  if (pidarg) {
356  *pidarg = pid;
357  }
358  // Is it still running?
359 #ifdef WIN32
360  if(TerminateProcess((void *)pid, 0) == 0)
361 #else
362  if (kill(pid, 0) < 0 && errno != EPERM)
363 #endif
364  {
365  //g_debug("%s.%d: PID %d is not running", __FUNCTION__, __LINE__, pid);
366  return PID_DEAD;
367  }
368  // Now let's see if it's "us" - our process
369  // That is, is it the same executable as we are?
370 
371  // So, what is the pathname of our executable?
372 #ifndef WIN32
373  ourexepath = g_file_read_link(PROCSELFEXE, NULL);
374 #else
375  ret = GetModuleFileName(NULL, w_ourexepath, nSize);
376  if(ret == 0) {
377  //g_debug("%s.%d: GetModuleFileName failed %d", __FUNCTION__, __LINE__, GetLastError());
378  return(PID_DEAD);
379  }
380  ourexepath = g_strdup(w_ourexepath);
381 #endif
382  if (NULL == ourexepath) {
383  return PID_RUNNING;
384  }
385  if (strrchr(ourexepath, SEP) != NULL) {
386  ourexecmd = strrchr(ourexepath, SEP)+1;
387  }else{
388  ourexecmd = ourexepath;
389  }
390  g_snprintf(pidexename, sizeof(pidexename), PROCOTHEREXE, pid);
391 
392  // What is the pathname of the executable that holds the pid lock?
393  pidexepath = g_file_read_link(pidexename, NULL);
394  if (pidexepath == NULL) {
395  g_free(ourexepath); ourexepath = NULL;
396  return (errno != EPERM ? PID_NOTUS : PID_RUNNING);
397  }
398  if (strrchr(pidexepath, SEP) != NULL) {
399  pidexecmd = strrchr(pidexepath, SEP)+1;
400  }else{
401  pidexecmd = pidexepath;
402  }
403  // Is it the same executable as we are?
404  if (strcmp(ourexecmd, pidexecmd) == 0) {
405  //g_debug("%s.%d: Link %s is the same as %s", __FUNCTION__, __LINE__, ourexepath
406  //, pidexepath);
407  g_free(ourexepath); ourexepath = NULL;
408  g_free(pidexepath); pidexepath = NULL;
409  return PID_RUNNING;
410  }
411  //g_debug("%s.%d: Link %s is NOT the same as %s", __FUNCTION__, __LINE__, ourexecmd
412  //, pidexecmd);
413  g_free(ourexepath); ourexepath = NULL;
414  g_free(pidexepath); pidexepath = NULL;
415  return PID_NOTUS;
416 }
417 
419 gboolean
420 create_pid_file(const char * pidfile)
421 {
422  char pidbuf[16];
423  GError* errptr = NULL;
424  PidRunningStat pstat;
425 
426 #if _MSC_VER
427 WINIMPORT
428 __out
429 void *
430 __stdcall
431 GetCurrentProcess();
432 #define GETPID GetCurrentProcessId()
433 #else
434 #define GETPID getpid()
435 #endif
436  //g_debug("%s.%d: Creating pid file %s for pid %d", __FUNCTION__, __LINE__, pidfile, GETPID);
437  pstat = are_we_already_running(pidfile, NULL);
438  if (PID_RUNNING == pstat) {
439  return FALSE;
440  }
441  g_snprintf(pidbuf, sizeof(pidbuf), "%6d\n", GETPID);
442  if (pstat == PID_DEAD || pstat == PID_NOTUS) {
443  //g_debug("%s.%d: Unlinking dead pid file %s", __FUNCTION__, __LINE__, pidfile);
444  g_unlink(pidfile);
445  }
446 
447  if (g_file_set_contents(pidfile, pidbuf, strlen(pidbuf), &errptr)) {
448  //g_debug("%s.%d: Successfully set file %s to content [%s]"
449  //, __FUNCTION__, __LINE__, pidfile, pidbuf);
450 #ifndef WIN32
451  if (chmod(pidfile, 0644) < 0) {
452  g_warning("%s.%d: Could not chmod pid file %s to 0644", __FUNCTION__, __LINE__
453  , pidfile);
454  }
455 #endif
456  created_pid_file = TRUE;
457  return TRUE;
458  }
459  g_critical("%s.%d: Cannot create pid file [%s]. Reason: %s"
460  , __FUNCTION__, __LINE__, pidfile, errptr->message);
461  fprintf(stderr, "%s.%d: Cannot create pid file [%s]. Reason: %s\n"
462  , __FUNCTION__, __LINE__, pidfile, errptr->message);
463  return FALSE;
464 }
466 char *
468  char *p_pidfile;
469 #ifndef WIN32
470  p_pidfile = g_build_filename(STD_PID_DIR, procname, NULL);
471 #else
472  const char * const *dirs = g_get_system_config_dirs();
473  p_pidfile = g_build_filename(dirs[0], procname, NULL);
474 #endif
475  //g_debug("%s.%d: pidfile = %s", __FUNCTION__, __LINE__, p_pidfile);
476  return(p_pidfile);
477 }
479 void
480 remove_pid_file(const char * pidfile)
481 {
482  if (created_pid_file) {
483  g_unlink(pidfile);
484  }
485 }
486 
488 int
489 kill_pid_service(const char * pidfile, int signal)
490 {
491  int service_pid = 0;
492  PidRunningStat pidstat;
493 
494  pidstat = are_we_already_running(pidfile, &service_pid);
495  if (pidstat == PID_RUNNING) {
496 #ifndef WIN32
497  return kill((pid_t)service_pid, signal);
498 #else
499  if(TerminateProcess((HANDLE) service_pid, signal) != 0) {
500  g_unlink(pidfile);
501  return(-1);
502  }
503 #endif
504  }
505  g_unlink(pidfile); // No harm in removing it...
506  return 0;
507 }
508 
509 static const char * saved_pidfile = NULL;
511 void
512 rmpid_and_exit_on_signal(const char * pidfile, int signal_in)
513 {
514 #ifndef WIN32
515  struct sigaction sigact;
516 #endif
517 
518  if (pidfile != NULL) {
519  saved_pidfile = pidfile;
520  }
521 #ifndef WIN32
522  memset(&sigact, 0, sizeof(sigact));
523  sigact.sa_handler = catch_pid_signal;
524  sigaction(signal_in, &sigact, NULL);
525 #else
526  signal(signal_in, catch_pid_signal);
527 #endif
528 }
529 FSTATIC void
530 catch_pid_signal(int unused_signum)
531 {
532  (void)unused_signum;
533  g_unlink(saved_pidfile);
534  exit(0);
535 }
536 
538 guint
540 {
541  // These exit codes from the Linux Standard Base
542  // http://refspecs.linuxbase.org/LSB_3.1.1/LSB-Core-generic/LSB-Core-generic/iniscrptact.html
543  switch (stat) {
544  case PID_NOTRUNNING:
545  return 3; // LSB: program is not running`
546 
547  case PID_DEAD: /*FALLTHROUGH*/
548  case PID_NOTUS: // This could be an excessively anal retentive check...
549  return 1; // LSB: program is dead and /var/run/pid exists
550 
551  case PID_RUNNING:
552  return 0; // LSB: program is running
553 
554  default: /*FALLTHROUGH*/
555  break;
556  }
557  return 4; // LSB: program or service status is unknown
558 }
559 
561 WINEXPORT gchar **
562 assim_merge_environ(const gchar * const* env
563 , ConfigContext* update)
564 {
565  int j;
566  int initenvcount;
567  int updatecount = 0;
568  gchar** result;
569  int resultelem = 0;
570  gchar** newenv = NULL;
571 
572  if (NULL == env) {
573  // The result of g_get_environ() has to be freed later...
574  // Store malloced copy in 'newenv' so that 'env' parameter can be const...
575  newenv = g_get_environ();
576  env = (const gchar* const*) newenv;
577  }
578 
579  for (initenvcount = 0; env[initenvcount]; ++initenvcount) {
580  ; /* Nothing - just count */
581  }
582  if (update) {
583  updatecount = update->keycount(update);
584  }
585 
586  // This is the worst case for the size needed...
587  result = (gchar**) g_malloc((updatecount+initenvcount+1)* sizeof(gchar*));
588 
589  if (update) {
590  GSList* updatekeys = NULL;
591  GSList* thiskeylist;
592 
593 
594  updatekeys = update->keys(update);
595 
596  // Put all our update keys in first...
597  for (thiskeylist = updatekeys; thiskeylist; thiskeylist=thiskeylist->next) {
598  char * thiskey = (char *)thiskeylist->data;
599  enum ConfigValType vtype= update->gettype(update, thiskey);
600  GString * gsvalue = g_string_new("");
601 
602  g_string_printf(gsvalue, "%s=", thiskey);
603 
604  switch (vtype) {
605  case CFG_BOOL:
606  // Do we want true/false -- or 1/0 ??
607  g_string_append(gsvalue, update->getbool(update, thiskey) ? "true" : "false");
608  break;
609 
610  case CFG_INT64:
611  g_string_append_printf(gsvalue, FMT_64BIT"d", update->getint(update,thiskey));
612  break;
613 
614  case CFG_STRING:
615  g_string_append(gsvalue, update->getstring(update, thiskey));
616  break;
617  case CFG_NETADDR: {
618  NetAddr* addr = update->getaddr(update,thiskey);
619  char * s = addr->baseclass.toString(&addr->baseclass);
620  g_string_append(gsvalue, s);
621  g_free(s);
622  // No need to unref 'addr' - it's not a copy
623  break;
624  }
625  case CFG_ARRAY:
626  g_string_append(gsvalue, _shell_array_value(
627  ( update->getarray(update,thiskey))));
628  break;
629  default:
630  g_string_free(gsvalue, TRUE);
631  gsvalue = NULL;
632  thiskeylist->data = thiskey = NULL;
633  continue;
634  }
635  result[resultelem] = g_string_free(gsvalue, FALSE);
636  gsvalue = NULL;
637  ++resultelem;
638  // The keys in the key list are NOT copies. Don't free them!!
639  // g_free(thiskey);
640  thiskeylist->data = thiskey = NULL;
641  }
642  // Done with 'updatekeys'
643  g_slist_free(updatekeys);
644  updatekeys = NULL;
645 
646  }
647 
648  // Now, add all the env vars not overridden by 'update'
649  for (j = 0; env[j]; ++j) {
650  char * envname;
651  char * eqpos;
652  eqpos = strchr(env[j], '=');
653  if (NULL == eqpos || eqpos == env[j]) {
654  continue;
655  }
656  envname = g_strndup(env[j], eqpos - env[j]);
657  // Make sure it isn't overridden before including it...
658  if (NULL == update || (update->gettype(update, envname) == CFG_EEXIST)) {
659  result[resultelem] = g_strdup(env[j]);
660  ++resultelem;
661  }
662  g_free(envname);
663  }
664  result[resultelem] = NULL;
665 
666  if (newenv) {
667  g_strfreev(newenv);
668  }
669  newenv = NULL;
670  env = NULL;
671  return result;
672 }
673 
675 FSTATIC char *
676 _shell_array_value(GSList* arrayvalue)
677 {
678  GString* gsvalue = g_string_new("");
679  const char * space = "";
680  GSList* thiselem;
681 
682  for (thiselem = arrayvalue; thiselem; thiselem=thiselem->next) {
683  ConfigValue* elem = CASTTOCLASS(ConfigValue, thiselem->data);
684  if (elem->valtype != CFG_STRING) {
685  continue;
686  }
687  g_string_append_printf(gsvalue, "%s%s", space, elem->u.strvalue);
688  space = " ";
689  }
690  return g_string_free(gsvalue, FALSE);
691 }
692 
694 WINEXPORT void
695 assim_free_environ(gchar ** env)
696 {
697  g_strfreev(env);
698 }
699 
700 
702 WINEXPORT gsize
703 setpipebuf(int fd, gsize bufsize)
704 {
705 #ifdef F_SETPIPE_SZ
706 # define SYS_MAX_PIPE_SIZE "/proc/sys/fs/pipe-max-size"
707  if (fcntl(fd, F_SETPIPE_SZ, (int)bufsize) < 0) {
708  int sysfsfd = open(SYS_MAX_PIPE_SIZE, O_WRONLY);
709  if (sysfsfd >= 0) {
710  char sizestr[32];
711  int rc;
712  snprintf(sizestr, sizeof(sizestr), "%zd\n", (size_t)bufsize);
713  // Try our best, and do the best we can...
714  rc = write(sysfsfd, sizestr, sizeof(sizestr)-1);
715  (void)rc;
716  (void)close(sysfsfd);
717  (void)fcntl(fd, F_SETPIPE_SZ, (int)bufsize);
718  }
719  }
720 #else
721  (void)bufsize;
722 #endif
723  // We've done the best we know how above, now check to see how it worked..
724  return getpipebuf(fd);
725 }
726 
728 WINEXPORT gsize
729 getpipebuf(int fd)
730 {
731 #ifdef F_GETPIPE_SZ
732  return (gsize)fcntl(fd, F_GETPIPE_SZ);
733 #else
734  (void)fd;
735  return 4096;
736 #endif
737 }
738 WINEXPORT void
739 assim_g_notify_unref(gpointer assimobj)
740 {
741  AssimObj* obj = CASTTOCLASS(AssimObj, assimobj);
742  obj->unref(obj);
743 }
744 
745 static GIOChannel* _io_channel = NULL;
746 static GIOFunc _io_functocall = NULL;
747 static gpointer _io_add_watch_pointer = NULL;
748 #define MAXCOND (G_IO_IN|G_IO_OUT|G_IO_PRI|G_IO_HUP|G_IO_ERR|G_IO_NVAL)
749 WINEXPORT guint
751 assim_set_io_watch(int fd, //< File descriptor
752  GIOCondition condition, //< Desired Condition
753  GIOFunc func, //< Function to call
754  gpointer user_data) //< data to pass 'func'
755 {
756  GIOChannel* channel;
757  guint retval;
758 #ifdef WIN32
759  channel = g_io_channel_win32_new_fd(fd);
760 #else
761  channel = g_io_channel_unix_new(fd);
762 #endif
763  _io_functocall = func;
764  _io_add_watch_pointer = user_data;
765  _io_channel = channel;
766 #ifdef DEBUG_CALLBACKS
767  g_warning("%s.%d: calling g_io_add_watch(%p, 0x%04x, (proxy:%p (real:%p)), %p)"
768  , __FUNCTION__, __LINE__
769  , channel, condition, _assim_proxy_io_watch, func, user_data);
770 #endif
771  retval = g_io_add_watch(channel, condition, _assim_proxy_io_watch, user_data);
772 #ifdef DEBUG_CALLBACKS
773  g_warning("%s.%d: return %d;", __FUNCTION__, __LINE__, retval);
774 #endif
775  return retval;
776 }
777 
778 #include <stdio.h>
780 FSTATIC gboolean
781 _assim_proxy_io_watch(GIOChannel* source,
782  GIOCondition cond,
783  gpointer data)
784 {
785  gboolean retval;
786  // Validate what we've been given
787  // This only works if we have a single watch active...
788  // For the moment, that's True...
789  if (source != _io_channel || data != _io_add_watch_pointer
790  || (cond&(~MAXCOND)) != 0) {
791  g_error("%s.%d: Called with invalid arguments (%p, 0x%04x, %p)"
792  " saved values are (%p, %p)", __FUNCTION__, __LINE__
793  , source, cond, data
794  , _io_channel, _io_add_watch_pointer);
795  }
796 #ifdef DEBUG_CALLBACKS
797  g_warning("%s.%d: Calling %p(%p, 0x%04x, %p);"
798  " saved values are (%p, %p)"
799  , __FUNCTION__, __LINE__
800  , _io_functocall, source, cond, data
801  , _io_channel, _io_add_watch_pointer);
802 #endif
803  retval = _io_functocall(source, cond, data);
804 #ifdef DEBUG_CALLBACKS
805  g_warning("%s.%d: return(%d);", __FUNCTION__, __LINE__, retval);
806 #endif
807  return retval;
808 }
Definition: misc.h:39
WINEXPORT gsize setpipebuf(int fd, gsize bufsize)
Set the buffer size of a pipe (if possible)
Definition: misc.c:703
const char *(* getstring)(const ConfigContext *, const char *name)
Get String value.
Definition: configcontext.h:86
enum ConfigValType valtype
Definition: configcontext.h:59
Defines miscellaneous interfaces.
char * proj_get_sysname(void)
Return a malloced string of the system name.
char * strvalue
Definition: configcontext.h:64
const char * procname
process name
Definition: nanoprobe.c:112
FSTATIC char * _shell_array_value(GSList *arrayvalue)
Return the value of an array in a shell-compatible way - to put in an environment variable...
Definition: misc.c:676
AssimObj baseclass
Definition: netaddr.h:44
#define PROCSELFEXE
Definition: misc.c:307
#define WINEXPORT
Definition: projectcommon.h:45
#define FSTATIC
Definition: projectcommon.h:31
enum ConfigValType(* gettype)(const ConfigContext *, const char *)
Return type.
Definition: configcontext.h:99
gint64(* getint)(const ConfigContext *, const char *name)
Get integer value.
Definition: configcontext.h:74
int signal
Definition: childprocess.c:238
gboolean create_pid_file(const char *pidfile)
Create a pid file for the current process.
Definition: misc.c:420
NetAddr *(* getaddr)(const ConfigContext *, const char *name)
Get NetAddr value.
Definition: configcontext.h:92
union _ConfigValue::@2 u
#define __FUNCTION__
GSList *(* getarray)(const ConfigContext *, const char *name)
Get array value.
Definition: configcontext.h:84
WINEXPORT void assim_g_notify_unref(gpointer assimobj)
Unref for glib notify.
Definition: misc.c:739
FSTATIC void catch_pid_signal(int signum)
Should be overridden with the name to appear in the logs.
Definition: misc.c:530
void assimilation_openlog(const char *logname)
Open logs in our style (syslog)
Definition: misc.c:211
void assimilation_logger(const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data)
Definition: misc.c:236
WINEXPORT guint assim_set_io_watch(int fd, GIOCondition condition, GIOFunc func, gpointer user_data)
Simiplified interface to g_io_add_watch for our Python code.
Definition: misc.c:751
const char * assim_syslogid
Definition: misc.c:52
tuple GIOFunc
Definition: glib.py:72
#define FMT_64BIT
Format designator for a 64 bit integer.
Definition: projectcommon.h:32
#define STD_PID_DIR
Definition: misc.h:32
gboolean(* getbool)(const ConfigContext *, const char *name)
Get boolean value.
Definition: configcontext.h:77
GSList *(* keys)(const ConfigContext *)
Return list of keys.
Project common header file.
#define DIMOF(a)
Definition: lldp_min.c:30
int kill_pid_service(const char *pidfile, int signal)
kill the service that goes with our current pid file - return negative iff pidfile pid is running and...
Definition: misc.c:489
#define GETPID
Definition: misc.h:40
PidRunningStat
Status of pid file and/or running processes referred to by it - analogous to "service status"...
Definition: misc.h:37
guint pidrunningstat_to_status(PidRunningStat stat)
Convert PidRunningStat to an exit code for status.
Definition: misc.c:539
void rmpid_and_exit_on_signal(const char *pidfile, int signal_in)
Remove PID file and exit when a signal is received.
Definition: misc.c:512
ConfigValType
Definition: configcontext.h:44
void remove_pid_file(const char *pidfile)
Remove the pid file that goes with this service iff we created one during this invocation.
Definition: misc.c:480
#define g_unlink(arg)
Definition: projectcommon.h:61
#define SEP
Definition: misc.c:306
The NetAddr class class represents a general network address - whether IP, MAC, or any other type of ...
Definition: netaddr.h:43
WINEXPORT gchar ** assim_merge_environ(const gchar *const *env, ConfigContext *update)
Merge ConfigContext into possibly NULL current environment, returning a new environment.
Definition: misc.c:562
gchar ** g_get_environ(void)
FSTATIC gboolean _assim_proxy_io_watch(GIOChannel *, GIOCondition, gpointer)
This proxy function is here for debugging C<->Python problems...
Definition: misc.c:781
char * get_default_pid_fileName(const char *procname)
get default pid file name
Definition: misc.c:467
gchar *(* toString)(gconstpointer)
Produce malloc-ed string representation.
Definition: assimobj.h:58
guint(* keycount)(const ConfigContext *)
Return number of keys in object.
#define PROCOTHEREXE
Definition: misc.c:308
PidRunningStat are_we_already_running(const char *pidfile, int *pidarg)
See if the pid file suggests we are already running or not.
Definition: misc.c:317
WINEXPORT void assim_free_environ(gchar **env)
Free the result of assim_merge_env.
Definition: misc.c:695
#define MAXPATH
Definition: misc.c:311
#define MAXCOND
Definition: misc.c:748
#define CASTTOCLASS(Cclass, obj)
Safely cast 'obj' to C-class 'class' - verifying that it was registerd as being of type class ...
Definition: proj_classes.h:66
void(* unref)(gpointer)
Decrement reference count.
Definition: assimobj.h:57
WINEXPORT gsize getpipebuf(int fd)
Return the buffer size of a pipe - if not possible return 4096 (a good guess)
Definition: misc.c:729
void daemonize_me(gboolean stay_in_foreground, const char *dirtorunin, char *pidfile, int minclosefd)
Function to get system name (uname -n in UNIX terms) - and return in lower case
Definition: misc.c:105