GNUnet  0.10.x
os_installation.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2006-2018 GNUnet e.V.
4 
5  GNUnet is free software: you can redistribute it and/or modify it
6  under the terms of the GNU Affero General Public License as published
7  by the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  GNUnet is distributed in the hope that it will be useful, but
11  WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Affero General Public License for more details.
14 
15  You should have received a copy of the GNU Affero General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  SPDX-License-Identifier: AGPL3.0-or-later
19 */
20 
31 #include <sys/stat.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <unistd.h>
35 #include <unistr.h> /* for u16_to_u8 */
36 
37 #include "platform.h"
38 #include "gnunet_util_lib.h"
39 #if DARWIN
40 #include <mach-o/ldsyms.h>
41 #include <mach-o/dyld.h>
42 #elif WINDOWS
43 #include <windows.h>
44 #endif
45 
46 
47 #define LOG(kind,...) GNUNET_log_from (kind, "util-os-installation", __VA_ARGS__)
48 
49 #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util-os-installation", syscall, filename)
50 
51 
56 static const struct GNUNET_OS_ProjectData default_pd = {
57  .libname = "libgnunetutil",
58  .project_dirname = "gnunet",
59  .binary_name = "gnunet-arm",
60  .env_varname = "GNUNET_PREFIX",
61  .base_config_varname = "GNUNET_BASE_CONFIG",
62  .bug_email = "gnunet-developers@gnu.org",
63  .homepage = "http://www.gnu.org/s/gnunet/",
64  .config_file = "gnunet.conf",
65  .user_config_file = "~/.config/gnunet.conf",
66 };
67 
73 
77 const struct GNUNET_OS_ProjectData *
79 {
80  return &default_pd;
81 }
82 
83 
87 const struct GNUNET_OS_ProjectData *
89 {
90  return current_pd;
91 }
92 
93 
99 void
101 {
102  GNUNET_assert (NULL != pd);
103  current_pd = pd;
104 }
105 
106 
107 #if LINUX
108 
113 static char *
114 get_path_from_proc_maps ()
115 {
116  char fn[64];
117  char line[1024];
118  char dir[1024];
119  FILE *f;
120  char *lgu;
121 
122  GNUNET_snprintf (fn, sizeof (fn), "/proc/%u/maps", getpid ());
123  if (NULL == (f = FOPEN (fn, "r")))
124  return NULL;
125  while (NULL != fgets (line, sizeof (line), f))
126  {
127  if ((1 ==
128  SSCANF (line, "%*x-%*x %*c%*c%*c%*c %*x %*2x:%*2x %*u%*[ ]%1023s", dir)) &&
129  (NULL != (lgu = strstr (dir,
130  current_pd->libname))))
131  {
132  lgu[0] = '\0';
133  FCLOSE (f);
134  return GNUNET_strdup (dir);
135  }
136  }
137  FCLOSE (f);
138  return NULL;
139 }
140 
141 
147 static char *
148 get_path_from_proc_exe ()
149 {
150  char fn[64];
151  char lnk[1024];
152  ssize_t size;
153  char *lep;
154 
155  GNUNET_snprintf (fn,
156  sizeof (fn),
157  "/proc/%u/exe",
158  getpid ());
159  size = readlink (fn,
160  lnk,
161  sizeof (lnk) - 1);
162  if (size <= 0)
163  {
165  "readlink",
166  fn);
167  return NULL;
168  }
169  GNUNET_assert ( ((size_t) size) < sizeof (lnk));
170  lnk[size] = '\0';
171  while ((lnk[size] != '/') && (size > 0))
172  size--;
173  GNUNET_asprintf (&lep,
174  "/%s/libexec/",
175  current_pd->project_dirname);
176  /* test for being in lib/gnunet/libexec/ or lib/MULTIARCH/gnunet/libexec */
177  if ( (((size_t) size) > strlen (lep)) &&
178  (0 == strcmp (lep,
179  &lnk[size - strlen (lep)])) )
180  size -= strlen (lep) - 1;
181  GNUNET_free (lep);
182  if ( (size < 4) ||
183  (lnk[size - 4] != '/') )
184  {
185  /* not installed in "/bin/" -- binary path probably useless */
186  return NULL;
187  }
188  lnk[size] = '\0';
189  return GNUNET_strdup (lnk);
190 }
191 #endif
192 
193 
194 #if WINDOWS
195 static HINSTANCE dll_instance;
196 
197 
203 BOOL WINAPI
204 DllMain (HINSTANCE hinstDLL,
205  DWORD fdwReason,
206  LPVOID lpvReserved)
207 {
208  switch (fdwReason)
209  {
210  case DLL_PROCESS_ATTACH:
211  dll_instance = hinstDLL;
212  break;
213  case DLL_THREAD_ATTACH:
214  break;
215  case DLL_THREAD_DETACH:
216  break;
217  case DLL_PROCESS_DETACH:
218  break;
219  }
220  return TRUE;
221 }
222 
223 
229 static char *
230 get_path_from_module_filename ()
231 {
232  size_t pathlen = 512;
233  DWORD real_pathlen;
234  wchar_t *idx;
235  wchar_t *modulepath = NULL;
236  char *upath;
237  uint8_t *u8_string;
238  size_t u8_string_length;
239 
240  /* This braindead function won't tell us how much space it needs, so
241  * we start at 1024 and double the space up if it doesn't fit, until
242  * it fits, or we exceed the threshold.
243  */
244  do
245  {
246  pathlen = pathlen * 2;
247  modulepath = GNUNET_realloc (modulepath,
248  pathlen * sizeof (wchar_t));
249  SetLastError (0);
250  real_pathlen = GetModuleFileNameW (dll_instance,
251  modulepath,
252  pathlen * sizeof (wchar_t));
253  } while (real_pathlen >= pathlen && pathlen < 16*1024);
254  if (real_pathlen >= pathlen)
255  GNUNET_assert (0);
256  /* To be safe */
257  modulepath[real_pathlen] = '\0';
258 
259  idx = modulepath + real_pathlen;
260  while ((idx > modulepath) && (*idx != L'\\') && (*idx != L'/'))
261  idx--;
262  *idx = L'\0';
263 
264  /* Now modulepath holds full path to the directory where libgnunetutil is.
265  * This directory should look like <GNUNET_PREFIX>/bin or <GNUNET_PREFIX>.
266  */
267  if (wcschr (modulepath, L'/') || wcschr (modulepath, L'\\'))
268  {
269  /* At least one directory component (i.e. we're not in a root directory) */
270  wchar_t *dirname = idx;
271  while ((dirname > modulepath) && (*dirname != L'\\') && (*dirname != L'/'))
272  dirname--;
273  *dirname = L'\0';
274  if (dirname > modulepath)
275  {
276  dirname++;
277  /* Now modulepath holds full path to the parent directory of the directory
278  * where libgnunetutil is.
279  * dirname holds the name of the directory where libgnunetutil is.
280  */
281  if (wcsicmp (dirname, L"bin") == 0)
282  {
283  /* pass */
284  }
285  else
286  {
287  /* Roll back our changes to modulepath */
288  dirname--;
289  *dirname = L'/';
290  }
291  }
292  }
293 
294  /* modulepath is GNUNET_PREFIX */
295  u8_string = u16_to_u8 (modulepath, wcslen (modulepath), NULL, &u8_string_length);
296  if (NULL == u8_string)
297  GNUNET_assert (0);
298 
299  upath = GNUNET_malloc (u8_string_length + 1);
300  GNUNET_memcpy (upath, u8_string, u8_string_length);
301  upath[u8_string_length] = '\0';
302 
303  free (u8_string);
304  GNUNET_free (modulepath);
305 
306  return upath;
307 }
308 #endif
309 
310 
311 #if DARWIN
312 
319 typedef int
320 (*MyNSGetExecutablePathProto) (char *buf,
321  size_t *bufsize);
322 
323 
329 static char *
330 get_path_from_NSGetExecutablePath ()
331 {
332  static char zero = '\0';
333  char *path;
334  size_t len;
335  MyNSGetExecutablePathProto func;
336 
337  path = NULL;
338  if (NULL == (func =
339  (MyNSGetExecutablePathProto) dlsym (RTLD_DEFAULT, "_NSGetExecutablePath")))
340  return NULL;
341  path = &zero;
342  len = 0;
343  /* get the path len, including the trailing \0 */
344  (void) func (path, &len);
345  if (0 == len)
346  return NULL;
347  path = GNUNET_malloc (len);
348  if (0 != func (path, &len))
349  {
350  GNUNET_free (path);
351  return NULL;
352  }
353  len = strlen (path);
354  while ((path[len] != '/') && (len > 0))
355  len--;
356  path[len] = '\0';
357  return path;
358 }
359 
360 
366 static char *
367 get_path_from_dyld_image ()
368 {
369  const char *path;
370  char *p;
371  char *s;
372  unsigned int i;
373  int c;
374 
375  c = _dyld_image_count ();
376  for (i = 0; i < c; i++)
377  {
378  if (((const void *) _dyld_get_image_header (i)) !=
379  ((const void *) &_mh_dylib_header) )
380  continue;
381  path = _dyld_get_image_name (i);
382  if ( (NULL == path) || (0 == strlen (path)) )
383  continue;
384  p = GNUNET_strdup (path);
385  s = p + strlen (p);
386  while ((s > p) && ('/' != *s))
387  s--;
388  s++;
389  *s = '\0';
390  return p;
391  }
392  return NULL;
393 }
394 #endif
395 
396 
404 static char *
405 get_path_from_PATH (const char *binary)
406 {
407  char *path;
408  char *pos;
409  char *end;
410  char *buf;
411  const char *p;
412 
413  if (NULL == (p = getenv ("PATH")))
414  return NULL;
415 #if WINDOWS
416  /* On W32 look in CWD first. */
417  GNUNET_asprintf (&path, ".%c%s", PATH_SEPARATOR, p);
418 #else
419  path = GNUNET_strdup (p); /* because we write on it */
420 #endif
421  buf = GNUNET_malloc (strlen (path) + strlen (binary) + 1 + 1);
422  pos = path;
423  while (NULL != (end = strchr (pos, PATH_SEPARATOR)))
424  {
425  *end = '\0';
426  sprintf (buf, "%s/%s", pos, binary);
427  if (GNUNET_DISK_file_test (buf) == GNUNET_YES)
428  {
429  pos = GNUNET_strdup (pos);
430  GNUNET_free (buf);
431  GNUNET_free (path);
432  return pos;
433  }
434  pos = end + 1;
435  }
436  sprintf (buf, "%s/%s", pos, binary);
437  if (GNUNET_YES == GNUNET_DISK_file_test (buf))
438  {
439  pos = GNUNET_strdup (pos);
440  GNUNET_free (buf);
441  GNUNET_free (path);
442  return pos;
443  }
444  GNUNET_free (buf);
445  GNUNET_free (path);
446  return NULL;
447 }
448 
449 
456 static char *
458 {
459  const char *p;
460 
461  if ( (NULL != current_pd->env_varname) &&
462  (NULL != (p = getenv (current_pd->env_varname))) )
463  return GNUNET_strdup (p);
464  if ( (NULL != current_pd->env_varname_alt) &&
465  (NULL != (p = getenv (current_pd->env_varname_alt))) )
466  return GNUNET_strdup (p);
467  return NULL;
468 }
469 
470 
477 static char *
479 {
480  char *ret;
481 
482  if (NULL != (ret = get_path_from_GNUNET_PREFIX ()))
483  return ret;
484 #if LINUX
485  if (NULL != (ret = get_path_from_proc_maps ()))
486  return ret;
487  /* try path *first*, before /proc/exe, as /proc/exe can be wrong */
488  if ( (NULL != current_pd->binary_name) &&
489  (NULL != (ret = get_path_from_PATH (current_pd->binary_name))) )
490  return ret;
491  if (NULL != (ret = get_path_from_proc_exe ()))
492  return ret;
493 #endif
494 #if WINDOWS
495  if (NULL != (ret = get_path_from_module_filename ()))
496  return ret;
497 #endif
498 #if DARWIN
499  if (NULL != (ret = get_path_from_dyld_image ()))
500  return ret;
501  if (NULL != (ret = get_path_from_NSGetExecutablePath ()))
502  return ret;
503 #endif
504  if ( (NULL != current_pd->binary_name) &&
505  (NULL != (ret = get_path_from_PATH (current_pd->binary_name))) )
506  return ret;
507  /* other attempts here */
509  _("Could not determine installation path for %s. Set `%s' environment variable.\n"),
510  current_pd->project_dirname,
511  current_pd->env_varname);
512  return NULL;
513 }
514 
515 
520 static char *
522 {
523  char *ret = NULL;
524 
525 #if LINUX
526  if (NULL != (ret = get_path_from_proc_exe ()))
527  return ret;
528 #endif
529 #if WINDOWS
530  if (NULL != (ret = get_path_from_module_filename ()))
531  return ret;
532 #endif
533 #if DARWIN
534  if (NULL != (ret = get_path_from_NSGetExecutablePath ()))
535  return ret;
536 #endif
537  /* other attempts here */
538  return ret;
539 }
540 
541 
547 char *
549 {
550  size_t n;
551  char *dirname;
552  char *execpath = NULL;
553  char *tmp;
554  char *multiarch;
555  char *libdir;
556  int isbasedir;
557 
558  /* if wanted, try to get the current app's bin/ */
559  if (dirkind == GNUNET_OS_IPK_SELF_PREFIX)
560  execpath = os_get_exec_path ();
561 
562  /* try to get GNUnet's bin/ or lib/, or if previous was unsuccessful some
563  * guess for the current app */
564  if (NULL == execpath)
565  execpath = os_get_gnunet_path ();
566 
567  if (NULL == execpath)
568  return NULL;
569 
570  n = strlen (execpath);
571  if (0 == n)
572  {
573  /* should never happen, but better safe than sorry */
574  GNUNET_free (execpath);
575  return NULL;
576  }
577  /* remove filename itself */
578  while ((n > 1) && (DIR_SEPARATOR == execpath[n - 1]))
579  execpath[--n] = '\0';
580 
581  isbasedir = 1;
582  if ((n > 6) &&
583  ((0 == strcasecmp (&execpath[n - 6], "/lib32")) ||
584  (0 == strcasecmp (&execpath[n - 6], "/lib64"))))
585  {
586  if ( (GNUNET_OS_IPK_LIBDIR != dirkind) &&
587  (GNUNET_OS_IPK_LIBEXECDIR != dirkind) )
588  {
589  /* strip '/lib32' or '/lib64' */
590  execpath[n - 6] = '\0';
591  n -= 6;
592  }
593  else
594  isbasedir = 0;
595  }
596  else if ((n > 4) &&
597  ((0 == strcasecmp (&execpath[n - 4], "/bin")) ||
598  (0 == strcasecmp (&execpath[n - 4], "/lib"))))
599  {
600  /* strip '/bin' or '/lib' */
601  execpath[n - 4] = '\0';
602  n -= 4;
603  }
604  multiarch = NULL;
605  if (NULL != (libdir = strstr (execpath, "/lib/")))
606  {
607  /* test for multi-arch path of the form "PREFIX/lib/MULTIARCH/";
608  here we need to re-add 'multiarch' to lib and libexec paths later! */
609  multiarch = &libdir[5];
610  if (NULL == strchr (multiarch, '/'))
611  libdir[0] = '\0'; /* Debian multiarch format, cut of from 'execpath' but preserve in multicarch */
612  else
613  multiarch = NULL; /* maybe not, multiarch still has a '/', which is not OK */
614  }
615  /* in case this was a directory named foo-bin, remove "foo-" */
616  while ((n > 1) && (execpath[n - 1] == DIR_SEPARATOR))
617  execpath[--n] = '\0';
618  switch (dirkind)
619  {
622  dirname = GNUNET_strdup (DIR_SEPARATOR_STR);
623  break;
626  break;
628  if (isbasedir)
629  {
630  GNUNET_asprintf (&tmp,
631  "%s%s%s%s%s%s%s",
632  execpath,
633  DIR_SEPARATOR_STR "lib",
634  (NULL != multiarch) ? DIR_SEPARATOR_STR : "",
635  (NULL != multiarch) ? multiarch : "",
636  DIR_SEPARATOR_STR,
637  current_pd->project_dirname,
638  DIR_SEPARATOR_STR);
639  if (GNUNET_YES ==
641  {
642  GNUNET_free (execpath);
643  return tmp;
644  }
645  GNUNET_free (tmp);
646  tmp = NULL;
647  dirname = NULL;
648  if (4 == sizeof (void *))
649  {
650  GNUNET_asprintf (&dirname,
651  DIR_SEPARATOR_STR "lib32" DIR_SEPARATOR_STR "%s" DIR_SEPARATOR_STR,
652  current_pd->project_dirname);
653  GNUNET_asprintf (&tmp,
654  "%s%s",
655  execpath,
656  dirname);
657  }
658  if (8 == sizeof (void *))
659  {
660  GNUNET_asprintf (&dirname,
661  DIR_SEPARATOR_STR "lib64" DIR_SEPARATOR_STR "%s" DIR_SEPARATOR_STR,
662  current_pd->project_dirname);
663  GNUNET_asprintf (&tmp,
664  "%s%s",
665  execpath,
666  dirname);
667  }
668 
669  if ( (NULL != tmp) &&
670  (GNUNET_YES ==
672  {
673  GNUNET_free (execpath);
674  GNUNET_free_non_null (dirname);
675  return tmp;
676  }
677  GNUNET_free (tmp);
678  GNUNET_free_non_null (dirname);
679  }
680  GNUNET_asprintf (&dirname,
681  DIR_SEPARATOR_STR "%s" DIR_SEPARATOR_STR,
682  current_pd->project_dirname);
683  break;
685  GNUNET_asprintf (&dirname,
686  DIR_SEPARATOR_STR "share" DIR_SEPARATOR_STR "%s" DIR_SEPARATOR_STR,
687  current_pd->project_dirname);
688  break;
690  dirname = GNUNET_strdup (DIR_SEPARATOR_STR "share" DIR_SEPARATOR_STR "locale" DIR_SEPARATOR_STR);
691  break;
693  dirname = GNUNET_strdup (DIR_SEPARATOR_STR "share" DIR_SEPARATOR_STR "icons" DIR_SEPARATOR_STR);
694  break;
696  GNUNET_asprintf (&dirname,
697  DIR_SEPARATOR_STR "share" DIR_SEPARATOR_STR "doc" DIR_SEPARATOR_STR "%s" DIR_SEPARATOR_STR,
698  current_pd->project_dirname);
699  break;
701  if (isbasedir)
702  {
703  GNUNET_asprintf (&dirname,
704  DIR_SEPARATOR_STR "%s" DIR_SEPARATOR_STR "libexec" DIR_SEPARATOR_STR,
705  current_pd->project_dirname);
706  GNUNET_asprintf (&tmp,
707  "%s%s%s%s",
708  execpath,
709  DIR_SEPARATOR_STR "lib" DIR_SEPARATOR_STR,
710  (NULL != multiarch) ? multiarch : "",
711  dirname);
712  if (GNUNET_YES ==
714  {
715  GNUNET_free (execpath);
716  GNUNET_free (dirname);
717  return tmp;
718  }
719  GNUNET_free (tmp);
720  tmp = NULL;
721  dirname = NULL;
722  if (4 == sizeof (void *))
723  {
724  GNUNET_asprintf (&dirname,
725  DIR_SEPARATOR_STR "lib32" DIR_SEPARATOR_STR "%s" DIR_SEPARATOR_STR "libexec" DIR_SEPARATOR_STR,
726  current_pd->project_dirname);
727  GNUNET_asprintf (&tmp,
728  "%s%s",
729  execpath,
730  dirname);
731  }
732  if (8 == sizeof (void *))
733  {
734  GNUNET_asprintf (&dirname,
735  DIR_SEPARATOR_STR "lib64" DIR_SEPARATOR_STR "%s" DIR_SEPARATOR_STR "libexec" DIR_SEPARATOR_STR,
736  current_pd->project_dirname);
737  GNUNET_asprintf (&tmp,
738  "%s%s",
739  execpath,
740  dirname);
741  }
742  if ( (NULL != tmp) &&
743  (GNUNET_YES ==
745  {
746  GNUNET_free (execpath);
747  GNUNET_free_non_null (dirname);
748  return tmp;
749  }
750  GNUNET_free (tmp);
751  GNUNET_free_non_null (dirname);
752  }
753  GNUNET_asprintf (&dirname,
754  DIR_SEPARATOR_STR "%s" DIR_SEPARATOR_STR "libexec" DIR_SEPARATOR_STR,
755  current_pd->project_dirname);
756  break;
757  default:
758  GNUNET_free (execpath);
759  return NULL;
760  }
761  GNUNET_asprintf (&tmp,
762  "%s%s",
763  execpath,
764  dirname);
765  GNUNET_free (dirname);
766  GNUNET_free (execpath);
767  return tmp;
768 }
769 
770 
779 char *
780 GNUNET_OS_get_libexec_binary_path (const char *progname)
781 {
782  static char *cache;
783  char *libexecdir;
784  char *binary;
785 
786  if ( (DIR_SEPARATOR == progname[0]) ||
787  (GNUNET_YES ==
789  GNUNET_NO,
790  NULL, NULL)) )
791  return GNUNET_strdup (progname);
792  if (NULL != cache)
793  libexecdir = cache;
794  else
796  if (NULL == libexecdir)
797  return GNUNET_strdup (progname);
798  GNUNET_asprintf (&binary,
799  "%s%s",
800  libexecdir,
801  progname);
802  cache = libexecdir;
803  return binary;
804 }
805 
806 
819 char *
821  const char *progname)
822 {
823  static char *cache;
824  char *binary = NULL;
825  char *path = NULL;
826  size_t path_len;
827 
828  if (GNUNET_YES ==
830  GNUNET_NO,
831  NULL, NULL))
832  {
833  return GNUNET_strdup (progname);
834  }
835  if (NULL != cache)
836  path = cache;
837  else
839  "PATHS",
840  "SUID_BINARY_PATH",
841  &path);
842  if (NULL == path || 0 == strlen (path))
843  return GNUNET_OS_get_libexec_binary_path (progname);
844  path_len = strlen (path);
845  GNUNET_asprintf (&binary,
846  "%s%s%s",
847  path,
848  (path[path_len - 1] == DIR_SEPARATOR) ? "" : DIR_SEPARATOR_STR,
849  progname);
850  cache = path;
851  return binary;
852 }
853 
854 
871 int
872 GNUNET_OS_check_helper_binary (const char *binary,
873  int check_suid,
874  const char *params)
875 {
876  struct stat statbuf;
877  char *p;
878  char *pf;
879 #ifdef MINGW
880  char *binaryexe;
881 
882  GNUNET_asprintf (&binaryexe,
883  "%s.exe",
884  binary);
885  if ( (GNUNET_YES ==
887  GNUNET_NO,
888  NULL, NULL)) ||
889  (0 == strncmp (binary, "./", 2)) )
890  p = GNUNET_strdup (binaryexe);
891  else
892  {
893  p = get_path_from_PATH (binaryexe);
894  if (NULL != p)
895  {
896  GNUNET_asprintf (&pf, "%s/%s", p, binaryexe);
897  GNUNET_free (p);
898  p = pf;
899  }
900  }
901  GNUNET_free (binaryexe);
902 #else
903  if ( (GNUNET_YES ==
905  GNUNET_NO,
906  NULL,
907  NULL)) ||
908  (0 == strncmp (binary, "./", 2)) )
909  {
910  p = GNUNET_strdup (binary);
911  }
912  else
913  {
914  p = get_path_from_PATH (binary);
915  if (NULL != p)
916  {
917  GNUNET_asprintf (&pf,
918  "%s/%s",
919  p,
920  binary);
921  GNUNET_free (p);
922  p = pf;
923  }
924  }
925 #endif
926  if (NULL == p)
927  {
929  _("Could not find binary `%s' in PATH!\n"),
930  binary);
931  return GNUNET_SYSERR;
932  }
933  if (0 != ACCESS (p,
934  X_OK))
935  {
937  "access",
938  p);
939  GNUNET_free (p);
940  return GNUNET_SYSERR;
941  }
942 #ifndef MINGW
943  if (0 == getuid ())
944  {
945  /* as we run as root, we don't insist on SUID */
946  GNUNET_free (p);
947  return GNUNET_YES;
948  }
949 #endif
950  if (0 != STAT (p,
951  &statbuf))
952  {
954  "stat",
955  p);
956  GNUNET_free (p);
957  return GNUNET_SYSERR;
958  }
959  if (check_suid)
960  {
961 #ifndef MINGW
962  (void) params;
963  if ( (0 != (statbuf.st_mode & S_ISUID)) &&
964  (0 == statbuf.st_uid) )
965  {
966  GNUNET_free (p);
967  return GNUNET_YES;
968  }
970  _("Binary `%s' exists, but is not SUID\n"),
971  p);
972  /* binary exists, but not SUID */
973 #else
974  STARTUPINFO start;
975  char parameters[512];
976  PROCESS_INFORMATION proc;
977  DWORD exit_value;
978 
979  GNUNET_snprintf (parameters,
980  sizeof (parameters),
981  "-d %s", params);
982  memset (&start, 0, sizeof (start));
983  start.cb = sizeof (start);
984  memset (&proc, 0, sizeof (proc));
985 
986 
987  // Start the child process.
988  if ( ! (CreateProcess( p, // current windows (2k3 and up can handle / instead of \ in paths))
989  parameters, // execute dryrun/priviliege checking mode
990  NULL, // Process handle not inheritable
991  NULL, // Thread handle not inheritable
992  FALSE, // Set handle inheritance to FALSE
993  CREATE_DEFAULT_ERROR_MODE, // No creation flags
994  NULL, // Use parent's environment block
995  NULL, // Use parent's starting directory
996  &start, // Pointer to STARTUPINFO structure
997  &proc ) // Pointer to PROCESS_INFORMATION structure
998  ))
999  {
1001  _("CreateProcess failed for binary %s (%d).\n"),
1002  p, GetLastError());
1003  return GNUNET_SYSERR;
1004  }
1005 
1006  // Wait until child process exits.
1007  WaitForSingleObject( proc.hProcess, INFINITE );
1008 
1009  if ( ! GetExitCodeProcess (proc.hProcess, &exit_value)){
1011  _("GetExitCodeProcess failed for binary %s (%d).\n"),
1012  p, GetLastError() );
1013  return GNUNET_SYSERR;
1014  }
1015  // Close process and thread handles.
1016  CloseHandle( proc.hProcess );
1017  CloseHandle( proc.hThread );
1018 
1019  if (!exit_value)
1020  return GNUNET_YES;
1021 #endif
1022  }
1023  GNUNET_free (p);
1024  return GNUNET_NO;
1025 }
1026 
1027 
1028 /* end of os_installation.c */
static const struct GNUNET_CRYPTO_EcdsaPrivateKey zero
Public key of all zeros.
int GNUNET_DISK_file_test(const char *fil)
Check that fil corresponds to a filename (of a file that exists and that is not a directory)...
Definition: disk.c:669
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
Definition: w32nsp.c:272
static char * dir
Set to the directory where runtime files are stored.
Definition: gnunet-arm.c:84
Return the directory where translations are installed (share/locale/)
Project-specific data used to help the OS subsystem find installation paths.
static int end
Set if we are to shutdown all services (including ARM).
Definition: gnunet-arm.c:34
int GNUNET_snprintf(char *buf, size_t size, const char *format,...)
Like snprintf, just aborts if the buffer is of insufficient size.
Return the directory where libraries are installed.
const char * project_dirname
Name of the project that is used in the "libexec" prefix, For example, "gnunet".
static int start
Set if we are to start default services (including ARM).
Definition: gnunet-arm.c:39
int GNUNET_STRINGS_path_is_absolute(const char *filename, int can_be_uri, int *r_is_uri, char **r_uri_scheme)
Check whether filename is absolute or not, and if it&#39;s an URI.
Definition: strings.c:1171
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
static char * os_get_gnunet_path()
get the path to GNUnet bin/ or lib/, prefering the lib/ path
int GNUNET_DISK_directory_test(const char *fil, int is_readable)
Test if fil is a directory and listable.
Definition: disk.c:628
const char * env_varname_alt
Alternative name of an environment variable that can be used to override installation path detection...
#define GNUNET_NO
Definition: gnunet_common.h:81
const struct GNUNET_OS_ProjectData * GNUNET_OS_project_data_default(void)
Return default project data used by &#39;libgnunetutil&#39; for GNUnet.
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
int GNUNET_OS_check_helper_binary(const char *binary, int check_suid, const char *params)
Check whether an executable exists and possibly if the suid bit is set on the file.
#define STAT(p, b)
Definition: plibc.h:663
static int ret
Final status code.
Definition: gnunet-arm.c:89
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define FOPEN(f, m)
Definition: plibc.h:644
#define _(String)
GNU gettext support macro.
Definition: platform.h:208
Return the "PREFIX" directory given to configure.
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
const char * env_varname
Name of an environment variable that can be used to override installation path detection, for example "GNUNET_PREFIX".
#define LOG(kind,...)
#define GNUNET_memcpy(dst, src, n)
static struct GNUNET_OS_Process * p
Helper process we started.
Definition: gnunet-qr.c:59
static char * line
Desired phone line (string to be converted to a hash).
Return the prefix of the path with documentation files, including the license (share/doc/gnunet/).
const char * libname
Name of a library that is installed in the "lib/" directory of the project, such as "libgnunetutil"...
static char * fn
Filename of the unique file.
#define GNUNET_realloc(ptr, size)
Wrapper around realloc.
char * GNUNET_OS_installation_get_path(enum GNUNET_OS_InstallationPathKind dirkind)
get the path to a specific GNUnet installation directory or, with GNUNET_OS_IPK_SELF_PREFIX, the current running apps installation directory
static const struct GNUNET_OS_ProjectData default_pd
Default project data used for installation path detection for GNUnet (core).
static char buf[2048]
const char * binary_name
Name of a project-specific binary that should be in "$PREFIX/bin/".
char * GNUNET_OS_get_suid_binary_path(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *progname)
Given the name of a helper, service or daemon binary construct the full path to the binary using the ...
Return the directory where helper binaries are installed (lib/gnunet/libexec/)
#define DIR_SEPARATOR
Definition: plibc.h:631
GNUNET_OS_InstallationPathKind
Possible installation paths to request.
int GNUNET_CONFIGURATION_get_value_string(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be a string.
static struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
Definition: gnunet-arm.c:104
static char * os_get_exec_path()
get the path to current app&#39;s bin/
#define GNUNET_SYSERR
Definition: gnunet_common.h:79
static unsigned int size
Size of the "table".
Definition: peer.c:67
char * getenv()
static const struct GNUNET_OS_ProjectData * current_pd
Which project data do we currently use for installation path detection? Never NULL.
Return the installation directory of this application, not the one of the overall GNUnet installation...
#define LOG_STRERROR_FILE(kind, syscall, filename)
#define PATH_SEPARATOR
Definition: plibc.h:633
Return the directory where the program binaries are installed.
static char * get_path_from_PATH(const char *binary)
Return the actual path to a file found in the current PATH environment variable.
static struct GNUNET_CONTAINER_MultiHashMap32 * cache
Hashmap to maintain cache.
#define SSCANF
Definition: plibc.h:691
configuration data
Definition: configuration.c:85
static char * get_path_from_GNUNET_PREFIX()
Try to obtain the installation path using the "GNUNET_PREFIX" environment variable.
#define GNUNET_log(kind,...)
const struct GNUNET_OS_ProjectData * GNUNET_OS_project_data_get()
char * GNUNET_OS_get_libexec_binary_path(const char *progname)
Given the name of a gnunet-helper, gnunet-service or gnunet-daemon binary, try to prefix it with the ...
void GNUNET_OS_init(const struct GNUNET_OS_ProjectData *pd)
Setup OS subsystem with project data.
#define FCLOSE(f)
Definition: plibc.h:645
#define GNUNET_YES
Definition: gnunet_common.h:80
Return the prefix of the path with application icons (share/icons/).
#define DIR_SEPARATOR_STR
Definition: plibc.h:632
#define ACCESS(p, m)
Definition: plibc.h:656
#define GNUNET_malloc(size)
Wrapper around malloc.
Return the directory where data is installed (share/gnunet/)
#define GNUNET_free(ptr)
Wrapper around free.
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...