Add test about issue with no commit on a branch
[cvsps-hv.git] / util.c
blobe4b9d14d132acf6f70bbe18e60b648f13690f145
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 #include <search.h>
13 #include <time.h>
14 #include <errno.h>
15 #include <signal.h>
16 #include <regex.h>
17 #include <sys/stat.h>
18 #include <sys/time.h>
19 #include <sys/types.h>
20 #include <sys/wait.h>
22 #include <cbtcommon/debug.h>
24 #include "util.h"
26 typedef int (*compare_func)(const void *, const void *);
28 static void * string_tree;
29 char *readfile(char const *filename, char *buf, size_t size)
31 FILE *fp;
32 char *ptr;
33 size_t len;
35 fp = fopen(filename, "r");
36 if (!fp)
37 return NULL;
39 ptr = fgets(buf, size, fp);
40 fclose(fp);
42 if (!ptr)
43 return NULL;
45 len = strlen(buf);
46 if (buf[len-1] == '\n')
47 buf[len-1] = '\0';
49 return buf;
52 char *strrep(char *s, char find, char replace)
54 char * p = s;
55 while (*p)
57 if (*p == find)
58 *p = replace;
59 p++;
62 return s;
65 char *get_cvsps_dir()
67 struct stat sbuf;
68 static char prefix[PATH_MAX];
69 const char * home;
71 if (prefix[0])
72 return prefix;
74 if (!(home = getenv("HOME")))
76 debug(DEBUG_APPERROR, "HOME environment variable not set");
77 exit(1);
80 if (snprintf(prefix, PATH_MAX, "%s/%s", home, CVSPS_PREFIX) >= PATH_MAX)
82 debug(DEBUG_APPERROR, "prefix buffer overflow");
83 exit(1);
86 /* Make sure the prefix directory exists */
87 if (stat(prefix, &sbuf) < 0)
89 int ret;
90 ret = mkdir(prefix, 0777);
91 if (ret < 0)
93 debug(DEBUG_SYSERROR, "Cannot create the cvsps directory '%s'", CVSPS_PREFIX);
94 exit(1);
97 else
99 if (!(S_ISDIR(sbuf.st_mode)))
100 debug(DEBUG_APPERROR, "cvsps directory '%s' is not a directory!", CVSPS_PREFIX);
103 return prefix;
106 char *xstrdup(char const *str)
108 char *ret;
109 assert(str);
110 ret = strdup(str);
111 if (!ret)
113 debug(DEBUG_ERROR, "strdup failed");
114 exit(1);
117 return ret;
120 void strzncpy(char * dst, const char * src, int n)
122 strncpy(dst, src, n);
123 dst[n - 1] = 0;
126 char *get_string(char const *str)
128 char ** res;
130 if (!str)
131 return NULL;
133 res = (char **)tfind(str, &string_tree, (compare_func)strcmp);
134 if (!res)
136 char *key = xstrdup(str);
137 res = (char **)tsearch(key, &string_tree, (compare_func)strcmp);
138 *res = key;
141 return *res;
144 static int get_int_substr(const char * str, const regmatch_t * p)
146 char buff[256];
147 memcpy(buff, str + p->rm_so, p->rm_eo - p->rm_so);
148 buff[p->rm_eo - p->rm_so] = 0;
149 return atoi(buff);
152 static time_t mktime_utc(struct tm * tm)
154 char * old_tz = getenv("TZ");
155 time_t ret;
157 setenv("TZ", "UTC", 1);
159 tzset();
161 ret = mktime(tm);
163 if (old_tz)
164 setenv("TZ", old_tz, 1);
165 else
166 unsetenv("TZ");
168 tzset();
170 return ret;
173 void convert_date(time_t * t, const char * dte)
175 static regex_t date_re;
176 static int init_re;
178 #define MAX_MATCH 16
179 size_t nmatch = MAX_MATCH;
180 regmatch_t match[MAX_MATCH];
182 if (!init_re)
184 if (regcomp(&date_re, "([0-9]{4})[-/]([0-9]{2})[-/]([0-9]{2}) ([0-9]{2}):([0-9]{2}):([0-9]{2})", REG_EXTENDED))
186 fprintf(stderr, "FATAL: date regex compilation error\n");
187 exit(1);
189 init_re = 1;
192 if (regexec(&date_re, dte, nmatch, match, 0) == 0)
194 regmatch_t * pm = match;
195 struct tm tm = {0};
197 /* first regmatch_t is match location of entire re */
198 pm++;
200 tm.tm_year = get_int_substr(dte, pm++);
201 tm.tm_mon = get_int_substr(dte, pm++);
202 tm.tm_mday = get_int_substr(dte, pm++);
203 tm.tm_hour = get_int_substr(dte, pm++);
204 tm.tm_min = get_int_substr(dte, pm++);
205 tm.tm_sec = get_int_substr(dte, pm++);
207 tm.tm_year -= 1900;
208 tm.tm_mon--;
210 *t = mktime_utc(&tm);
212 else
214 *t = atoi(dte);
218 static struct timeval start_time;
220 void timing_start()
222 gettimeofday(&start_time, NULL);
225 void timing_stop(const char * msg)
227 struct timeval stop_time;
228 gettimeofday(&stop_time, NULL);
229 stop_time.tv_sec -= start_time.tv_sec;
230 stop_time.tv_usec -= start_time.tv_usec;
231 if (stop_time.tv_usec < 0)
232 stop_time.tv_sec--,stop_time.tv_usec += 1000000;
234 printf("Elapsed time for %s: %d.%06d\n", msg, (int)stop_time.tv_sec, (int)stop_time.tv_usec);
237 extern char ** environ;
239 /* taken from the linux manual page for system */
240 int my_system (const char *command)
242 int pid, status;
244 if (command == 0)
245 return 1;
246 pid = fork();
247 if (pid == -1)
248 return -1;
249 if (pid == 0) {
250 char *argv[4];
251 argv[0] = "sh";
252 argv[1] = "-c";
253 argv[2] = (char*)command; /* discard const */
254 argv[3] = 0;
255 execve("/bin/sh", argv, environ);
256 exit(127);
258 do {
259 if (waitpid(pid, &status, 0) == -1) {
260 if (errno != EINTR)
261 return -1;
262 } else
263 return status;
264 } while(1);
267 int escape_filename(char * dst, int len, const char * src)
269 static char * naughty_chars = " \\\"'@<>=;|&()#$`?*[!:{";
271 if (len > 0)
273 while (len > 1 && *src)
275 if (strchr(naughty_chars, *src))
277 if (len == 2)
278 break;
279 *dst++ = '\\';
280 len--;
283 *dst++ = *src++;
284 len--;
287 *dst = 0;
290 return (*src == 0) ? 0 : -1;