no-fork.p
[cvsps/4msysgit.git] / util.c
blob79a44e832fb7c0389191ac7330e76a6a66aa16a0
1 /*
2 * Copyright 2001, 2002, 2003 David Mansfield and Cobite, Inc.
3 * See COPYING file for license information
4 */
6 #include <stdio.h>
7 #include <string.h>
8 #include <stdlib.h>
9 #include <unistd.h>
10 #include <limits.h>
11 #include <assert.h>
12 #ifdef __MINGW32__
13 #include <tsearch/search.h>
14 #include <windows.h>
15 #else
16 #include <search.h>
17 #endif
18 #include <time.h>
19 #include <errno.h>
20 #include <signal.h>
21 #include <regex.h>
22 #include <sys/stat.h>
23 #include <sys/time.h>
24 #include <sys/types.h>
25 #ifndef __MINGW32__
26 #include <sys/wait.h>
27 #endif
29 #include <cbtcommon/debug.h>
31 #include "util.h"
33 typedef int (*compare_func)(const void *, const void *);
35 static void * string_tree;
36 char *readfile(char const *filename, char *buf, size_t size)
38 FILE *fp;
39 char *ptr;
40 size_t len;
42 fp = fopen(filename, "r");
43 if (!fp)
44 return NULL;
46 ptr = fgets(buf, size, fp);
47 fclose(fp);
49 if (!ptr)
50 return NULL;
52 len = strlen(buf);
53 if (buf[len-1] == '\n')
54 buf[len-1] = '\0';
56 return buf;
59 char *strrep(char *s, char find, char replace)
61 char * p = s;
62 while (*p)
64 if (*p == find)
65 *p = replace;
66 p++;
69 return s;
72 char *get_cvsps_dir()
74 struct stat sbuf;
75 static char prefix[PATH_MAX];
76 const char * home;
78 if (prefix[0])
79 return prefix;
81 if (!(home = getenv("HOME")))
83 debug(DEBUG_APPERROR, "HOME environment variable not set");
84 exit(1);
87 if (snprintf(prefix, PATH_MAX, "%s/%s", home, CVSPS_PREFIX) >= PATH_MAX)
89 debug(DEBUG_APPERROR, "prefix buffer overflow");
90 exit(1);
93 /* Make sure the prefix directory exists */
94 if (stat(prefix, &sbuf) < 0)
96 int ret;
97 #ifdef __MINGW32__
98 ret = mkdir(prefix);
99 #else
100 ret = mkdir(prefix, 0777);
101 #endif
102 if (ret < 0)
104 debug(DEBUG_SYSERROR, "Cannot create the cvsps directory '%s'", CVSPS_PREFIX);
105 exit(1);
108 else
110 if (!(S_ISDIR(sbuf.st_mode)))
111 debug(DEBUG_APPERROR, "cvsps directory '%s' is not a directory!", CVSPS_PREFIX);
114 return prefix;
117 char *xstrdup(char const *str)
119 char *ret;
120 assert(str);
121 ret = strdup(str);
122 if (!ret)
124 debug(DEBUG_ERROR, "strdup failed");
125 exit(1);
128 return ret;
131 void strzncpy(char * dst, const char * src, int n)
133 strncpy(dst, src, n);
134 dst[n - 1] = 0;
137 char *get_string(char const *str)
139 char ** res;
141 if (!str)
142 return NULL;
144 res = (char **)tfind(str, &string_tree, (compare_func)strcmp);
145 if (!res)
147 char *key = xstrdup(str);
148 res = (char **)tsearch(key, &string_tree, (compare_func)strcmp);
149 *res = key;
152 return *res;
155 static int get_int_substr(const char * str, const regmatch_t * p)
157 char buff[256];
158 memcpy(buff, str + p->rm_so, p->rm_eo - p->rm_so);
159 buff[p->rm_eo - p->rm_so] = 0;
160 return atoi(buff);
163 static time_t mktime_utc(struct tm * tm)
165 char * old_tz = getenv("TZ");
166 time_t ret;
168 setenv("TZ", "UTC", 1);
170 tzset();
172 ret = mktime(tm);
174 if (old_tz)
175 setenv("TZ", old_tz, 1);
176 else
177 unsetenv("TZ");
179 tzset();
181 return ret;
184 void convert_date(time_t * t, const char * dte)
186 static regex_t date_re;
187 static int init_re;
189 #define MAX_MATCH 16
190 size_t nmatch = MAX_MATCH;
191 regmatch_t match[MAX_MATCH];
193 if (!init_re)
195 if (regcomp(&date_re, "([0-9]{4})[-/]([0-9]{2})[-/]([0-9]{2}) ([0-9]{2}):([0-9]{2}):([0-9]{2})", REG_EXTENDED))
197 fprintf(stderr, "FATAL: date regex compilation error\n");
198 exit(1);
200 init_re = 1;
203 if (regexec(&date_re, dte, nmatch, match, 0) == 0)
205 regmatch_t * pm = match;
206 struct tm tm = {0};
208 /* first regmatch_t is match location of entire re */
209 pm++;
211 tm.tm_year = get_int_substr(dte, pm++);
212 tm.tm_mon = get_int_substr(dte, pm++);
213 tm.tm_mday = get_int_substr(dte, pm++);
214 tm.tm_hour = get_int_substr(dte, pm++);
215 tm.tm_min = get_int_substr(dte, pm++);
216 tm.tm_sec = get_int_substr(dte, pm++);
218 tm.tm_year -= 1900;
219 tm.tm_mon--;
221 *t = mktime_utc(&tm);
223 else
225 *t = atoi(dte);
229 static struct timeval start_time;
231 void timing_start()
233 gettimeofday(&start_time, NULL);
236 void timing_stop(const char * msg)
238 struct timeval stop_time;
239 gettimeofday(&stop_time, NULL);
240 stop_time.tv_sec -= start_time.tv_sec;
241 stop_time.tv_usec -= start_time.tv_usec;
242 if (stop_time.tv_usec < 0)
243 stop_time.tv_sec--,stop_time.tv_usec += 1000000;
245 printf("Elapsed time for %s: %d.%06d\n", msg, (int)stop_time.tv_sec, (int)stop_time.tv_usec);
248 extern char ** environ;
250 /* taken from the linux manual page for system
251 See http://linux.die.net/man/3/system
253 int my_system (const char *command)
255 #ifdef __MINGW32__
256 /* Launch child process */
257 STARTUPINFO si;
258 ZeroMemory( &si, sizeof( si ) );
259 si.cb = sizeof( si );
260 PROCESS_INFORMATION pi;
261 ZeroMemory( &pi, sizeof( pi ) );
262 if( !CreateProcess(
263 0, /* module name (0 means use first token in command line) */
264 (char*)command, /* command line */
265 0, /* process security attributes */
266 0, /* primary thread security attributes */
267 TRUE, /* handles are inherited */
268 0, /* creation flags (none) */
269 0, /* use parent's environment */
270 0, /* use parent's current directory */
271 &si, /* STARTUPINFO pointer */
272 &pi /* receives PROCESS_INFORMATION */
273 ) ) {
274 debug(DEBUG_APPERROR, "CreateProcess failed.\n command line was: %s", command);
275 return -1;
278 /* Wait for child process to exit */
279 DWORD timeout = 10*1000; /* milliseconds */
280 DWORD ret = WaitForSingleObject( pi.hProcess, timeout );
281 if (ret == WAIT_OBJECT_0) {
282 /* OK. Child has exited */
284 else if (ret == WAIT_FAILED) {
285 DWORD last_err = GetLastError();
286 debug(DEBUG_APPERROR, "WaitForSingleObject failed.\n GetLastError returned : %d", last_err);
287 return -1;
289 else {
290 debug(DEBUG_APPERROR, "WaitForSingleObject returned %x", ret);
291 return -1;
294 /* Retrieve exit code */
295 DWORD exit_code;
296 if( !GetExitCodeProcess( pi.hProcess, &exit_code ) ) {
297 DWORD last_err = GetLastError();
298 debug(DEBUG_APPERROR, "GetExitCodeProcess failed.\n GetLastError returned : %d", last_err);
299 return -1;
302 return exit_code;
303 #else
304 int pid, status;
306 if (command == 0)
307 return 1;
308 pid = fork();
309 if (pid == -1)
310 return -1;
311 if (pid == 0) {
312 char *argv[4];
313 argv[0] = "sh";
314 argv[1] = "-c";
315 argv[2] = (char*)command; /* discard const */
316 argv[3] = 0;
317 execve("/bin/sh", argv, environ);
318 exit(127);
320 do {
321 if (waitpid(pid, &status, 0) == -1) {
322 if (errno != EINTR)
323 return -1;
324 } else
325 return status;
326 } while(1);
327 #endif
330 int escape_filename(char * dst, int len, const char * src)
332 static char * naughty_chars = " \\\"'@<>=;|&()#$`?*[!:{";
334 if (len > 0)
336 while (len > 1 && *src)
338 if (strchr(naughty_chars, *src))
340 if (len == 2)
341 break;
342 *dst++ = '\\';
343 len--;
346 *dst++ = *src++;
347 len--;
350 *dst = 0;
353 return (*src == 0) ? 0 : -1;