00001
00007
00008
00009
00010 #include <stdio.h>
00011 #include <stdlib.h>
00012 #include <string.h>
00013 #include <sys/stat.h>
00014
00015 #include "portability.h"
00016 #include "utility.h"
00017
00032 int
00033 gs_versions_incompatible(const char *ver1, const char *ver2)
00034 {
00035 int maj1, min1, rev1, maj2, min2, rev2, n1, n2;
00036
00037 if(!ver1 || !ver2) {
00038 ERRPRINTF("Warning: bad args\n");
00039 return 1;
00040 }
00041
00042 maj1 = min1 = rev1 = maj2 = min2 = rev2 = 0;
00043
00044 n1 = sscanf(ver1, "%d.%d.%d", &maj1, &min1, &rev1);
00045 n2 = sscanf(ver2, "%d.%d.%d", &maj2, &min2, &rev2);
00046
00047 if((n1 < 1) || (n2 < 1)) {
00048 ERRPRINTF("Warning: malformed version number\n");
00049 return 1;
00050 }
00051
00052 return (maj1 != maj2) || (min1 != min2);
00053 }
00054
00065 char *
00066 gs_get_line(FILE *in)
00067 {
00068 #define BUFSZ 400
00069 char buf[BUFSZ];
00070 char *rv, *line, *ltmp;
00071 int idx = 0, cur_size = BUFSZ;
00072
00073 if(!in) return NULL;
00074
00075 line = (char *)malloc(BUFSZ);
00076 *line = '\0';
00077
00078 if(!line) return NULL;
00079
00080 do {
00081 rv = fgets(buf, BUFSZ, in);
00082
00083 if(!rv) {
00084 free(line);
00085 return NULL;
00086 }
00087
00088 memcpy(line+idx, buf, BUFSZ);
00089 idx += strlen(buf);
00090
00091 cur_size += BUFSZ;
00092 ltmp = realloc(line, cur_size);
00093
00094 if(!ltmp) return NULL;
00095 line = ltmp;
00096 } while(buf[strlen(buf)-1] != '\n');
00097
00098 return line;
00099 }
00100
00112 char *
00113 gs_read_line(FILE *f, int *linecount)
00114 {
00115 char *tmp = NULL;
00116 do
00117 {
00118 if(tmp)
00119 free(tmp);
00120 tmp = gs_get_line(f);
00121 if(!tmp)
00122 break;
00123 (*linecount)++;
00124 } while((tmp[0] == '\n')||(tmp[0] == '#'));
00125 return tmp;
00126 }
00127
00138 int
00139 gs_parse_config_file(char *filename, gs_info_t **tmp)
00140 {
00141 gs_info_t *sa_headNode;
00142 int i = 0, linecount = 0;
00143 char *p, *line;
00144 FILE *sc_file;
00145
00146
00147 sc_file = fopen(filename, "r");
00148 if(!sc_file) {
00149 ERRPRINTF("Could not open %s file\n", filename);
00150 return -1;
00151 }
00152
00153
00154
00155
00156
00157
00158
00159 sa_headNode = (gs_info_t *)malloc(sizeof(gs_info_t));
00160 if(!sa_headNode) {
00161 fclose(sc_file);
00162 ERRPRINTF("Could not allocate memory for server attributes\n");
00163 return -1;
00164 }
00165
00166 *tmp = sa_headNode;
00167 while((line = gs_read_line(sc_file, &linecount))) {
00168
00169 (*tmp)->next = (gs_info_t *)malloc(sizeof(gs_info_t));
00170 if(!(*tmp)->next){
00171 free(line);
00172 free(sa_headNode);
00173 fclose(sc_file);
00174 ERRPRINTF("Could not allocate memory for server attributes\n");
00175 return -1;
00176 }
00177 (*tmp) = (*tmp)->next;
00178
00179 (*tmp)->value = strdup(strpbrk(line,"=")+1);
00180 if(!(*tmp)->value){
00181 free(line);
00182 free(sa_headNode);
00183 fclose(sc_file);
00184 ERRPRINTF("Could not strdup for (*tmp)->value\n");
00185 return -1;
00186 }
00187
00188 (*tmp)->type = strdup(strtok(line,"="));
00189 if(!(*tmp)->type){
00190 free(line);
00191 free(sa_headNode);
00192 fclose(sc_file);
00193 ERRPRINTF("Could not strdup for (*tmp)->type\n");
00194 return -1;
00195 }
00196
00197 (*tmp)->next= NULL;
00198
00199 while(((*tmp)->value[strlen((*tmp)->value)-1] == ' ') ||
00200 ((*tmp)->value[strlen((*tmp)->value)-1] == '\n'))
00201 (*tmp)->value[strlen((*tmp)->value)-1] = '\0';
00202
00203 i = strspn((*tmp)->value, " ");
00204 if(i >0){
00205 for (p = (*tmp)->value; ; p++){
00206 *p = *(p+i);
00207 if(*p == '\0') break;
00208 }
00209 }
00210
00211 while((*tmp)->type[strlen((*tmp)->type)-1] == ' ')
00212 (*tmp)->type[strlen((*tmp)->type)-1] = '\0';
00213
00214 sprintf(line,"%s=%s",(*tmp)->type,(*tmp)->value);
00215
00216 if (putenv(strdup(line)) != 0){
00217 free(line);
00218 free(sa_headNode);
00219 fclose(sc_file);
00220 ERRPRINTF("Could not putenv \n");
00221 return -1;
00222 }
00223
00224 free(line);
00225 }
00226 *tmp = sa_headNode->next;
00227 free(sa_headNode);
00228 fclose(sc_file);
00229 return 0;
00230 }
00231
00232
00233 #ifndef WIN32
00234
00244 int
00245 gs_open_locked_file(char *filename, short lock_type, int flags)
00246 {
00247 int fd;
00248
00249 if(!filename) {
00250 ERRPRINTF("Invalid arg: null filename\n");
00251 return -1;
00252 }
00253
00254 if((fd = open(filename, flags, 0600)) == -1) {
00255 ERRPRINTF("open failed\n");
00256 perror("open");
00257 return -1;
00258 }
00259
00260
00261
00262 if (gs_lock_fd(fd, lock_type) == -1) {
00263 perror("lock");
00264 close(fd);
00265 return -1;
00266 }
00267
00268 return fd;
00269 }
00270 #endif
00271
00280 int
00281 gs_unlock_file(int fd)
00282 {
00283 if(gs_unlock_fd(fd) == -1) {
00284 ERRPRINTF("Warning: could not unlock file\n");
00285 perror("unlock");
00286 return -1;
00287 }
00288
00289 return 0;
00290 }
00291
00298 static void
00299 gs_alarm_catch(int sig)
00300 {
00301 return;
00302 }
00303
00315 #ifndef WIN32
00316 int
00317 gs_open_locked_file_timeout(char *lockfile, short lock_type, int flags, int timeout)
00318 {
00319 struct itimerval tv = {{timeout, 0}, {timeout, 0}};
00320 struct itimerval cv = {{0, 0}, {0, 0}};
00321 struct sigaction act, oldact;
00322 sigset_t set, oldset;
00323 int fd;
00324
00325 memset(&act, 0, sizeof(act));
00326 act.sa_handler = gs_alarm_catch;
00327 act.sa_flags = 0;
00328 sigfillset(&act.sa_mask);
00329 if(sigaction(SIGALRM, &act, &oldact) == -1) {
00330 ERRPRINTF("error setting up SIGALRM\n");
00331 return -1;
00332 }
00333
00334 sigemptyset(&set);
00335 sigaddset(&set, SIGALRM);
00336 if(sigprocmask(SIG_UNBLOCK, &set, &oldset) == -1) {
00337 ERRPRINTF("sigprocmask failed\n");
00338 sigaction(SIGALRM, &oldact, NULL);
00339 return -1;
00340 }
00341
00342 setitimer(ITIMER_REAL, &tv, 0);
00343
00344 fd = gs_open_locked_file(lockfile, lock_type, flags);
00345
00346 if(fd < 0) {
00347 setitimer(ITIMER_REAL, &cv, 0);
00348 sigprocmask(SIG_SETMASK, &oldset, NULL);
00349 return -1;
00350 }
00351
00352 setitimer(ITIMER_REAL, &cv, 0);
00353 sigprocmask(SIG_SETMASK, &oldset, NULL);
00354 sigaction(SIGALRM, &oldact, NULL);
00355
00356 return fd;
00357 }
00358 #endif
00359
00369 long
00370 gs_seconds_since_modified(char *filename)
00371 {
00372 gs_struct_stat stbuf;
00373 struct timeval tv;
00374 long age;
00375
00376 if(!filename)
00377 return -1;
00378
00379 if(gs_stat(filename, &stbuf) < 0)
00380 return -1;
00381
00382 gettimeofday(&tv, NULL);
00383
00384 age = tv.tv_sec - stbuf.st_mtime;
00385
00386 return age;
00387 }
00388
00389 int
00390 gs_get_contents_of_file(char *name, char **contents)
00391 {
00392 struct stat stbuf;
00393 int cfd, nread;
00394 char *buf;
00395
00396 if(stat(name, &stbuf) < 0)
00397 return -1;
00398
00399 buf = malloc((int)stbuf.st_size+1);
00400
00401 if(!buf) {
00402 ERRPRINTF("malloc failed\n");
00403 return -1;
00404 }
00405
00406 cfd = open(name, O_RDONLY, 0600);
00407
00408 if(cfd < 0) {
00409 ERRPRINTF("Warning: failed to open file '%s'\n", name);
00410 free(buf);
00411 return -1;
00412 }
00413
00414 nread = read(cfd, buf, (int) stbuf.st_size + 1);
00415 buf[nread] = '\0';
00416
00417 close(cfd);
00418
00419 if(nread <= 0) {
00420 free(buf);
00421 return -1;
00422 }
00423
00424 *contents = buf;
00425 return nread;
00426 }
00427
00428 static float
00429 gs_popen_loadavg(char *cmd)
00430 {
00431 float tmpf = -1;
00432 #ifndef WIN32
00433 char buf[200], *tmp, tmp2[20];
00434 FILE *pstream;
00435
00436 if((pstream = popen(cmd, "r")) == NULL)
00437 return -1;
00438
00439 tmp = fgets(buf, 200, pstream);
00440 pclose(pstream);
00441
00442 if(!tmp)
00443 return -1;
00444
00445 tmp = strstr(buf, "average:");
00446 if(!tmp)
00447 return -1;
00448
00449 if(sscanf(tmp, "%s %f", tmp2, &tmpf) != 2)
00450 return -1;
00451
00452 #endif
00453 return tmpf;
00454 }
00455
00456 static float
00457 gs_fopen_loadavg(char *filename)
00458 {
00459 FILE *loadavg_file;
00460 float tmpf;
00461 int n;
00462
00463 if((loadavg_file = fopen(filename, "r")) == NULL)
00464 return -1;
00465
00466 n = fscanf(loadavg_file, "%f", &tmpf);
00467
00468 fclose(loadavg_file);
00469
00470 if(n != 1)
00471 return -1;
00472
00473 return tmpf;
00474 }
00475
00484 int
00485 gs_get_workload()
00486 {
00487 char *commands[] = {"uptime", "w", NULL};
00488 char *files[] = {"/proc/loadavg", NULL};
00489 float workload;
00490 int i, scale;
00491
00492 scale = 100;
00493
00494 for(i=0;files[i];i++)
00495 if((workload = gs_fopen_loadavg(files[i])) >= 0)
00496 return (int) (scale * workload);
00497
00498 for(i=0;commands[i];i++)
00499 if((workload = gs_popen_loadavg(commands[i])) >= 0)
00500 return (int) (scale * workload);
00501
00502 return -1;
00503 }