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