Pass DBUS_SESSION_BUS_ADDRESS for gnome3
[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_NPTH
67 # include <npth.h>
68 #endif
69 #include <fcntl.h>
70
71 #include <assuan.h>
72
73 #include "util.h"
74 #include "i18n.h"
75
76 #include "sysutils.h"
77
78 #define tohex(n) ((n) < 10 ? ((n) + '0') : (((n) - 10) + 'A'))
79
80
81 #if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2
82 #warning using trap_unaligned
83 static int
84 setsysinfo(unsigned long op, void *buffer, unsigned long size,
85                      int *start, void *arg, unsigned long flag)
86 {
87     return syscall(__NR_osf_setsysinfo, op, buffer, size, start, arg, flag);
88 }
89
90 void
91 trap_unaligned(void)
92 {
93     unsigned int buf[2];
94
95     buf[0] = SSIN_UACPROC;
96     buf[1] = UAC_SIGBUS | UAC_NOPRINT;
97     setsysinfo(SSI_NVPAIRS, buf, 1, 0, 0, 0);
98 }
99 #else
100 void
101 trap_unaligned(void)
102 {  /* dummy */
103 }
104 #endif
105
106
107 int
108 disable_core_dumps (void)
109 {
110 #ifdef HAVE_DOSISH_SYSTEM
111     return 0;
112 #else
113 # ifdef HAVE_SETRLIMIT
114     struct rlimit limit;
115
116     /* We only set the current limit unless we were not able to
117        retrieve the old value. */
118     if (getrlimit (RLIMIT_CORE, &limit))
119       limit.rlim_max = 0;
120     limit.rlim_cur = 0;
121     if( !setrlimit (RLIMIT_CORE, &limit) )
122         return 0;
123     if( errno != EINVAL && errno != ENOSYS )
124         log_fatal (_("can't disable core dumps: %s\n"), strerror(errno) );
125 #endif
126     return 1;
127 #endif
128 }
129
130 int
131 enable_core_dumps (void)
132 {
133 #ifdef HAVE_DOSISH_SYSTEM
134     return 0;
135 #else
136 # ifdef HAVE_SETRLIMIT
137     struct rlimit limit;
138
139     if (getrlimit (RLIMIT_CORE, &limit))
140       return 1;
141     limit.rlim_cur = limit.rlim_max;
142     setrlimit (RLIMIT_CORE, &limit);
143     return 1; /* We always return true because this function is
144                  merely a debugging aid. */
145 # endif
146     return 1;
147 #endif
148 }
149
150
151
152 /* Return a string which is used as a kind of process ID.  */
153 const byte *
154 get_session_marker (size_t *rlen)
155 {
156   static byte marker[SIZEOF_UNSIGNED_LONG*2];
157   static int initialized;
158
159   if (!initialized)
160     {
161       gcry_create_nonce (marker, sizeof marker);
162       initialized = 1;
163     }
164   *rlen = sizeof (marker);
165   return marker;
166 }
167
168 /* Return a random number in an unsigned int. */
169 unsigned int
170 get_uint_nonce (void)
171 {
172   unsigned int value;
173
174   gcry_create_nonce (&value, sizeof value);
175   return value;
176 }
177
178
179
180 #if 0 /* not yet needed - Note that this will require inclusion of
181          cmacros.am in Makefile.am */
182 int
183 check_permissions(const char *path,int extension,int checkonly)
184 {
185 #if defined(HAVE_STAT) && !defined(HAVE_DOSISH_SYSTEM)
186   char *tmppath;
187   struct stat statbuf;
188   int ret=1;
189   int isdir=0;
190
191   if(opt.no_perm_warn)
192     return 0;
193
194   if(extension && path[0]!=DIRSEP_C)
195     {
196       if(strchr(path,DIRSEP_C))
197         tmppath=make_filename(path,NULL);
198       else
199         tmppath=make_filename(GNUPG_LIBDIR,path,NULL);
200     }
201   else
202     tmppath=m_strdup(path);
203
204   /* It's okay if the file doesn't exist */
205   if(stat(tmppath,&statbuf)!=0)
206     {
207       ret=0;
208       goto end;
209     }
210
211   isdir=S_ISDIR(statbuf.st_mode);
212
213   /* Per-user files must be owned by the user.  Extensions must be
214      owned by the user or root. */
215   if((!extension && statbuf.st_uid != getuid()) ||
216      (extension && statbuf.st_uid!=0 && statbuf.st_uid!=getuid()))
217     {
218       if(!checkonly)
219         log_info(_("Warning: unsafe ownership on %s \"%s\"\n"),
220                  isdir?"directory":extension?"extension":"file",path);
221       goto end;
222     }
223
224   /* This works for both directories and files - basically, we don't
225      care what the owner permissions are, so long as the group and
226      other permissions are 0 for per-user files, and non-writable for
227      extensions. */
228   if((extension && (statbuf.st_mode & (S_IWGRP|S_IWOTH)) !=0) ||
229      (!extension && (statbuf.st_mode & (S_IRWXG|S_IRWXO)) != 0))
230     {
231       char *dir;
232
233       /* However, if the directory the directory/file is in is owned
234          by the user and is 700, then this is not a problem.
235          Theoretically, we could walk this test up to the root
236          directory /, but for the sake of sanity, I'm stopping at one
237          level down. */
238
239       dir= make_dirname (tmppath);
240       if(stat(dir,&statbuf)==0 && statbuf.st_uid==getuid() &&
241          S_ISDIR(statbuf.st_mode) && (statbuf.st_mode & (S_IRWXG|S_IRWXO))==0)
242         {
243           xfree (dir);
244           ret=0;
245           goto end;
246         }
247
248       m_free(dir);
249
250       if(!checkonly)
251         log_info(_("Warning: unsafe permissions on %s \"%s\"\n"),
252                  isdir?"directory":extension?"extension":"file",path);
253       goto end;
254     }
255
256   ret=0;
257
258  end:
259   m_free(tmppath);
260
261   return ret;
262
263 #endif /* HAVE_STAT && !HAVE_DOSISH_SYSTEM */
264
265   return 0;
266 }
267 #endif
268
269
270 /* Wrapper around the usual sleep fucntion.  This one won't wake up
271    before the sleep time has really elapsed.  When build with Pth it
272    merely calls pth_sleep and thus suspends only the current
273    thread. */
274 void
275 gnupg_sleep (unsigned int seconds)
276 {
277 #ifdef USE_NPTH
278   npth_sleep (seconds);
279 #else
280   /* Fixme:  make sure that a sleep won't wake up to early.  */
281 # ifdef HAVE_W32_SYSTEM
282   Sleep (seconds*1000);
283 # else
284   sleep (seconds);
285 # endif
286 #endif
287 }
288
289
290 /* This function is a NOP for POSIX systems but required under Windows
291    as the file handles as returned by OS calls (like CreateFile) are
292    different from the libc file descriptors (like open). This function
293    translates system file handles to libc file handles.  FOR_WRITE
294    gives the direction of the handle.  */
295 int
296 translate_sys2libc_fd (gnupg_fd_t fd, int for_write)
297 {
298 #if defined(HAVE_W32CE_SYSTEM)
299   (void)for_write;
300   return (int) fd;
301 #elif defined(HAVE_W32_SYSTEM)
302   int x;
303
304   if (fd == GNUPG_INVALID_FD)
305     return -1;
306
307   /* Note that _open_osfhandle is currently defined to take and return
308      a long.  */
309   x = _open_osfhandle ((long)fd, for_write ? 1 : 0);
310   if (x == -1)
311     log_error ("failed to translate osfhandle %p\n", (void *) fd);
312   return x;
313 #else /*!HAVE_W32_SYSTEM */
314   (void)for_write;
315   return fd;
316 #endif
317 }
318
319 /* This is the same as translate_sys2libc_fd but takes an integer
320    which is assumed to be such an system handle.  On WindowsCE the
321    passed FD is a rendezvous ID and the function finishes the pipe
322    creation. */
323 int
324 translate_sys2libc_fd_int (int fd, int for_write)
325 {
326 #if HAVE_W32CE_SYSTEM
327   fd = (int) _assuan_w32ce_finish_pipe (fd, for_write);
328   return translate_sys2libc_fd ((void*)fd, for_write);
329 #elif HAVE_W32_SYSTEM
330   if (fd <= 2)
331     return fd;  /* Do not do this for error, stdin, stdout, stderr. */
332
333   return translate_sys2libc_fd ((void*)fd, for_write);
334 #else
335   (void)for_write;
336   return fd;
337 #endif
338 }
339
340
341
342 /* Replacement for tmpfile().  This is required because the tmpfile
343    function of Windows' runtime library is broken, insecure, ignores
344    TMPDIR and so on.  In addition we create a file with an inheritable
345    handle.  */
346 FILE *
347 gnupg_tmpfile (void)
348 {
349 #ifdef HAVE_W32_SYSTEM
350   int attempts, n;
351 #ifdef HAVE_W32CE_SYSTEM
352   wchar_t buffer[MAX_PATH+7+12+1];
353 # define mystrlen(a) wcslen (a)
354   wchar_t *name, *p;
355 #else
356   char buffer[MAX_PATH+7+12+1];
357 # define mystrlen(a) strlen (a)
358   char *name, *p;
359 #endif
360   HANDLE file;
361   int pid = GetCurrentProcessId ();
362   unsigned int value;
363   int i;
364   SECURITY_ATTRIBUTES sec_attr;
365
366   memset (&sec_attr, 0, sizeof sec_attr );
367   sec_attr.nLength = sizeof sec_attr;
368   sec_attr.bInheritHandle = TRUE;
369
370   n = GetTempPath (MAX_PATH+1, buffer);
371   if (!n || n > MAX_PATH || mystrlen (buffer) > MAX_PATH)
372     {
373       gpg_err_set_errno (ENOENT);
374       return NULL;
375     }
376   p = buffer + mystrlen (buffer);
377 #ifdef HAVE_W32CE_SYSTEM
378   wcscpy (p, L"_gnupg");
379   p += 7;
380 #else
381   p = stpcpy (p, "_gnupg");
382 #endif
383   /* We try to create the directory but don't care about an error as
384      it may already exist and the CreateFile would throw an error
385      anyway.  */
386   CreateDirectory (buffer, NULL);
387   *p++ = '\\';
388   name = p;
389   for (attempts=0; attempts < 10; attempts++)
390     {
391       p = name;
392       value = (GetTickCount () ^ ((pid<<16) & 0xffff0000));
393       for (i=0; i < 8; i++)
394         {
395           *p++ = tohex (((value >> 28) & 0x0f));
396           value <<= 4;
397         }
398 #ifdef HAVE_W32CE_SYSTEM
399       wcscpy (p, L".tmp");
400 #else
401       strcpy (p, ".tmp");
402 #endif
403       file = CreateFile (buffer,
404                          GENERIC_READ | GENERIC_WRITE,
405                          0,
406                          &sec_attr,
407                          CREATE_NEW,
408                          FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE,
409                          NULL);
410       if (file != INVALID_HANDLE_VALUE)
411         {
412           FILE *fp;
413 #ifdef HAVE_W32CE_SYSTEM
414           int fd = (int)file;
415           fp = _wfdopen (fd, L"w+b");
416 #else
417           int fd = _open_osfhandle ((long)file, 0);
418           if (fd == -1)
419             {
420               CloseHandle (file);
421               return NULL;
422             }
423           fp = fdopen (fd, "w+b");
424 #endif
425           if (!fp)
426             {
427               int save = errno;
428               close (fd);
429               gpg_err_set_errno (save);
430               return NULL;
431             }
432           return fp;
433         }
434       Sleep (1); /* One ms as this is the granularity of GetTickCount.  */
435     }
436   gpg_err_set_errno (ENOENT);
437   return NULL;
438 #undef mystrlen
439 #else /*!HAVE_W32_SYSTEM*/
440   return tmpfile ();
441 #endif /*!HAVE_W32_SYSTEM*/
442 }
443
444
445 /* Make sure that the standard file descriptors are opened. Obviously
446    some folks close them before an exec and the next file we open will
447    get one of them assigned and thus any output (i.e. diagnostics) end
448    up in that file (e.g. the trustdb).  Not actually a gpg problem as
449    this will hapen with almost all utilities when called in a wrong
450    way.  However we try to minimize the damage here and raise
451    awareness of the problem.
452
453    Must be called before we open any files! */
454 void
455 gnupg_reopen_std (const char *pgmname)
456 {
457 #if defined(HAVE_STAT) && !defined(HAVE_W32_SYSTEM)
458   struct stat statbuf;
459   int did_stdin = 0;
460   int did_stdout = 0;
461   int did_stderr = 0;
462   FILE *complain;
463
464   if (fstat (STDIN_FILENO, &statbuf) == -1 && errno ==EBADF)
465     {
466       if (open ("/dev/null",O_RDONLY) == STDIN_FILENO)
467         did_stdin = 1;
468       else
469         did_stdin = 2;
470     }
471
472   if (fstat (STDOUT_FILENO, &statbuf) == -1 && errno == EBADF)
473     {
474       if (open ("/dev/null",O_WRONLY) == STDOUT_FILENO)
475         did_stdout = 1;
476       else
477         did_stdout = 2;
478     }
479
480   if (fstat (STDERR_FILENO, &statbuf)==-1 && errno==EBADF)
481     {
482       if (open ("/dev/null", O_WRONLY) == STDERR_FILENO)
483         did_stderr = 1;
484       else
485         did_stderr = 2;
486     }
487
488   /* It's hard to log this sort of thing since the filehandle we would
489      complain to may be closed... */
490   if (!did_stderr)
491     complain = stderr;
492   else if (!did_stdout)
493     complain = stdout;
494   else
495     complain = NULL;
496
497   if (complain)
498     {
499       if (did_stdin == 1)
500         fprintf (complain, "%s: WARNING: standard input reopened\n", pgmname);
501       if (did_stdout == 1)
502         fprintf (complain, "%s: WARNING: standard output reopened\n", pgmname);
503       if (did_stderr == 1)
504         fprintf (complain, "%s: WARNING: standard error reopened\n", pgmname);
505
506       if (did_stdin == 2 || did_stdout == 2 || did_stderr == 2)
507         fprintf(complain,"%s: fatal: unable to reopen standard input,"
508                 " output, or error\n", pgmname);
509     }
510
511   if (did_stdin == 2 || did_stdout == 2 || did_stderr == 2)
512     exit (3);
513 #else /* !(HAVE_STAT && !HAVE_W32_SYSTEM) */
514   (void)pgmname;
515 #endif
516 }
517
518
519 /* Hack required for Windows.  */
520 void
521 gnupg_allow_set_foregound_window (pid_t pid)
522 {
523   if (!pid)
524     log_info ("%s called with invalid pid %lu\n",
525               "gnupg_allow_set_foregound_window", (unsigned long)pid);
526 #if defined(HAVE_W32_SYSTEM) && !defined(HAVE_W32CE_SYSTEM)
527   else if (!AllowSetForegroundWindow ((pid_t)pid == (pid_t)(-1)?ASFW_ANY:pid))
528     log_info ("AllowSetForegroundWindow(%lu) failed: %s\n",
529                (unsigned long)pid, w32_strerror (-1));
530 #endif
531 }
532
533 int
534 gnupg_remove (const char *fname)
535 {
536 #ifdef HAVE_W32CE_SYSTEM
537   int rc;
538   wchar_t *wfname;
539
540   wfname = utf8_to_wchar (fname);
541   if (!wfname)
542     rc = 0;
543   else
544     {
545       rc = DeleteFile (wfname);
546       xfree (wfname);
547     }
548   if (!rc)
549     return -1; /* ERRNO is automagically provided by gpg-error.h.  */
550   return 0;
551 #else
552   return remove (fname);
553 #endif
554 }
555
556
557 /* A wrapper around mkdir which takes a string for the mode argument.
558    This makes it easier to handle the mode argument which is not
559    defined on all systems.  The format of the modestring is
560
561       "-rwxrwxrwx"
562
563    '-' is a don't care or not set.  'r', 'w', 'x' are read allowed,
564    write allowed, execution allowed with the first group for the user,
565    the second for the group and the third for all others.  If the
566    string is shorter than above the missing mode characters are meant
567    to be not set.  */
568 int
569 gnupg_mkdir (const char *name, const char *modestr)
570 {
571 #ifdef HAVE_W32CE_SYSTEM
572   wchar_t *wname;
573   (void)modestr;
574
575   wname = utf8_to_wchar (name);
576   if (!wname)
577     return -1;
578   if (!CreateDirectoryW (wname, NULL))
579     {
580       xfree (wname);
581       return -1;  /* ERRNO is automagically provided by gpg-error.h.  */
582     }
583   xfree (wname);
584   return 0;
585 #elif MKDIR_TAKES_ONE_ARG
586   (void)modestr;
587   /* Note: In the case of W32 we better use CreateDirectory and try to
588      set appropriate permissions.  However using mkdir is easier
589      because this sets ERRNO.  */
590   return mkdir (name);
591 #else
592   mode_t mode = 0;
593
594   if (modestr && *modestr)
595     {
596       modestr++;
597       if (*modestr && *modestr++ == 'r')
598         mode |= S_IRUSR;
599       if (*modestr && *modestr++ == 'w')
600         mode |= S_IWUSR;
601       if (*modestr && *modestr++ == 'x')
602         mode |= S_IXUSR;
603       if (*modestr && *modestr++ == 'r')
604         mode |= S_IRGRP;
605       if (*modestr && *modestr++ == 'w')
606         mode |= S_IWGRP;
607       if (*modestr && *modestr++ == 'x')
608         mode |= S_IXGRP;
609       if (*modestr && *modestr++ == 'r')
610         mode |= S_IROTH;
611       if (*modestr && *modestr++ == 'w')
612         mode |= S_IWOTH;
613       if (*modestr && *modestr++ == 'x')
614         mode |= S_IXOTH;
615     }
616   return mkdir (name, mode);
617 #endif
618 }
619
620
621 /* Our version of mkdtemp.  The API is identical to POSIX.1-2008
622    version.  We do not use a system provided mkdtemp because we have a
623    good RNG instantly available and this way we don't have diverging
624    versions.  */
625 char *
626 gnupg_mkdtemp (char *tmpl)
627 {
628   /* A lower bound on the number of temporary files to attempt to
629      generate.  The maximum total number of temporary file names that
630      can exist for a given template is 62**6 (5*36**3 for Windows).
631      It should never be necessary to try all these combinations.
632      Instead if a reasonable number of names is tried (we define
633      reasonable as 62**3 or 5*36**3) fail to give the system
634      administrator the chance to remove the problems.  */
635 #ifdef HAVE_W32_SYSTEM
636   static const char letters[] =
637     "abcdefghijklmnopqrstuvwxyz0123456789";
638 # define NUMBER_OF_LETTERS 36
639 # define ATTEMPTS_MIN (5 * 36 * 36 * 36)
640 #else
641   static const char letters[] =
642     "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
643 # define NUMBER_OF_LETTERS 62
644 # define ATTEMPTS_MIN (62 * 62 * 62)
645 #endif
646   int len;
647   char *XXXXXX;
648   uint64_t value;
649   unsigned int count;
650   int save_errno = errno;
651   /* The number of times to attempt to generate a temporary file.  To
652      conform to POSIX, this must be no smaller than TMP_MAX.  */
653 #if ATTEMPTS_MIN < TMP_MAX
654   unsigned int attempts = TMP_MAX;
655 #else
656   unsigned int attempts = ATTEMPTS_MIN;
657 #endif
658
659   len = strlen (tmpl);
660   if (len < 6 || strcmp (&tmpl[len - 6], "XXXXXX"))
661     {
662       gpg_err_set_errno (EINVAL);
663       return NULL;
664     }
665
666   /* This is where the Xs start.  */
667   XXXXXX = &tmpl[len - 6];
668
669   /* Get a random start value.  */
670   gcry_create_nonce (&value, sizeof value);
671
672   /* Loop until a directory was created.  */
673   for (count = 0; count < attempts; value += 7777, ++count)
674     {
675       uint64_t v = value;
676
677       /* Fill in the random bits.  */
678       XXXXXX[0] = letters[v % NUMBER_OF_LETTERS];
679       v /= NUMBER_OF_LETTERS;
680       XXXXXX[1] = letters[v % NUMBER_OF_LETTERS];
681       v /= NUMBER_OF_LETTERS;
682       XXXXXX[2] = letters[v % NUMBER_OF_LETTERS];
683       v /= NUMBER_OF_LETTERS;
684       XXXXXX[3] = letters[v % NUMBER_OF_LETTERS];
685       v /= NUMBER_OF_LETTERS;
686       XXXXXX[4] = letters[v % NUMBER_OF_LETTERS];
687       v /= NUMBER_OF_LETTERS;
688       XXXXXX[5] = letters[v % NUMBER_OF_LETTERS];
689
690       if (!gnupg_mkdir (tmpl, "-rwx"))
691         {
692           gpg_err_set_errno (save_errno);
693           return tmpl;
694         }
695       if (errno != EEXIST)
696         return NULL;
697     }
698
699   /* We got out of the loop because we ran out of combinations to try.  */
700   gpg_err_set_errno (EEXIST);
701   return NULL;
702 }
703
704
705 int
706 gnupg_setenv (const char *name, const char *value, int overwrite)
707 {
708 #ifdef HAVE_W32CE_SYSTEM
709   (void)name;
710   (void)value;
711   (void)overwrite;
712   return 0;
713 #elif defined(HAVE_W32_SYSTEM)
714   if (!overwrite)
715     {
716       char tmpbuf[10];
717       if (GetEnvironmentVariable (name, tmpbuf, sizeof tmpbuf))
718         return 0; /* Exists but overwrite was not requested.  */
719     }
720   if (!SetEnvironmentVariable (name, value))
721     {
722       gpg_err_set_errno (EINVAL); /* (Might also be ENOMEM.) */
723       return -1;
724     }
725   return 0;
726 #elif defined(HAVE_SETENV)
727   return setenv (name, value, overwrite);
728 #else
729   char *buf;
730
731   (void)overwrite;
732   if (!name || !value)
733     {
734       gpg_err_set_errno (EINVAL);
735       return -1;
736     }
737   buf = xtrymalloc (strlen (name) + 1 + strlen (value) + 1);
738   if (!buf)
739     return -1;
740   strcpy (stpcpy (stpcpy (buf, name), "="), value);
741 #if __GNUC__
742 # warning no setenv - using putenv but leaking memory.
743 #endif
744   return putenv (buf);
745 #endif
746 }
747
748
749 int
750 gnupg_unsetenv (const char *name)
751 {
752 #ifdef HAVE_W32CE_SYSTEM
753   (void)name;
754   return 0;
755 #elif defined(HAVE_W32_SYSTEM)
756   if (!SetEnvironmentVariable (name, NULL))
757     {
758       gpg_err_set_errno (EINVAL); /* (Might also be ENOMEM.) */
759       return -1;
760     }
761   return 0;
762 #elif defined(HAVE_UNSETENV)
763   return unsetenv (name);
764 #else
765   char *buf;
766
767   if (!name)
768     {
769       gpg_err_set_errno (EINVAL);
770       return -1;
771     }
772   buf = xtrystrdup (name);
773   if (!buf)
774     return -1;
775 #if __GNUC__
776 # warning no unsetenv - trying putenv but leaking memory.
777 #endif
778   return putenv (buf);
779 #endif
780 }
781
782
783 /* Return the current working directory as a malloced string.  Return
784    NULL and sets ERRNo on error.  */
785 char *
786 gnupg_getcwd (void)
787 {
788   char *buffer;
789   size_t size = 100;
790
791   for (;;)
792     {
793       buffer = xtrymalloc (size+1);
794       if (!buffer)
795         return NULL;
796 #ifdef HAVE_W32CE_SYSTEM
797       strcpy (buffer, "/");  /* Always "/".  */
798       return buffer;
799 #else
800       if (getcwd (buffer, size) == buffer)
801         return buffer;
802       xfree (buffer);
803       if (errno != ERANGE)
804         return NULL;
805       size *= 2;
806 #endif
807     }
808 }
809
810
811 \f
812 #ifdef HAVE_W32CE_SYSTEM
813 /* There is a isatty function declaration in cegcc but it does not
814    make sense, thus we redefine it.  */
815 int
816 _gnupg_isatty (int fd)
817 {
818   (void)fd;
819   return 0;
820 }
821 #endif
822
823
824 #ifdef HAVE_W32CE_SYSTEM
825 /* Replacement for getenv which takes care of the our use of getenv.
826    The code is not thread safe but we expect it to work in all cases
827    because it is called for the first time early enough.  */
828 char *
829 _gnupg_getenv (const char *name)
830 {
831   static int initialized;
832   static char *assuan_debug;
833
834   if (!initialized)
835     {
836       assuan_debug = read_w32_registry_string (NULL,
837                                                "\\Software\\GNU\\libassuan",
838                                                "debug");
839       initialized = 1;
840     }
841
842   if (!strcmp (name, "ASSUAN_DEBUG"))
843     return assuan_debug;
844   else
845     return NULL;
846 }
847
848 #endif /*HAVE_W32CE_SYSTEM*/
849
850
851 #ifdef HAVE_W32_SYSTEM
852 /* Return the user's security identifier from the current process.  */
853 PSID
854 w32_get_user_sid (void)
855 {
856   int okay = 0;
857   HANDLE proc = NULL;
858   HANDLE token = NULL;
859   TOKEN_USER *user = NULL;
860   PSID sid = NULL;
861   DWORD tokenlen, sidlen;
862
863   proc = OpenProcess (PROCESS_QUERY_INFORMATION, FALSE, GetCurrentProcessId());
864   if (!proc)
865     goto leave;
866
867   if (!OpenProcessToken (proc, TOKEN_QUERY, &token))
868     goto leave;
869
870   if (!GetTokenInformation (token, TokenUser, NULL, 0, &tokenlen)
871       && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
872     goto leave;
873
874   user = xtrymalloc (tokenlen);
875   if (!user)
876     goto leave;
877
878   if (!GetTokenInformation (token, TokenUser, user, tokenlen, &tokenlen))
879     goto leave;
880   if (!IsValidSid (user->User.Sid))
881     goto leave;
882   sidlen = GetLengthSid (user->User.Sid);
883   sid = xtrymalloc (sidlen);
884   if (!sid)
885     goto leave;
886   if (!CopySid (sidlen, sid, user->User.Sid))
887     goto leave;
888   okay = 1;
889
890  leave:
891   xfree (user);
892   if (token)
893     CloseHandle (token);
894   if (proc)
895     CloseHandle (proc);
896
897   if (!okay)
898     {
899       xfree (sid);
900       sid = NULL;
901     }
902   return sid;
903 }
904 #endif /*HAVE_W32_SYSTEM*/