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