common: Use strconcat in gnupg_setenv.
[gnupg.git] / common / sysutils.c
1 /* sysutils.c -  system helpers
2  * Copyright (C) 1991-2001, 2003-2004,
3  *               2006-2008  Free Software Foundation, Inc.
4  * Copyright (C) 2013-2014 Werner Koch
5  *
6  * This file is part of GnuPG.
7  *
8  * This file is free software; you can redistribute it and/or modify
9  * it under the terms of either
10  *
11  *   - the GNU Lesser General Public License as published by the Free
12  *     Software Foundation; either version 3 of the License, or (at
13  *     your option) any later version.
14  *
15  * or
16  *
17  *   - the GNU General Public License as published by the Free
18  *     Software Foundation; either version 2 of the License, or (at
19  *     your option) any later version.
20  *
21  * or both in parallel, as here.
22  *
23  * This file is distributed in the hope that it will be useful,
24  * but WITHOUT ANY WARRANTY; without even the implied warranty of
25  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26  * GNU General Public License for more details.
27  *
28  * You should have received a copy of the GNU General Public License
29  * along with this program; if not, see <http://www.gnu.org/licenses/>.
30  */
31
32 #include <config.h>
33
34 #ifdef WITHOUT_NPTH /* Give the Makefile a chance to build without Pth.  */
35 # undef HAVE_NPTH
36 # undef USE_NPTH
37 #endif
38
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <stdint.h>
42 #include <string.h>
43 #include <unistd.h>
44 #include <errno.h>
45 #ifdef HAVE_STAT
46 # include <sys/stat.h>
47 #endif
48 #if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2
49 # include <asm/sysinfo.h>
50 # include <asm/unistd.h>
51 #endif
52 #ifdef HAVE_SETRLIMIT
53 # include <time.h>
54 # include <sys/time.h>
55 # include <sys/resource.h>
56 #endif
57 #ifdef HAVE_W32_SYSTEM
58 # if WINVER < 0x0500
59 #   define WINVER 0x0500  /* Required for AllowSetForegroundWindow.  */
60 # endif
61 # ifdef HAVE_WINSOCK2_H
62 #  include <winsock2.h>
63 # endif
64 # include <windows.h>
65 #endif
66 #ifdef HAVE_INOTIFY_INIT
67 # include <sys/inotify.h>
68 #endif /*HAVE_INOTIFY_INIT*/
69 #ifdef HAVE_NPTH
70 # include <npth.h>
71 #endif
72 #include <fcntl.h>
73
74 #include <assuan.h>
75
76 #include "util.h"
77 #include "i18n.h"
78
79 #include "sysutils.h"
80
81 #define tohex(n) ((n) < 10 ? ((n) + '0') : (((n) - 10) + 'A'))
82
83
84 static GPGRT_INLINE gpg_error_t
85 my_error_from_syserror (void)
86 {
87   return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
88 }
89
90 static GPGRT_INLINE gpg_error_t
91 my_error (int e)
92 {
93   return gpg_err_make (default_errsource, (e));
94 }
95
96
97
98 #if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2
99 #warning using trap_unaligned
100 static int
101 setsysinfo(unsigned long op, void *buffer, unsigned long size,
102                      int *start, void *arg, unsigned long flag)
103 {
104     return syscall(__NR_osf_setsysinfo, op, buffer, size, start, arg, flag);
105 }
106
107 void
108 trap_unaligned(void)
109 {
110     unsigned int buf[2];
111
112     buf[0] = SSIN_UACPROC;
113     buf[1] = UAC_SIGBUS | UAC_NOPRINT;
114     setsysinfo(SSI_NVPAIRS, buf, 1, 0, 0, 0);
115 }
116 #else
117 void
118 trap_unaligned(void)
119 {  /* dummy */
120 }
121 #endif
122
123
124 int
125 disable_core_dumps (void)
126 {
127 #ifdef HAVE_DOSISH_SYSTEM
128     return 0;
129 #else
130 # ifdef HAVE_SETRLIMIT
131     struct rlimit limit;
132
133     /* We only set the current limit unless we were not able to
134        retrieve the old value. */
135     if (getrlimit (RLIMIT_CORE, &limit))
136       limit.rlim_max = 0;
137     limit.rlim_cur = 0;
138     if( !setrlimit (RLIMIT_CORE, &limit) )
139         return 0;
140     if( errno != EINVAL && errno != ENOSYS )
141         log_fatal (_("can't disable core dumps: %s\n"), strerror(errno) );
142 #endif
143     return 1;
144 #endif
145 }
146
147 int
148 enable_core_dumps (void)
149 {
150 #ifdef HAVE_DOSISH_SYSTEM
151     return 0;
152 #else
153 # ifdef HAVE_SETRLIMIT
154     struct rlimit limit;
155
156     if (getrlimit (RLIMIT_CORE, &limit))
157       return 1;
158     limit.rlim_cur = limit.rlim_max;
159     setrlimit (RLIMIT_CORE, &limit);
160     return 1; /* We always return true because this function is
161                  merely a debugging aid. */
162 # endif
163     return 1;
164 #endif
165 }
166
167
168
169 /* Return a string which is used as a kind of process ID.  */
170 const byte *
171 get_session_marker (size_t *rlen)
172 {
173   static byte marker[SIZEOF_UNSIGNED_LONG*2];
174   static int initialized;
175
176   if (!initialized)
177     {
178       gcry_create_nonce (marker, sizeof marker);
179       initialized = 1;
180     }
181   *rlen = sizeof (marker);
182   return marker;
183 }
184
185 /* Return a random number in an unsigned int. */
186 unsigned int
187 get_uint_nonce (void)
188 {
189   unsigned int value;
190
191   gcry_create_nonce (&value, sizeof value);
192   return value;
193 }
194
195
196
197 #if 0 /* not yet needed - Note that this will require inclusion of
198          cmacros.am in Makefile.am */
199 int
200 check_permissions(const char *path,int extension,int checkonly)
201 {
202 #if defined(HAVE_STAT) && !defined(HAVE_DOSISH_SYSTEM)
203   char *tmppath;
204   struct stat statbuf;
205   int ret=1;
206   int isdir=0;
207
208   if(opt.no_perm_warn)
209     return 0;
210
211   if(extension && path[0]!=DIRSEP_C)
212     {
213       if(strchr(path,DIRSEP_C))
214         tmppath=make_filename(path,NULL);
215       else
216         tmppath=make_filename(GNUPG_LIBDIR,path,NULL);
217     }
218   else
219     tmppath=m_strdup(path);
220
221   /* It's okay if the file doesn't exist */
222   if(stat(tmppath,&statbuf)!=0)
223     {
224       ret=0;
225       goto end;
226     }
227
228   isdir=S_ISDIR(statbuf.st_mode);
229
230   /* Per-user files must be owned by the user.  Extensions must be
231      owned by the user or root. */
232   if((!extension && statbuf.st_uid != getuid()) ||
233      (extension && statbuf.st_uid!=0 && statbuf.st_uid!=getuid()))
234     {
235       if(!checkonly)
236         log_info(_("Warning: unsafe ownership on %s \"%s\"\n"),
237                  isdir?"directory":extension?"extension":"file",path);
238       goto end;
239     }
240
241   /* This works for both directories and files - basically, we don't
242      care what the owner permissions are, so long as the group and
243      other permissions are 0 for per-user files, and non-writable for
244      extensions. */
245   if((extension && (statbuf.st_mode & (S_IWGRP|S_IWOTH)) !=0) ||
246      (!extension && (statbuf.st_mode & (S_IRWXG|S_IRWXO)) != 0))
247     {
248       char *dir;
249
250       /* However, if the directory the directory/file is in is owned
251          by the user and is 700, then this is not a problem.
252          Theoretically, we could walk this test up to the root
253          directory /, but for the sake of sanity, I'm stopping at one
254          level down. */
255
256       dir= make_dirname (tmppath);
257       if(stat(dir,&statbuf)==0 && statbuf.st_uid==getuid() &&
258          S_ISDIR(statbuf.st_mode) && (statbuf.st_mode & (S_IRWXG|S_IRWXO))==0)
259         {
260           xfree (dir);
261           ret=0;
262           goto end;
263         }
264
265       m_free(dir);
266
267       if(!checkonly)
268         log_info(_("Warning: unsafe permissions on %s \"%s\"\n"),
269                  isdir?"directory":extension?"extension":"file",path);
270       goto end;
271     }
272
273   ret=0;
274
275  end:
276   m_free(tmppath);
277
278   return ret;
279
280 #endif /* HAVE_STAT && !HAVE_DOSISH_SYSTEM */
281
282   return 0;
283 }
284 #endif
285
286
287 /* Wrapper around the usual sleep function.  This one won't wake up
288    before the sleep time has really elapsed.  When build with Pth it
289    merely calls pth_sleep and thus suspends only the current
290    thread. */
291 void
292 gnupg_sleep (unsigned int seconds)
293 {
294 #ifdef USE_NPTH
295   npth_sleep (seconds);
296 #else
297   /* Fixme:  make sure that a sleep won't wake up to early.  */
298 # ifdef HAVE_W32_SYSTEM
299   Sleep (seconds*1000);
300 # else
301   sleep (seconds);
302 # endif
303 #endif
304 }
305
306
307 /* This function is a NOP for POSIX systems but required under Windows
308    as the file handles as returned by OS calls (like CreateFile) are
309    different from the libc file descriptors (like open). This function
310    translates system file handles to libc file handles.  FOR_WRITE
311    gives the direction of the handle.  */
312 int
313 translate_sys2libc_fd (gnupg_fd_t fd, int for_write)
314 {
315 #if defined(HAVE_W32CE_SYSTEM)
316   (void)for_write;
317   return (int) fd;
318 #elif defined(HAVE_W32_SYSTEM)
319   int x;
320
321   if (fd == GNUPG_INVALID_FD)
322     return -1;
323
324   /* Note that _open_osfhandle is currently defined to take and return
325      a long.  */
326   x = _open_osfhandle ((long)fd, for_write ? 1 : 0);
327   if (x == -1)
328     log_error ("failed to translate osfhandle %p\n", (void *) fd);
329   return x;
330 #else /*!HAVE_W32_SYSTEM */
331   (void)for_write;
332   return fd;
333 #endif
334 }
335
336 /* This is the same as translate_sys2libc_fd but takes an integer
337    which is assumed to be such an system handle.  On WindowsCE the
338    passed FD is a rendezvous ID and the function finishes the pipe
339    creation. */
340 int
341 translate_sys2libc_fd_int (int fd, int for_write)
342 {
343 #if HAVE_W32CE_SYSTEM
344   fd = (int) _assuan_w32ce_finish_pipe (fd, for_write);
345   return translate_sys2libc_fd ((void*)fd, for_write);
346 #elif HAVE_W32_SYSTEM
347   if (fd <= 2)
348     return fd;  /* Do not do this for error, stdin, stdout, stderr. */
349
350   return translate_sys2libc_fd ((void*)fd, for_write);
351 #else
352   (void)for_write;
353   return fd;
354 #endif
355 }
356
357
358
359 /* Replacement for tmpfile().  This is required because the tmpfile
360    function of Windows' runtime library is broken, insecure, ignores
361    TMPDIR and so on.  In addition we create a file with an inheritable
362    handle.  */
363 FILE *
364 gnupg_tmpfile (void)
365 {
366 #ifdef HAVE_W32_SYSTEM
367   int attempts, n;
368 #ifdef HAVE_W32CE_SYSTEM
369   wchar_t buffer[MAX_PATH+7+12+1];
370 # define mystrlen(a) wcslen (a)
371   wchar_t *name, *p;
372 #else
373   char buffer[MAX_PATH+7+12+1];
374 # define mystrlen(a) strlen (a)
375   char *name, *p;
376 #endif
377   HANDLE file;
378   int pid = GetCurrentProcessId ();
379   unsigned int value;
380   int i;
381   SECURITY_ATTRIBUTES sec_attr;
382
383   memset (&sec_attr, 0, sizeof sec_attr );
384   sec_attr.nLength = sizeof sec_attr;
385   sec_attr.bInheritHandle = TRUE;
386
387   n = GetTempPath (MAX_PATH+1, buffer);
388   if (!n || n > MAX_PATH || mystrlen (buffer) > MAX_PATH)
389     {
390       gpg_err_set_errno (ENOENT);
391       return NULL;
392     }
393   p = buffer + mystrlen (buffer);
394 #ifdef HAVE_W32CE_SYSTEM
395   wcscpy (p, L"_gnupg");
396   p += 7;
397 #else
398   p = stpcpy (p, "_gnupg");
399 #endif
400   /* We try to create the directory but don't care about an error as
401      it may already exist and the CreateFile would throw an error
402      anyway.  */
403   CreateDirectory (buffer, NULL);
404   *p++ = '\\';
405   name = p;
406   for (attempts=0; attempts < 10; attempts++)
407     {
408       p = name;
409       value = (GetTickCount () ^ ((pid<<16) & 0xffff0000));
410       for (i=0; i < 8; i++)
411         {
412           *p++ = tohex (((value >> 28) & 0x0f));
413           value <<= 4;
414         }
415 #ifdef HAVE_W32CE_SYSTEM
416       wcscpy (p, L".tmp");
417 #else
418       strcpy (p, ".tmp");
419 #endif
420       file = CreateFile (buffer,
421                          GENERIC_READ | GENERIC_WRITE,
422                          0,
423                          &sec_attr,
424                          CREATE_NEW,
425                          FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE,
426                          NULL);
427       if (file != INVALID_HANDLE_VALUE)
428         {
429           FILE *fp;
430 #ifdef HAVE_W32CE_SYSTEM
431           int fd = (int)file;
432           fp = _wfdopen (fd, L"w+b");
433 #else
434           int fd = _open_osfhandle ((long)file, 0);
435           if (fd == -1)
436             {
437               CloseHandle (file);
438               return NULL;
439             }
440           fp = fdopen (fd, "w+b");
441 #endif
442           if (!fp)
443             {
444               int save = errno;
445               close (fd);
446               gpg_err_set_errno (save);
447               return NULL;
448             }
449           return fp;
450         }
451       Sleep (1); /* One ms as this is the granularity of GetTickCount.  */
452     }
453   gpg_err_set_errno (ENOENT);
454   return NULL;
455 #undef mystrlen
456 #else /*!HAVE_W32_SYSTEM*/
457   return tmpfile ();
458 #endif /*!HAVE_W32_SYSTEM*/
459 }
460
461
462 /* Make sure that the standard file descriptors are opened. Obviously
463    some folks close them before an exec and the next file we open will
464    get one of them assigned and thus any output (i.e. diagnostics) end
465    up in that file (e.g. the trustdb).  Not actually a gpg problem as
466    this will happen with almost all utilities when called in a wrong
467    way.  However we try to minimize the damage here and raise
468    awareness of the problem.
469
470    Must be called before we open any files! */
471 void
472 gnupg_reopen_std (const char *pgmname)
473 {
474 #if defined(HAVE_STAT) && !defined(HAVE_W32_SYSTEM)
475   struct stat statbuf;
476   int did_stdin = 0;
477   int did_stdout = 0;
478   int did_stderr = 0;
479   FILE *complain;
480
481   if (fstat (STDIN_FILENO, &statbuf) == -1 && errno ==EBADF)
482     {
483       if (open ("/dev/null",O_RDONLY) == STDIN_FILENO)
484         did_stdin = 1;
485       else
486         did_stdin = 2;
487     }
488
489   if (fstat (STDOUT_FILENO, &statbuf) == -1 && errno == EBADF)
490     {
491       if (open ("/dev/null",O_WRONLY) == STDOUT_FILENO)
492         did_stdout = 1;
493       else
494         did_stdout = 2;
495     }
496
497   if (fstat (STDERR_FILENO, &statbuf)==-1 && errno==EBADF)
498     {
499       if (open ("/dev/null", O_WRONLY) == STDERR_FILENO)
500         did_stderr = 1;
501       else
502         did_stderr = 2;
503     }
504
505   /* It's hard to log this sort of thing since the filehandle we would
506      complain to may be closed... */
507   if (!did_stderr)
508     complain = stderr;
509   else if (!did_stdout)
510     complain = stdout;
511   else
512     complain = NULL;
513
514   if (complain)
515     {
516       if (did_stdin == 1)
517         fprintf (complain, "%s: WARNING: standard input reopened\n", pgmname);
518       if (did_stdout == 1)
519         fprintf (complain, "%s: WARNING: standard output reopened\n", pgmname);
520       if (did_stderr == 1)
521         fprintf (complain, "%s: WARNING: standard error reopened\n", pgmname);
522
523       if (did_stdin == 2 || did_stdout == 2 || did_stderr == 2)
524         fprintf(complain,"%s: fatal: unable to reopen standard input,"
525                 " output, or error\n", pgmname);
526     }
527
528   if (did_stdin == 2 || did_stdout == 2 || did_stderr == 2)
529     exit (3);
530 #else /* !(HAVE_STAT && !HAVE_W32_SYSTEM) */
531   (void)pgmname;
532 #endif
533 }
534
535
536 /* Hack required for Windows.  */
537 void
538 gnupg_allow_set_foregound_window (pid_t pid)
539 {
540   if (!pid)
541     log_info ("%s called with invalid pid %lu\n",
542               "gnupg_allow_set_foregound_window", (unsigned long)pid);
543 #if defined(HAVE_W32_SYSTEM) && !defined(HAVE_W32CE_SYSTEM)
544   else if (!AllowSetForegroundWindow ((pid_t)pid == (pid_t)(-1)?ASFW_ANY:pid))
545     log_info ("AllowSetForegroundWindow(%lu) failed: %s\n",
546                (unsigned long)pid, w32_strerror (-1));
547 #endif
548 }
549
550 int
551 gnupg_remove (const char *fname)
552 {
553 #ifdef HAVE_W32CE_SYSTEM
554   int rc;
555   wchar_t *wfname;
556
557   wfname = utf8_to_wchar (fname);
558   if (!wfname)
559     rc = 0;
560   else
561     {
562       rc = DeleteFile (wfname);
563       xfree (wfname);
564     }
565   if (!rc)
566     return -1; /* ERRNO is automagically provided by gpg-error.h.  */
567   return 0;
568 #else
569   return remove (fname);
570 #endif
571 }
572
573
574 #ifndef HAVE_W32_SYSTEM
575 static mode_t
576 modestr_to_mode (const char *modestr)
577 {
578   mode_t mode = 0;
579
580   if (modestr && *modestr)
581     {
582       modestr++;
583       if (*modestr && *modestr++ == 'r')
584         mode |= S_IRUSR;
585       if (*modestr && *modestr++ == 'w')
586         mode |= S_IWUSR;
587       if (*modestr && *modestr++ == 'x')
588         mode |= S_IXUSR;
589       if (*modestr && *modestr++ == 'r')
590         mode |= S_IRGRP;
591       if (*modestr && *modestr++ == 'w')
592         mode |= S_IWGRP;
593       if (*modestr && *modestr++ == 'x')
594         mode |= S_IXGRP;
595       if (*modestr && *modestr++ == 'r')
596         mode |= S_IROTH;
597       if (*modestr && *modestr++ == 'w')
598         mode |= S_IWOTH;
599       if (*modestr && *modestr++ == 'x')
600         mode |= S_IXOTH;
601     }
602
603   return mode;
604 }
605 #endif
606
607
608 /* A wrapper around mkdir which takes a string for the mode argument.
609    This makes it easier to handle the mode argument which is not
610    defined on all systems.  The format of the modestring is
611
612       "-rwxrwxrwx"
613
614    '-' is a don't care or not set.  'r', 'w', 'x' are read allowed,
615    write allowed, execution allowed with the first group for the user,
616    the second for the group and the third for all others.  If the
617    string is shorter than above the missing mode characters are meant
618    to be not set.  */
619 int
620 gnupg_mkdir (const char *name, const char *modestr)
621 {
622 #ifdef HAVE_W32CE_SYSTEM
623   wchar_t *wname;
624   (void)modestr;
625
626   wname = utf8_to_wchar (name);
627   if (!wname)
628     return -1;
629   if (!CreateDirectoryW (wname, NULL))
630     {
631       xfree (wname);
632       return -1;  /* ERRNO is automagically provided by gpg-error.h.  */
633     }
634   xfree (wname);
635   return 0;
636 #elif MKDIR_TAKES_ONE_ARG
637   (void)modestr;
638   /* Note: In the case of W32 we better use CreateDirectory and try to
639      set appropriate permissions.  However using mkdir is easier
640      because this sets ERRNO.  */
641   return mkdir (name);
642 #else
643   return mkdir (name, modestr_to_mode (modestr));
644 #endif
645 }
646
647
648 /* A wrapper around chmod which takes a string for the mode argument.
649    This makes it easier to handle the mode argument which is not
650    defined on all systems.  The format of the modestring is the same
651    as for gnupg_mkdir.  */
652 int
653 gnupg_chmod (const char *name, const char *modestr)
654 {
655 #ifdef HAVE_W32_SYSTEM
656   (void)name;
657   (void)modestr;
658   return 0;
659 #else
660   return chmod (name, modestr_to_mode (modestr));
661 #endif
662 }
663
664
665 /* Our version of mkdtemp.  The API is identical to POSIX.1-2008
666    version.  We do not use a system provided mkdtemp because we have a
667    good RNG instantly available and this way we don't have diverging
668    versions.  */
669 char *
670 gnupg_mkdtemp (char *tmpl)
671 {
672   /* A lower bound on the number of temporary files to attempt to
673      generate.  The maximum total number of temporary file names that
674      can exist for a given template is 62**6 (5*36**3 for Windows).
675      It should never be necessary to try all these combinations.
676      Instead if a reasonable number of names is tried (we define
677      reasonable as 62**3 or 5*36**3) fail to give the system
678      administrator the chance to remove the problems.  */
679 #ifdef HAVE_W32_SYSTEM
680   static const char letters[] =
681     "abcdefghijklmnopqrstuvwxyz0123456789";
682 # define NUMBER_OF_LETTERS 36
683 # define ATTEMPTS_MIN (5 * 36 * 36 * 36)
684 #else
685   static const char letters[] =
686     "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
687 # define NUMBER_OF_LETTERS 62
688 # define ATTEMPTS_MIN (62 * 62 * 62)
689 #endif
690   int len;
691   char *XXXXXX;
692   uint64_t value;
693   unsigned int count;
694   int save_errno = errno;
695   /* The number of times to attempt to generate a temporary file.  To
696      conform to POSIX, this must be no smaller than TMP_MAX.  */
697 #if ATTEMPTS_MIN < TMP_MAX
698   unsigned int attempts = TMP_MAX;
699 #else
700   unsigned int attempts = ATTEMPTS_MIN;
701 #endif
702
703   len = strlen (tmpl);
704   if (len < 6 || strcmp (&tmpl[len - 6], "XXXXXX"))
705     {
706       gpg_err_set_errno (EINVAL);
707       return NULL;
708     }
709
710   /* This is where the Xs start.  */
711   XXXXXX = &tmpl[len - 6];
712
713   /* Get a random start value.  */
714   gcry_create_nonce (&value, sizeof value);
715
716   /* Loop until a directory was created.  */
717   for (count = 0; count < attempts; value += 7777, ++count)
718     {
719       uint64_t v = value;
720
721       /* Fill in the random bits.  */
722       XXXXXX[0] = letters[v % NUMBER_OF_LETTERS];
723       v /= NUMBER_OF_LETTERS;
724       XXXXXX[1] = letters[v % NUMBER_OF_LETTERS];
725       v /= NUMBER_OF_LETTERS;
726       XXXXXX[2] = letters[v % NUMBER_OF_LETTERS];
727       v /= NUMBER_OF_LETTERS;
728       XXXXXX[3] = letters[v % NUMBER_OF_LETTERS];
729       v /= NUMBER_OF_LETTERS;
730       XXXXXX[4] = letters[v % NUMBER_OF_LETTERS];
731       v /= NUMBER_OF_LETTERS;
732       XXXXXX[5] = letters[v % NUMBER_OF_LETTERS];
733
734       if (!gnupg_mkdir (tmpl, "-rwx"))
735         {
736           gpg_err_set_errno (save_errno);
737           return tmpl;
738         }
739       if (errno != EEXIST)
740         return NULL;
741     }
742
743   /* We got out of the loop because we ran out of combinations to try.  */
744   gpg_err_set_errno (EEXIST);
745   return NULL;
746 }
747
748
749 int
750 gnupg_setenv (const char *name, const char *value, int overwrite)
751 {
752 #ifdef HAVE_W32CE_SYSTEM
753   (void)name;
754   (void)value;
755   (void)overwrite;
756   return 0;
757 #else /*!W32CE*/
758 # ifdef HAVE_W32_SYSTEM
759   /*  Windows maintains (at least) two sets of environment variables.
760       One set can be accessed by GetEnvironmentVariable and
761       SetEnvironmentVariable.  This set is inherited by the children.
762       The other set is maintained in the C runtime, and is accessed
763       using getenv and putenv.  We try to keep them in sync by
764       modifying both sets.  */
765   {
766     int exists;
767     char tmpbuf[10];
768     exists = GetEnvironmentVariable (name, tmpbuf, sizeof tmpbuf);
769
770     if ((! exists || overwrite) && !SetEnvironmentVariable (name, value))
771       {
772         gpg_err_set_errno (EINVAL); /* (Might also be ENOMEM.) */
773         return -1;
774       }
775   }
776 # endif /*W32*/
777
778 # ifdef HAVE_SETENV
779   return setenv (name, value, overwrite);
780 # else /*!HAVE_SETENV*/
781   if (! getenv (name) || overwrite)
782     {
783       char *buf;
784
785       (void)overwrite;
786       if (!name || !value)
787         {
788           gpg_err_set_errno (EINVAL);
789           return -1;
790         }
791       buf = strconcat (name, "=", value, NULL);
792       if (!buf)
793         return -1;
794 # if __GNUC__
795 #  warning no setenv - using putenv but leaking memory.
796 # endif
797       return putenv (buf);
798     }
799   return 0;
800 # endif /*!HAVE_SETENV*/
801 #endif /*!W32CE*/
802 }
803
804
805 int
806 gnupg_unsetenv (const char *name)
807 {
808 #ifdef HAVE_W32CE_SYSTEM
809   (void)name;
810   return 0;
811 #else /*!W32CE*/
812 # ifdef HAVE_W32_SYSTEM
813   /*  Windows maintains (at least) two sets of environment variables.
814       One set can be accessed by GetEnvironmentVariable and
815       SetEnvironmentVariable.  This set is inherited by the children.
816       The other set is maintained in the C runtime, and is accessed
817       using getenv and putenv.  We try to keep them in sync by
818       modifying both sets.  */
819   if (!SetEnvironmentVariable (name, NULL))
820     {
821       gpg_err_set_errno (EINVAL); /* (Might also be ENOMEM.) */
822       return -1;
823     }
824 # endif /*W32*/
825
826 # ifdef HAVE_UNSETENV
827   return unsetenv (name);
828 # else /*!HAVE_UNSETENV*/
829   {
830     char *buf;
831
832     if (!name)
833       {
834         gpg_err_set_errno (EINVAL);
835         return -1;
836       }
837     buf = xtrystrdup (name);
838     if (!buf)
839       return -1;
840 #  if __GNUC__
841 #   warning no unsetenv - trying putenv but leaking memory.
842 #  endif
843     return putenv (buf);
844   }
845 # endif /*!HAVE_UNSETENV*/
846 #endif /*!W32CE*/
847 }
848
849
850 /* Return the current working directory as a malloced string.  Return
851    NULL and sets ERRNo on error.  */
852 char *
853 gnupg_getcwd (void)
854 {
855   char *buffer;
856   size_t size = 100;
857
858   for (;;)
859     {
860       buffer = xtrymalloc (size+1);
861       if (!buffer)
862         return NULL;
863 #ifdef HAVE_W32CE_SYSTEM
864       strcpy (buffer, "/");  /* Always "/".  */
865       return buffer;
866 #else
867       if (getcwd (buffer, size) == buffer)
868         return buffer;
869       xfree (buffer);
870       if (errno != ERANGE)
871         return NULL;
872       size *= 2;
873 #endif
874     }
875 }
876
877
878 \f
879 #ifdef HAVE_W32CE_SYSTEM
880 /* There is a isatty function declaration in cegcc but it does not
881    make sense, thus we redefine it.  */
882 int
883 _gnupg_isatty (int fd)
884 {
885   (void)fd;
886   return 0;
887 }
888 #endif
889
890
891 #ifdef HAVE_W32CE_SYSTEM
892 /* Replacement for getenv which takes care of the our use of getenv.
893    The code is not thread safe but we expect it to work in all cases
894    because it is called for the first time early enough.  */
895 char *
896 _gnupg_getenv (const char *name)
897 {
898   static int initialized;
899   static char *assuan_debug;
900
901   if (!initialized)
902     {
903       assuan_debug = read_w32_registry_string (NULL,
904                                                "\\Software\\GNU\\libassuan",
905                                                "debug");
906       initialized = 1;
907     }
908
909   if (!strcmp (name, "ASSUAN_DEBUG"))
910     return assuan_debug;
911   else
912     return NULL;
913 }
914
915 #endif /*HAVE_W32CE_SYSTEM*/
916
917
918 #ifdef HAVE_W32_SYSTEM
919 /* Return the user's security identifier from the current process.  */
920 PSID
921 w32_get_user_sid (void)
922 {
923   int okay = 0;
924   HANDLE proc = NULL;
925   HANDLE token = NULL;
926   TOKEN_USER *user = NULL;
927   PSID sid = NULL;
928   DWORD tokenlen, sidlen;
929
930   proc = OpenProcess (PROCESS_QUERY_INFORMATION, FALSE, GetCurrentProcessId());
931   if (!proc)
932     goto leave;
933
934   if (!OpenProcessToken (proc, TOKEN_QUERY, &token))
935     goto leave;
936
937   if (!GetTokenInformation (token, TokenUser, NULL, 0, &tokenlen)
938       && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
939     goto leave;
940
941   user = xtrymalloc (tokenlen);
942   if (!user)
943     goto leave;
944
945   if (!GetTokenInformation (token, TokenUser, user, tokenlen, &tokenlen))
946     goto leave;
947   if (!IsValidSid (user->User.Sid))
948     goto leave;
949   sidlen = GetLengthSid (user->User.Sid);
950   sid = xtrymalloc (sidlen);
951   if (!sid)
952     goto leave;
953   if (!CopySid (sidlen, sid, user->User.Sid))
954     goto leave;
955   okay = 1;
956
957  leave:
958   xfree (user);
959   if (token)
960     CloseHandle (token);
961   if (proc)
962     CloseHandle (proc);
963
964   if (!okay)
965     {
966       xfree (sid);
967       sid = NULL;
968     }
969   return sid;
970 }
971 #endif /*HAVE_W32_SYSTEM*/
972
973
974 \f
975 /* Support for inotify under Linux.  */
976
977 /* Store a new inotify file handle for SOCKET_NAME at R_FD or return
978  * an error code. */
979 gpg_error_t
980 gnupg_inotify_watch_socket (int *r_fd, const char *socket_name)
981 {
982 #if HAVE_INOTIFY_INIT
983   gpg_error_t err;
984   char *fname;
985   int fd;
986   char *p;
987
988   *r_fd = -1;
989
990   fname = xtrystrdup (socket_name);
991   if (!fname)
992     return my_error_from_syserror ();
993
994   fd = inotify_init ();
995   if (fd == -1)
996     {
997       err = my_error_from_syserror ();
998       xfree (fname);
999       return err;
1000     }
1001
1002   /* We need to watch the directory for the file because there won't
1003    * be an IN_DELETE_SELF for a socket file.  To handle a removal of
1004    * the directory we also watch the directory itself. */
1005   p = strrchr (fname, '/');
1006   if (p)
1007     *p = 0;
1008   if (inotify_add_watch (fd, fname,
1009                          (IN_DELETE|IN_DELETE_SELF|IN_EXCL_UNLINK)) == -1)
1010     {
1011       err = my_error_from_syserror ();
1012       close (fd);
1013       xfree (fname);
1014       return err;
1015     }
1016
1017   xfree (fname);
1018
1019   *r_fd = fd;
1020   return 0;
1021 #else /*!HAVE_INOTIFY_INIT*/
1022
1023   (void)socket_name;
1024   *r_fd = -1;
1025   return my_error (GPG_ERR_NOT_SUPPORTED);
1026
1027 #endif /*!HAVE_INOTIFY_INIT*/
1028 }
1029
1030
1031 /* Read an inotify event and return true if it matches NAME or if it
1032  * sees an IN_DELETE_SELF event for the directory of NAME.  */
1033 int
1034 gnupg_inotify_has_name (int fd, const char *name)
1035 {
1036 #if USE_NPTH && HAVE_INOTIFY_INIT
1037   union {
1038     struct inotify_event ev;
1039     char _buf[sizeof (struct inotify_event) + 255 + 1];
1040   } buf;
1041   struct inotify_event *evp;
1042   int n;
1043
1044   n = npth_read (fd, &buf, sizeof buf);
1045   /* log_debug ("notify read: n=%d\n", n); */
1046   evp = &buf.ev;
1047   while (n >= sizeof (struct inotify_event))
1048     {
1049       /* log_debug ("             mask=%x len=%u name=(%s)\n", */
1050       /*        evp->mask, (unsigned int)evp->len, evp->len? evp->name:""); */
1051       if ((evp->mask & IN_UNMOUNT))
1052         {
1053           /* log_debug ("             found (dir unmounted)\n"); */
1054           return 3; /* Directory was unmounted.  */
1055         }
1056       if ((evp->mask & IN_DELETE_SELF))
1057         {
1058           /* log_debug ("             found (dir removed)\n"); */
1059           return 2; /* Directory was removed.  */
1060         }
1061       if ((evp->mask & IN_DELETE))
1062         {
1063           if (evp->len >= strlen (name) && !strcmp (evp->name, name))
1064             {
1065               /* log_debug ("             found (file removed)\n"); */
1066               return 1; /* File was removed.  */
1067             }
1068         }
1069       n -= sizeof (*evp) + evp->len;
1070       evp = (struct inotify_event *)((char*)evp + sizeof (*evp) + evp->len);
1071     }
1072
1073 #else /*!(USE_NPTH && HAVE_INOTIFY_INIT)*/
1074
1075   (void)fd;
1076   (void)name;
1077
1078 #endif  /*!(USE_NPTH && HAVE_INOTIFY_INIT)*/
1079
1080   return 0; /* Not found.  */
1081 }