]> err.no Git - sope/blob - user_home.c
623210d5e6f1d3701626bfc479ec3ce9ab844306
[sope] / user_home.c
1 /*
2    user_home.c
3    Copyright (C) 2002 Free Software Foundation, Inc.
4
5    Author: Richard Frith-Macdonald <richard@brainstorm.co.uk>
6    Date: February 2002
7
8    This file is part of the GNUstep Makefile Package.
9
10    This library is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License
12    as published by the Free Software Foundation; either version 2
13    of the License, or (at your option) any later version.
14
15    You should have received a copy of the GNU General Public
16    License along with this library; see the file COPYING.LIB.
17    If not, write to the Free Software Foundation,
18    59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
19
20 #include "config.h"
21
22 #ifdef __MINGW32__
23 #ifndef __MINGW__
24 #define __MINGW__
25 #endif
26 #ifndef __WIN32__
27 #define __WIN32__
28 #endif
29 #endif
30
31 #include <stdio.h>
32 #include <ctype.h>
33
34 #if defined(__MINGW__)
35 # include <windows.h>
36 #endif
37
38 #if HAVE_SYS_TYPES_H
39 # include <sys/types.h>
40 #endif
41
42 #if HAVE_STDLIB_H
43 # include <stdlib.h>
44 #endif
45
46 #if HAVE_UNISTD_H
47 # include <unistd.h>
48 #endif
49
50 #if HAVE_STRING_H
51 # include <string.h>
52 #endif
53
54 #if HAVE_PWD_H
55 # include <pwd.h>
56 #endif
57
58 #define lowlevelstringify(X) #X
59 #define stringify(X) lowlevelstringify(X)
60
61 #define SEP "/"
62
63 /*
64  * This tool is intended to produce a definitive form of the
65  * user specific root directories for a GNUstep user.  It must
66  * remain consistent with the code in the GNUstep base library
67  * which provides path information for all GNUstep applications.
68  *
69  *
70  * How to run this tool ...
71  *
72  * 1. With no arguments ... the tool should print the home directory of
73  * the current user to stdout.
74  *
75  * 2. With a 'user' argument ... the tool should print the
76  * GNUSTEP_USER_ROOT directory to stdout.
77  *
78  * 3. With a 'defaults' argument ... the tool should print the
79  * GNUSTEP_DEFAULTS_ROOT directory to stdout.
80  *
81  * Any other arguments will be ignored.
82  * On success the tool will terminate with an exit status of zero
83  * On failure, the tool will terminate with an exit status of one
84  * and will print an error message to stderr.
85  */
86
87 /* NOTE FOR DEVELOPERS.
88  * If you change the behavior of this method you must also change
89  * NSUser.m in the base library package to match.
90  */
91 int main (int argc, char** argv)
92 {
93   char          buf0[1024];
94   char          path[2048];
95   char          home[2048];
96   char          *loginName = 0;
97   enum { NONE, DEFS, USER } type = NONE;
98 #if defined(__MINGW__)
99   char          buf1[1024];
100   int           len0;
101   int           len1;
102 #else
103   struct passwd *pw;
104 #endif
105
106   if (argc > 1)
107     {
108       if (strcmp(argv[1], "defaults") == 0)
109         {
110           type = DEFS;
111         }
112       else if (strcmp(argv[1], "user") == 0)
113         {
114           type = USER;
115         }
116     }
117
118   if (loginName == 0)
119     {
120 #if defined(__WIN32__)
121       /* The GetUserName function returns the current user name */
122       DWORD     n = 1024;
123
124       len0 = GetEnvironmentVariable("LOGNAME", buf0, 1024);
125       if (len0 > 0 && len0 < 1024)
126         {
127           loginName = buf0;
128           loginName[len0] = '\0';
129         }
130       else if (GetUserName(buf0, &n))
131         {
132           loginName = buf0;
133         }
134 #else
135 #if HAVE_GETPWUID
136 #if HAVE_GETEUID
137       int uid = geteuid();
138 #else
139       int uid = getuid();
140 #endif /* HAVE_GETEUID */
141       struct passwd *pwent = getpwuid (uid);
142       loginName = pwent->pw_name;
143 #endif /* HAVE_GETPWUID */
144 #endif
145       if (loginName == 0)
146         {
147           fprintf(stderr, "Unable to determine current user name.\n");
148           return 1;
149         }
150     }
151
152 #if !defined(__MINGW__)
153   pw = getpwnam (loginName);
154   if (pw == 0)
155     {
156       fprintf(stderr, "Unable to locate home directory for '%s'\n", loginName);
157       return 1;
158     }
159   strncpy(home, pw->pw_dir, sizeof(home));
160 #else
161   home[0] = '\0';
162   /*
163    * The environment variable HOMEPATH holds the home directory
164    * for the user on Windows NT; Win95 has no concept of home.
165    * For OPENSTEP compatibility (and because USERPROFILE is usually
166    * unusable because it contains spaces), we use HOMEPATH in
167    * preference to USERPROFILE.
168    */
169   len0 = GetEnvironmentVariable("HOMEPATH", buf0, 1024);
170   if (len0 > 0 && len0 < 1024)
171     {
172       buf0[len0] = '\0';
173       /*
174        * Only use HOMEDRIVE is HOMEPATH does not already contain drive.
175        */
176       if (len0 < 2 || buf0[1] != ':')
177         {
178           len1 = GetEnvironmentVariable("HOMEDRIVE", buf1, 128);
179           if (len1 > 0 && len1 < 128)
180             {
181               buf1[len1] = '\0';
182               sprintf(home, "%s%s", buf1, buf0);
183             }
184           else
185             {
186               sprintf(home, "C:%s", buf0);
187             }
188         }
189     }
190   else
191     {
192       /* The environment variable USERPROFILE may hold the home directory
193          for the user on modern versions of windoze. */
194       len0 = GetEnvironmentVariable("USERPROFILE", buf0, 1024);
195       if (len0 > 0 && len0 < 1024)
196         {
197           buf0[len0] = '\0';
198           strcpy(home, buf0);
199         }
200     }
201   if (home[0] != '\0')
202     {
203       int       i;
204
205       for (i = 0; i < strlen(home); i++)
206         {
207           if (isspace((unsigned int)home[i]))
208             {
209               /*
210                * GNU make doesn't handle spaces in paths.
211                * Broken, wrong and totally unfixable.
212                */
213               fprintf(stderr, "Make cannot handle spaces in paths so the " \
214                           "home directory '%s' may cause problems!\n", home);
215               break;
216             }
217         }
218     }
219 #endif
220
221   if (type == NONE)
222     {
223       strcpy(path, home);
224     }
225   else
226     {
227       FILE      *fptr;
228       char      *user = "";
229       char      *defs = "";
230       int       forceD = 0;
231       int       forceU = 0;
232
233 #if defined (__MINGW32__)
234       len0 = GetEnvironmentVariable("GNUSTEP_SYSTEM_ROOT", buf0, sizeof(buf0));
235       if (len0 > 0)
236         {
237           strcpy(path, buf0);
238         }
239 #else 
240       {
241         const char *gnustep_system_root = (const char*)getenv("GNUSTEP_SYSTEM_ROOT");
242
243         if (gnustep_system_root != 0)
244           {
245             strcpy(path, gnustep_system_root);
246           }
247         else
248           {
249             /* On my machine the strcpy was segfaulting when
250              * gnustep_system_root == 0.  */
251             path[0] = '\0';
252           }
253       }
254 #endif
255       strcat(path, SEP);
256       strcat(path, ".GNUsteprc");
257       fptr = fopen(path, "r");
258       if (fptr != 0)
259         {
260           while (fgets(buf0, sizeof(buf0), fptr) != 0)
261             {
262               char      *pos = strchr(buf0, '=');
263               char      *key = buf0;
264               char      *val;
265
266               if (pos != 0)
267                 {
268                   val = pos;
269                   *val++ = '\0';
270                   while (isspace((int)*key))
271                     key++;
272                   while (strlen(key) > 0 && isspace((int)key[strlen(key)-1]))
273                     key[strlen(key)-1] = '\0';
274                   while (isspace(*val))
275                     val++;
276                   while (strlen(val) > 0 && isspace((int)val[strlen(val)-1]))
277                     val[strlen(val)-1] = '\0';
278                 }
279               else
280                 {
281                   while (isspace((int)*key))
282                     key++;
283                   while (strlen(key) > 0 && isspace((int)key[strlen(key)-1]))
284                     key[strlen(key)-1] = '\0';
285                   val = "";
286                 }
287                         
288               if (strcmp(key, "GNUSTEP_USER_ROOT") == 0)
289                 {
290                   if (*val == '~')
291                     {
292                       user = malloc(strlen(val) + strlen(home));
293                       strcpy(user, home);
294                       strcat(user, &val[1]);
295                     }
296                   else
297                     {
298                       user = malloc(strlen(val) + 1);
299                       strcpy(user, val);
300                     }
301                 }
302               else if (strcmp(key, "GNUSTEP_DEFAULTS_ROOT") == 0)
303                 {
304                   if (*val == '~')
305                     {
306                       defs = malloc(strlen(val) + strlen(home));
307                       strcpy(defs, home);
308                       strcat(defs, &val[1]);
309                     }
310                   else
311                     {
312                       defs = malloc(strlen(val) + 1);
313                       strcpy(defs, val);
314                     }
315                 }
316               else if (strcmp(key, "FORCE_USER_ROOT") == 0)
317                 {
318                   forceU = 1;
319                 }
320               else if (strcmp(key, "FORCE_DEFAULTS_ROOT") == 0)
321                 {
322                   forceD = 1;
323                 }
324             }
325           fclose(fptr);
326         }
327
328       if (*user == '\0' || forceU == 0 || *defs == '\0' || forceD == 0)
329         {
330           strcpy(path, home);
331           strcat(path, SEP);
332           strcat(path, ".GNUsteprc");
333           fptr = fopen(path, "r");
334           if (fptr != 0)
335             {
336               while (fgets(buf0, sizeof(buf0), fptr) != 0)
337                 {
338                   char  *pos = strchr(buf0, '=');
339
340                   if (pos != 0)
341                     {
342                       char      *key = buf0;
343                       char      *val = pos;
344
345                       *val++ = '\0';
346                       while (isspace((int)*key))
347                         key++;
348                       while (strlen(key) > 0
349                         && isspace((int)key[strlen(key)-1]))
350                         key[strlen(key)-1] = '\0';
351                       while (isspace((int)*val))
352                         val++;
353                       while (strlen(val) > 0
354                         && isspace((int)val[strlen(val)-1]))
355                         val[strlen(val)-1] = '\0';
356
357                       if (strcmp(key, "GNUSTEP_USER_ROOT") == 0)
358                         {
359                           if (*user == '\0' || forceU == 0)
360                             {
361                               if (*val == '~')
362                                 {
363                                   user = malloc(strlen(val) + strlen(home));
364                                   strcpy(user, home);
365                                   strcat(user, &val[1]);
366                                 }
367                               else
368                                 {
369                                   user = malloc(strlen(val) + 1);
370                                   strcpy(user, val);
371                                 }
372                             }
373                         }
374                       else if (strcmp(key, "GNUSTEP_DEFAULTS_ROOT") == 0)
375                         {
376                           if (*defs == '\0' || forceD == 0)
377                             {
378                               if (*val == '~')
379                                 {
380                                   defs = malloc(strlen(val) + strlen(home));
381                                   strcpy(defs, home);
382                                   strcat(defs, &val[1]);
383                                 }
384                               else
385                                 {
386                                   defs = malloc(strlen(val) + 1);
387                                   strcpy(defs, val);
388                                 }
389                             }
390                         }
391                     }
392                 }
393               fclose(fptr);
394             }
395         }
396
397       if (type == DEFS)
398         {
399           strcpy(path, defs);
400           if (*path == '\0')
401             {
402               strcpy(path, user);
403             }
404         }
405       else
406         {
407           strcpy(path, user);
408         }
409
410       if (*path == '\0')
411         {
412           strcpy(path, home);
413           strcat(path, SEP);
414           strcat(path, "GNUstep");
415         }
416     }
417 #if defined(__MINGW__)
418   /*
419    * We always want to use unix style paths.
420    */
421   if (strlen(path) > 1 && path[1] == ':')
422     {
423       char      *ptr = path;
424
425       while (*ptr != '\0')
426         {
427           if (*ptr == '\\')
428             {
429               *ptr = '/';
430             }
431           if (*ptr == '/' && ptr > path && ptr[-1] == '/')
432             {
433               memmove(ptr, &ptr[1], strlen(ptr)+1);
434             }
435           else
436             {
437               ptr++;
438             }
439         }
440       if (path[2] == '/' || path[2] == '\0')
441         {
442           path[1] = path[0];
443         }
444       else
445         {
446           memmove(&path[1], path, strlen(path)+1);
447           path[2] = '/';
448         }
449       path[0] = '/';
450     }
451 #endif
452   printf("%s", path);
453   return 0;
454 }
455