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
28 #include <sys/utsname.h>
30 #include "libs/fvwm_sys_stat.h"
33 #include <sys/select.h>
41 #define FD_SETSIZE 2048
45 fd_set_size_t fvwmlib_max_fd
= (fd_set_size_t
)-9999999;
47 fd_set_size_t
GetFdWidth(void)
50 return min(sysconf(_SC_OPEN_MAX
),FD_SETSIZE
);
52 return min(getdtablesize(),FD_SETSIZE
);
56 void fvwmlib_init_max_fd(void)
58 fvwmlib_max_fd
= GetFdWidth();
64 /* return a string indicating the OS type (i.e. "Linux", "SINIX-D", ... ) */
65 int getostype(char *buf
, int max
)
68 struct utsname sysname
;
70 if (uname( &sysname
) >= 0)
73 strncat(buf
, sysname
.sysname
, max
);
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);
99 char *p
= strchr(*p_path
, '+');
100 memmove(p
+ oldlen
, p
+ 1, strlen(p
+ 1) + 1);
101 memmove(p
, oldpath
, oldlen
);
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.
122 const char *pathlist
, const char *filename
, const char *suffix
,
129 if (filename
== NULL
|| *filename
== 0)
134 if (pathlist
== NULL
|| *pathlist
== 0)
136 /* use pwd if no path list is given */
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);
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
155 if (access(filename
, type
) == 0)
160 /* the file is not accessable (don't test suffixes with full
161 * path), return NULL */
167 /* Search each element of the pathlist for the file */
168 while (pathlist
&& *pathlist
)
170 char *path_end
= strchr(pathlist
, ':');
173 if (path_end
!= NULL
)
175 strncpy(path
, pathlist
, path_end
- pathlist
);
176 path
[path_end
- pathlist
] = '\0';
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
, '.');
189 /* count a leading nil in newext_len too */
190 int newext_len
= path
+ strlen(path
) - curr_end
;
193 filebase_len
= dot
- filename
;
197 filebase_len
= filename_len
;
200 memmove(curr_end
+ filebase_len
, curr_end
, newext_len
);
201 strncpy(curr_end
, filename
, filebase_len
);
206 strcat(path
, filename
);
209 if (access(path
, type
) == 0)
214 if (suffix
&& *suffix
!= '\0') {
215 strcat(path
, suffix
);
216 if (access(path
, type
) == 0)
222 /* Point to next element of the path */
223 if (path_end
== NULL
)
229 pathlist
= path_end
+ 1;
233 /* Hmm, couldn't find the file. 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
))
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
);
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> */
285 #include <sys/types.h>
286 #include <sys/stat.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)
306 static unsigned long value
;
309 int save_errno
= errno
;
311 len
= strlen (template);
312 if (len
< 6 || strcmp (&template[len
- 6], "XXXXXX"))
314 __set_errno (EINVAL
);
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];
332 XXXXXX
[1] = letters
[v
% 62];
334 XXXXXX
[2] = letters
[v
% 62];
336 XXXXXX
[3] = letters
[v
% 62];
338 XXXXXX
[4] = letters
[v
% 62];
340 XXXXXX
[5] = letters
[v
% 62];
343 template, O_RDWR
| O_CREAT
| O_EXCL
,
344 FVWM_S_IRUSR
| FVWM_S_IWUSR
);
347 __set_errno (save_errno
);
350 else if (errno
!= EEXIST
)
356 /* We got out of the loop because we ran out of combinations to try. */
357 __set_errno (EEXIST
);
361 #endif /* HAVE_SAFETY_MKSTEMP */