GRASS Programmer's Manual  6.5.svn(2014)-r66266
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
user_config.c
Go to the documentation of this file.
1 
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <assert.h>
31 #include <unistd.h>
32 #include <string.h>
33 #ifndef __MINGW32__
34 #include <pwd.h>
35 #endif
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #include <errno.h>
39 #include <grass/gis.h>
40 
41 
42 /**************************************************************************
43  * _make_toplevel(): make user's toplevel config directory if it doesn't
44  * already exist. Adjust perms to 1700. Returns the toplevel directory
45  * path [caller must G_free ()] on success, or NULL on failure
46  *************************************************************************/
47 
48 #ifndef __MINGW32__ /* TODO */
49 static char *_make_toplevel(void)
50 {
51  size_t len;
52  int status;
53 
54 #ifdef __MINGW32__
55  char *defaulthomedir = "c:";
56  char *homedir = getenv("HOME");
57 #else
58  uid_t me;
59  struct passwd *my_passwd;
60 #endif
61  struct stat buf;
62  char *path;
63 
64  errno = 0;
65 
66  /* Query whatever database to get user's home dir */
67 #ifdef __MINGW32__
68  if (NULL == homedir) {
69  homedir = defaulthomedir;
70  }
71 
72  len = strlen(homedir) + 8; /* + "/.grass\0" */
73  if (NULL == (path = G_calloc(1, len))) {
74  return NULL;
75  }
76  sprintf(path, "%s%s", homedir, "/.grass");
77 #else
78  me = getuid();
79  my_passwd = getpwuid(me);
80  if (my_passwd == NULL)
81  return NULL;
82 
83  len = strlen(my_passwd->pw_dir) + 8; /* + "/.grass\0" */
84  if (NULL == (path = G_calloc(1, len)))
85  return NULL;
86 
87  sprintf(path, "%s%s", my_passwd->pw_dir, "/.grass");
88 #endif
89 
90  status = G_lstat(path, &buf);
91 
92  /* If errno == ENOENT, the directory doesn't exist */
93  if (status != 0) {
94  if (errno == ENOENT) {
95  status = G_mkdir(path);
96 
97  if (status != 0) { /* mkdir failed */
98  G_free(path);
99  return NULL;
100  }
101 
102  /* override umask settings, if possible */
103  chmod(path, S_IRWXU);
104 
105  /* otherwise mkdir succeeded, we're done here */
106  return path;
107  }
108 
109  /* other errors should not be defined ??? give up */
110  G_free(path);
111  return NULL;
112  }
113  /* implicit else */
114 
115  /* Examine the stat "buf" */
116  /* It better be a directory */
117  if (!S_ISDIR(buf.st_mode)) { /* File, link, something else */
118  errno = ENOTDIR; /* element is not a directory, but should be */
119  G_free(path);
120  return NULL;
121  }
122 
123  /* No read/write/execute ??? */
124  if (!((S_IRUSR & buf.st_mode) &&
125  (S_IWUSR & buf.st_mode) && (S_IXUSR & buf.st_mode)
126  )
127  ) {
128  errno = EACCES; /* Permissions error */
129  G_free(path);
130  return NULL;
131  }
132 
133  /* We'll assume that if the user grants greater permissions
134  * than we would, that they know what they're doing
135  * -- so we're done here...
136  */
137 
138  return path;
139 }
140 
141 
142 /**************************************************************************
143  * _elem_count_split: Does a couple things:
144  * 1) Counts the number of elements in "elems"
145  * 2) Replaces occurrences of '/' with '\0'
146  * 3) Checks that no element begins with a '.'
147  * 4) Checks there are no '//'
148  *
149  * Therefore, THE STRING THAT IS PASSED IN IS MODIFIED
150  * Returns 0 if there are no elements, or an element
151  * beginning with a '.' or containing a '//' is found.
152  *************************************************************************/
153 static int _elem_count_split(char *elems)
154 {
155  int i;
156  size_t len;
157  char *begin, *end;
158 
159  /* Some basic assertions */
160  assert(elems != NULL);
161  assert((len = strlen(elems)) > 0);
162  assert(*elems != '/');
163 
164  begin = elems;
165  for (i = 0; begin != NULL && len > begin - elems; i++) {
166  /* check '.' condition */
167  if (*begin == '.')
168  return 0;
169  end = strchr(begin, '/');
170  /* check '//' condition */
171  if (end != NULL && end == begin)
172  return 0;
173  /* okay, change '/' into '\0' */
174  begin = end;
175  if (begin != NULL) {
176  *begin = '\0'; /* begin points at '/', change it */
177  begin++; /* increment begin to next char */
178  }
179  }
180 
181  /* That's it */
182  return i;
183 }
184 
185 
186 /**************************************************************************
187  * _make_sublevels(): creates subelements as necessary from the passed
188  * "elems" string. It returns the full path if successful or NULL
189  * if it fails. "elems" must not be NULL, zero length, or have any
190  * elements that begin with a '.' or any occurrences of '//'.
191  *************************************************************************/
192 static char *_make_sublevels(const char *elems)
193 {
194  int i, status;
195  char *cp, *path, *top, *ptr;
196  struct stat buf;
197 
198  /* Get top level path */
199  if (NULL == (top = _make_toplevel()))
200  return NULL;
201 
202  /* Make a copy of elems */
203  if (NULL == (cp = G_store(elems))) {
204  G_free(top);
205  return NULL;
206  }
207 
208  /* Do element count, sanity checking and "splitting" */
209  if ((i = _elem_count_split(cp)) < 1) {
210  G_free(cp);
211  G_free(top);
212  return NULL;
213  }
214 
215  /* Allocate our path to be large enough */
216  if ((path = G_calloc(1, strlen(top) + strlen(elems) + 2)) == NULL) {
217  G_free(top);
218  G_free(cp);
219  return NULL;
220  }
221 
222  /* Now loop along adding directories if they don't exist
223  * make sure the thing is a directory as well.
224  * If there was a trailing '/' in the original "elem", it doesn't
225  * make it into the returned path.
226  */
227  for (; i > 0; i--) {
228  sprintf(path, "%s/%s", top, cp);
229  errno = 0;
230  status = G_lstat(path, &buf);
231  if (status != 0) {
232  /* the element doesn't exist */
233  status = G_mkdir(path);
234  if (status != 0) {
235  /* Some kind of problem... */
236  G_free(top);
237  G_free(cp);
238  return NULL;
239  }
240  /* override umask settings, if possible */
241  chmod(path, S_IRWXU);
242  }
243  else {
244  /* Examine the stat "buf" */
245  /* It better be a directory */
246  if (!S_ISDIR(buf.st_mode)) { /* File, link, something else */
247  errno = ENOTDIR; /* element is not a directory, but should be */
248  G_free(path);
249  return NULL;
250  }
251 
252  /* No read/write/execute ??? */
253  if (!((S_IRUSR & buf.st_mode) &&
254  (S_IWUSR & buf.st_mode) && (S_IXUSR & buf.st_mode)
255  )
256  ) {
257  errno = EACCES; /* Permissions error */
258  G_free(path);
259  return NULL;
260  }
261 
262  /* okay continue ... */
263  }
264 
265  ptr = strchr(cp, '\0');
266  *ptr = '/';
267  }
268 
269  /* All done, free memory */
270  G_free(top);
271  G_free(cp);
272 
273  return path;
274 }
275 
276 
291 char *G_rc_path(const char *element, const char *item)
292 {
293  size_t len;
294  char *path, *ptr;
295 
296  assert(!(element == NULL && item == NULL));
297 
298  /* Simple item in top-level */
299  if (element == NULL) {
300  path = _make_toplevel();
301  }
302  else if (item == NULL) {
303  return _make_sublevels(element);
304  }
305  else {
306  path = _make_sublevels(element);
307  }
308 
309 
310  assert(*item != '.');
311  assert(path != NULL);
312  ptr = strchr(item, '/'); /* should not have slashes */
313  assert(ptr == NULL);
314  len = strlen(path) + strlen(item) + 2;
315  if ((ptr = G_realloc(path, len)) == NULL) {
316  G_free(path);
317  return NULL;
318  }
319  path = ptr;
320  ptr = strchr(path, '\0');
321  sprintf(ptr, "/%s", item);
322 
323  return path;
324 } /* G_rc_path */
325 
326 
327 /* vim: set softtabstop=4 shiftwidth=4 expandtab: */
328 #endif
sprintf(buf2,"%s", G3D_CATS_ELEMENT)
void G_free(void *buf)
Free allocated memory.
Definition: gis/alloc.c:142
char * G_store(const char *s)
Copy string to allocated memory.
Definition: store.c:32
int G_mkdir(const char *path)
Creates a new directory.
Definition: paths.c:17
int G_lstat(const char *file_name, struct stat *buf)
Get file status.
Definition: paths.c:135
char * getenv()
int stat
Definition: g3dcolor.c:369
char buf[GNAME_MAX+sizeof(G3D_DIRECTORY)+2]
Definition: g3drange.c:62
return NULL
Definition: dbfopen.c:1394
int errno
char * G_rc_path(const char *element, const char *item)
Returns path to element and item.
Definition: user_config.c:291