Restructure how we look for Read files slightly.
[fvwm.git] / libs / System.c
blobf06f2baa2a3bcf6c06b382247126a4d4f33fab5d
1 /* -*-c-*- */
2 /* This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 * System.c: code for dealing with various OS system call variants
21 #include "config.h"
22 #include "fvwmlib.h"
23 #include "envvar.h"
24 #include "System.h"
25 #include "Strings.h"
27 #if HAVE_UNAME
28 #include <sys/utsname.h>
29 #endif
30 #include "libs/fvwm_sys_stat.h"
32 #if HAVE_SYS_SELECT_H
33 #include <sys/select.h>
34 #endif
38 * just in case...
40 #ifndef FD_SETSIZE
41 #define FD_SETSIZE 2048
42 #endif
45 fd_set_size_t fvwmlib_max_fd = (fd_set_size_t)-9999999;
47 fd_set_size_t GetFdWidth(void)
49 #if HAVE_SYSCONF
50 return min(sysconf(_SC_OPEN_MAX),FD_SETSIZE);
51 #else
52 return min(getdtablesize(),FD_SETSIZE);
53 #endif
56 void fvwmlib_init_max_fd(void)
58 fvwmlib_max_fd = GetFdWidth();
60 return;
64 /* return a string indicating the OS type (i.e. "Linux", "SINIX-D", ... ) */
65 int getostype(char *buf, int max)
67 #if HAVE_UNAME
68 struct utsname sysname;
70 if (uname( &sysname ) >= 0)
72 buf[0] = '\0';
73 strncat(buf, sysname.sysname, max);
74 return 0;
76 #endif
77 strcpy (buf, "");
78 return -1;
83 * Set a colon-separated path, with environment variable expansions,
84 * and expand '+' to be the value of the previous path.
86 void setPath(char **p_path, const char *newpath, int free_old_path)
88 char *oldpath = *p_path;
89 int oldlen = strlen(oldpath);
90 char *stripped_path = stripcpy(newpath);
91 int found_plus = strchr(newpath, '+') != NULL;
93 /* Leave room for the old path, if we find a '+' in newpath */
94 *p_path = envDupExpand(stripped_path, found_plus ? oldlen - 1 : 0);
95 free(stripped_path);
97 if (found_plus)
99 char *p = strchr(*p_path, '+');
100 memmove(p + oldlen, p + 1, strlen(p + 1) + 1);
101 memmove(p, oldpath, oldlen);
104 if (free_old_path)
106 free(oldpath);
113 * Find the specified file somewhere along the given path.
115 * There is a possible race condition here: We check the file and later
116 * do something with it. By then, the file might not be accessible.
117 * Oh well.
120 #include <stdio.h>
121 char *searchPath(
122 const char *pathlist, const char *filename, const char *suffix,
123 int type)
125 char *path;
126 int filename_len;
127 int maxpath_len;
129 if (filename == NULL || *filename == 0)
131 return NULL;
134 if (pathlist == NULL || *pathlist == 0)
136 /* use pwd if no path list is given */
137 pathlist = ".";
140 filename_len = strlen(filename);
141 maxpath_len = (pathlist) ? strlen(pathlist) : 0;
142 maxpath_len += (suffix) ? strlen(suffix) : 0;
144 /* +1 for extra / and +1 for null termination */
145 path = safemalloc(maxpath_len + filename_len + 2);
146 *path = '\0';
148 if (*filename == '/')
150 /* No search if filename begins with a slash */
151 strcpy(path, filename);
153 /* test if the path is accessable -- the module code assumes
154 * this is done */
155 if (access(filename, type) == 0)
157 return path;
160 /* the file is not accessable (don't test suffixes with full
161 * path), return NULL */
162 free(path);
164 return NULL;
167 /* Search each element of the pathlist for the file */
168 while (pathlist && *pathlist)
170 char *path_end = strchr(pathlist, ':');
171 char *curr_end;
173 if (path_end != NULL)
175 strncpy(path, pathlist, path_end - pathlist);
176 path[path_end - pathlist] = '\0';
178 else
180 strcpy(path, pathlist);
183 /* handle specially the path extention using semicolon */
184 curr_end = strchr(path, ';');
185 if (curr_end != NULL)
187 char *dot = strrchr(filename, '.');
188 int filebase_len;
189 /* count a leading nil in newext_len too */
190 int newext_len = path + strlen(path) - curr_end;
191 if (dot != NULL)
193 filebase_len = dot - filename;
195 else
197 filebase_len = filename_len;
199 *(curr_end++) = '/';
200 memmove(curr_end + filebase_len, curr_end, newext_len);
201 strncpy(curr_end, filename, filebase_len);
203 else
205 strcat(path, "/");
206 strcat(path, filename);
209 if (access(path, type) == 0)
211 return path;
214 if (suffix && *suffix != '\0') {
215 strcat(path, suffix);
216 if (access(path, type) == 0)
218 return path;
222 /* Point to next element of the path */
223 if (path_end == NULL)
225 break;
227 else
229 pathlist = path_end + 1;
233 /* Hmm, couldn't find the file. Return NULL */
234 free(path);
235 return NULL;
239 * void setFileStamp(FileStamp *stamp, const char *name);
240 * Bool isFileStampChanged(const FileStamp *stamp, const char *name);
242 * An interface for verifying cached files.
243 * The first function associates a file stamp with file (named by name).
244 * The second function returns True or False in case the file was changed
245 * from the time the stamp was associated.
247 * FileStamp can be a structure; try to save memory by evaluating a checksum.
250 FileStamp getFileStamp(const char *name)
252 static struct stat buf;
254 if (!name || stat(name, &buf))
256 return 0;
258 return ((FileStamp)buf.st_mtime << 13) + (FileStamp)buf.st_size;
261 void setFileStamp(FileStamp *stamp, const char *name)
263 *stamp = getFileStamp(name);
266 Bool isFileStampChanged(const FileStamp *stamp, const char *name)
268 return *stamp != getFileStamp(name);
271 #ifdef HAVE_SAFETY_MKSTEMP
272 int fvwm_mkstemp (char *TEMPLATE)
274 return mkstemp(TEMPLATE);
276 #else
278 /* This function is an adaptation of the mkstemp() function included
279 * in the Gnu C Library, version 2.2.2. The Gnu C library, in turn,
280 * adapted the function from OpenBSD.
281 * Michael Han <mikehan@mikehan.com> */
283 #include <stdio.h>
284 #include <errno.h>
285 #include <sys/types.h>
286 #include <sys/stat.h>
287 #include <fcntl.h>
288 #include <unistd.h>
289 #include "ftime.h"
291 #define __set_errno(val) errno = (val)
293 /* These are the characters used in temporary filenames. */
294 static const char letters[] =
295 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
297 /* Generate a unique temporary file name from TEMPLATE.
298 The last six characters of TEMPLATE must be "XXXXXX";
299 they are replaced with a string that makes the filename unique.
300 Then open the file and return a fd. */
302 int fvwm_mkstemp (char *template)
304 int len;
305 char *XXXXXX;
306 static unsigned long value;
307 struct timeval tv;
308 int count, fd = -1;
309 int save_errno = errno;
311 len = strlen (template);
312 if (len < 6 || strcmp (&template[len - 6], "XXXXXX"))
314 __set_errno (EINVAL);
315 return -1;
318 /* This is where the Xs start. */
319 XXXXXX = &template[len - 6];
321 /* Get some more or less random data. */
322 gettimeofday (&tv, NULL);
323 value = ((unsigned long) tv.tv_usec << 16) ^ tv.tv_sec ^ getpid ();
325 for (count = 0; count < TMP_MAX; value = 7777, count)
327 unsigned long v = value;
329 /* Fill in the random bits. */
330 XXXXXX[0] = letters[v % 62];
331 v /= 62;
332 XXXXXX[1] = letters[v % 62];
333 v /= 62;
334 XXXXXX[2] = letters[v % 62];
335 v /= 62;
336 XXXXXX[3] = letters[v % 62];
337 v /= 62;
338 XXXXXX[4] = letters[v % 62];
339 v /= 62;
340 XXXXXX[5] = letters[v % 62];
342 fd = open(
343 template, O_RDWR | O_CREAT | O_EXCL,
344 FVWM_S_IRUSR | FVWM_S_IWUSR);
345 if (fd >= 0)
347 __set_errno (save_errno);
348 return fd;
350 else if (errno != EEXIST)
352 return -1;
356 /* We got out of the loop because we ran out of combinations to try. */
357 __set_errno (EEXIST);
358 return -1;
361 #endif /* HAVE_SAFETY_MKSTEMP */