4 * ROX-Filer, filer for the ROX desktop project
5 * Copyright (C) 1999, Thomas Leonard, <tal197@ecs.soton.ac.uk>.
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the Free
9 * Software Foundation; either version 2 of the License, or (at your option)
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * You should have received a copy of the GNU General Public License along with
18 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
19 * Place, Suite 330, Boston, MA 02111-1307 USA
21 /* choices.c - code for handling loading and saving of user choices */
27 #include <sys/types.h>
28 #include <sys/param.h>
34 static char *program_name
= NULL
;
35 static char path_buffer
[MAXPATHLEN
];
37 /* Static prototypes */
38 static char *my_strdup(char *str
);
39 static char *make_choices_path(char *path
, char *leaf
,
40 int create
, char *shared_name
);
41 static char *default_user_choices();
42 static int exists(char *path
);
44 /* Call this before using any of the other functions in this file -
45 * it reads CHOICESPATH into an array for later use.
46 * The program name you pass here will be used for the directory name.
48 void choices_init(char *prog_name
)
50 program_name
= my_strdup(prog_name
);
54 /* Get the pathname of a choices file to load. Eg:
55 * choices_find_path_load("menus") -> "/usr/local/Choices/ProgName/menus".
56 * The return values may be NULL - use built-in defaults - otherwise
57 * it points to a static buffer which is valid until the next call to
60 char *choices_find_path_load(char *leaf
)
62 return choices_find_path_load_shared(leaf
, program_name
);
65 /* Like choices_find_path_load(), but use shared_name instead of
66 * prog_name (as passed to choices_init).
68 char *choices_find_path_load_shared(char *leaf
, char *shared_name
)
70 char *choices_path
, *path
;
74 fprintf(stderr
, "choices_find_path_load_shared: "
75 "bad program name (or not initialised)\n");
79 choices_path
= getenv("CHOICESPATH");
82 path
= make_choices_path(default_user_choices(),
83 leaf
, 0, shared_name
);
84 if (path
&& exists(path
))
86 choices_path
= "/usr/local/Choices:/usr/Choices";
89 if (*choices_path
== ':')
94 path
= make_choices_path(choices_path
, leaf
, 0, shared_name
);
95 if (path
&& exists(path
))
97 choices_path
= strchr(choices_path
, ':');
105 /* Return a linked list (possibly NULL) of matching files from all
106 * directories in CHOICESPATH. The first item in the list is the right-most
107 * entry in CHOICESPATH.
109 ChoicesList
*choices_find_load_all(char *leaf
, char *dir_name
)
111 char *choices_path
, *path
;
112 ChoicesList
*retval
= NULL
;
116 fprintf(stderr
, "choices_find_path_load_all: "
117 "bad Choices dir_name\n");
121 choices_path
= getenv("CHOICESPATH");
124 path
= make_choices_path(default_user_choices(),
126 if (path
&& exists(path
) && (path
= my_strdup(path
)))
128 retval
= malloc(sizeof(ChoicesList
));
133 choices_path
= "/usr/local/Choices:/usr/Choices";
136 if (*choices_path
== ':')
141 path
= make_choices_path(choices_path
, leaf
, 0, dir_name
);
142 if (path
&& exists(path
) && (path
= my_strdup(path
)))
146 new = malloc(sizeof(ChoicesList
));
152 choices_path
= strchr(choices_path
, ':');
160 /* Return a pathname to save to, or NULL if saving isn't possible.
161 * Otherwise, it points to a static buffer which is valid until the next call
162 * to the choices system.
163 * If 'create' is true then missing directories are created automatically.
165 char *choices_find_path_save(char *leaf
, int create
)
171 fprintf(stderr
, "choices_find_path_save: not initialised\n");
175 choices_path
= getenv("CHOICESPATH");
178 return make_choices_path(choices_path
, leaf
, create
,
181 return make_choices_path(default_user_choices(), leaf
,
182 create
, program_name
);
185 /* Like strdup(), but also reports an error to stderr on failure */
186 static char *my_strdup(char *str
)
190 retval
= strdup(str
);
193 fprintf(stderr
, "choices.c: strdup() failed\n");
198 /* Join these two strings together, with /ProgName/ between them, and return
199 * the resulting pathname as a pointer to a static buffer, or NULL on
201 * 'path' is \0 or : terminated and empty strings result in a NULL return.
202 * If create is non-zero then the extra directories will be created if they
203 * don't already exist.
205 static char *make_choices_path(char *path
,
211 size_t path_len
, prog_len
;
213 term
= path
? strchr(path
, ':') : NULL
;
214 if (term
== path
|| *path
== '\0')
218 path_len
= term
- path
;
220 path_len
= strlen(path
);
222 prog_len
= strlen(shared_name
);
224 /* path/progname/leaf0 */
225 if (path_len
+ prog_len
+ strlen(leaf
) + 3 >= MAXPATHLEN
)
226 return NULL
; /* Path is too long */
228 memcpy(path_buffer
, path
, path_len
);
231 path_buffer
[path_len
] = '\0';
232 mkdir(path_buffer
, S_IRWXU
| S_IRWXG
| S_IRWXO
);
235 path_buffer
[path_len
] = '/';
236 strcpy(path_buffer
+ path_len
+ 1, shared_name
);
238 mkdir(path_buffer
, S_IRWXU
| S_IRWXG
| S_IRWXO
);
240 path_buffer
[path_len
+ 1 + prog_len
] = '/';
241 strcpy(path_buffer
+ path_len
+ prog_len
+ 2, leaf
);
246 /* Return ${HOME}/Choices (expanded), or NULL */
247 static char *default_user_choices()
249 static char *retval
= NULL
;
255 home
= getenv("HOME");
259 else if (strlen(home
) + strlen("/Choices") >= MAXPATHLEN
- 1)
263 sprintf(path_buffer
, "%s/Choices", home
);
264 retval
= my_strdup(path_buffer
);
270 /* Returns 1 if the object exists, 0 if it doesn't */
271 static int exists(char *path
)
275 return stat(path
, &info
) == 0;