GRASS Programmer's Manual
6.4.2(2012)
|
00001 00002 /*************************************************************************** 00003 * tools.c 00004 * 00005 * Mon Apr 18 15:00:13 2005 00006 * Copyright 2005 Benjamin Ducke 00007 ****************************************************************************/ 00008 00009 /* 00010 * This program is free software; you can redistribute it and/or modify 00011 * it under the terms of the GNU General Public License as published by 00012 * the Free Software Foundation; either version 2 of the License, or 00013 * (at your option) any later version. 00014 * 00015 * This program is distributed in the hope that it will be useful, 00016 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00018 * GNU Library General Public License for more details. 00019 * 00020 * You should have received a copy of the GNU General Public License 00021 * along with this program; if not, write to the Free Software 00022 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 00023 */ 00024 00025 #include "globals.h" 00026 00027 00028 /* the following are for cross-platform compatibility. They may already exist 00029 on a Linux or BSD system, but maybe absent e.g. in Win32, so we will define 00030 them here. */ 00031 00032 00033 char *basename(char *path) 00034 { 00035 char *copy; 00036 char *element; 00037 char *backup; 00038 00039 copy = strdup(path); 00040 00041 backup = NULL; 00042 element = strtok(copy, "/"); 00043 if (element == NULL) { 00044 if (copy != NULL) { 00045 free(copy); 00046 } 00047 return (NULL); 00048 } 00049 00050 backup = strdup(element); 00051 while (element != NULL) { 00052 element = strtok(NULL, "/"); 00053 if ((backup != NULL) && (element != NULL)) { 00054 free(backup); 00055 } 00056 if ((element != NULL) && (*element != '\0')) { 00057 backup = strdup(element); 00058 } 00059 } 00060 00061 if (copy != NULL) { 00062 free(copy); 00063 } 00064 00065 return (backup); 00066 } 00067 00068 00069 /* A shell version of mkdir () 00070 needed because the MINGW one does no accept unix style MOD specifications. 00071 THIS DOES NOT CHECK FOR ERRORS ! 00072 */ 00073 void mkdir_s(char *pathname, char *mode) 00074 { 00075 char tmp[5000]; 00076 00077 sprintf(tmp, "mkdir %s --mode=%s -p", pathname, mode); 00078 system(tmp); 00079 00080 } 00081 00082 /* 00083 Removes all dangling white-spaces and EOL chars from the end of a string. 00084 Returns total number of chopped-off characters. 00085 */ 00086 int chop(char *string) 00087 { 00088 int i; 00089 int chopped; 00090 int stop = 0; 00091 00092 chopped = 0; 00093 i = strlen(string) - 1; 00094 while (i >= 0) { 00095 stop = 1; 00096 if ((string[i] == '\n') || (string[i] == '\t') || 00097 (string[i] == ' ') || (string[i] == '\f') || 00098 (string[i] == '\r')) { 00099 chopped++; 00100 stop = 0; 00101 } 00102 if (stop == 1) { 00103 /* got a non white-space char: stop chopping! */ 00104 break; 00105 } 00106 i--; 00107 } 00108 00109 /* chop string */ 00110 string[strlen(string) - chopped] = '\0'; 00111 00112 return (chopped); 00113 } 00114 00115 00116 /* 00117 Inserts a string into an array of n strings; positions start at 0 00118 The size of the array will be increased by one char*. 00119 Returns new size of array. 00120 String array must be NULL-terminated. 00121 There must be at least one slots left after the NULL-terminator to 00122 hold the new string! This function will not resize the string 00123 array to accomodate the new string! 00124 */ 00125 int insert_str(char *str, int pos, char **strarr) 00126 { 00127 char save[MAXSTR]; 00128 char insert[MAXSTR]; 00129 char last[MAXSTR]; 00130 int n, j; 00131 int len; 00132 00133 /* check for valid pos */ 00134 n = 0; 00135 while (strarr[n] != NULL) { 00136 n++; 00137 } 00138 00139 if ((pos < 0) || (pos > (n))) { 00140 print_error(ERR_REGISTER_ENTRIES_GISMAN, 00141 "insert: invalid line number %i.\n", pos); 00142 } 00143 00144 /* if a new string is to be added to the end of the array: */ 00145 if (pos == n) { 00146 len = (1 + strlen(str)) * sizeof(char); 00147 strarr[n] = malloc(len); 00148 strcpy(strarr[n], str); 00149 n = n + 2; 00150 strarr[n - 1] = NULL; 00151 return (n); 00152 } 00153 00154 strcpy(last, strarr[n - 1]); 00155 strcpy(insert, strarr[pos]); 00156 free(strarr[pos]); 00157 strarr[pos] = malloc((1 + strlen(str)) * sizeof(char)); 00158 strcpy(strarr[pos], str); 00159 /* now move all strings > pos up one */ 00160 for (j = pos; j < n - 1; j++) { 00161 strcpy(save, strarr[j + 1]); /* save string to be overwritten */ 00162 free(strarr[j + 1]); /* overwrite string */ 00163 len = (1 + strlen(insert)) * sizeof(char); /* make room for string to be inserted */ 00164 strarr[j + 1] = malloc(len); 00165 strcpy(strarr[j + 1], insert); /* insert string */ 00166 00167 strcpy(insert, save); /* set saved string to next to be inserted */ 00168 00169 } 00170 00171 /* overwrite NULL terminator with last item */ 00172 strarr[n] = malloc((1 + strlen(last)) * sizeof(char)); 00173 strcpy(strarr[n], last); 00174 00175 /* increase size of array by one */ 00176 n = n + 2; 00177 strarr[n - 1] = NULL; /* set last element of array to NULL */ 00178 00179 return (n); 00180 } 00181 00182 00183 /* 00184 Delete a string at position pos (o to n) from an array of n strings; 00185 positions start at 0 00186 The size of the array will be decreased by one char*. 00187 Returns new size of array. 00188 String array must be NULL-terminated. 00189 */ 00190 int delete_str(int pos, char **strarr) 00191 { 00192 int i; 00193 00194 /* check for valid pos */ 00195 i = 0; 00196 while (strarr[i] != NULL) { 00197 i++; 00198 } 00199 00200 if ((pos < 0) || (pos > (i))) { 00201 print_error(ERR_REGISTER_ENTRIES_GISMAN, 00202 "delete: invalid line number %i.\n", pos); 00203 } 00204 00205 /* now move all strings > pos down one */ 00206 i = pos; 00207 while (strarr[i] != NULL) { 00208 free(strarr[i]); 00209 if (strarr[i + 1] != NULL) { 00210 strarr[i] = malloc((1 + (strlen(strarr[i + 1]))) * sizeof(char)); 00211 strcpy(strarr[i], strarr[i + 1]); 00212 } 00213 i++; 00214 } 00215 00216 /* decrease size of array by one */ 00217 i = i - 1; 00218 strarr[i] = NULL; /* set last element of array to NULL */ 00219 00220 return (i); 00221 } 00222 00223 00224 /* 00225 Returns the first line number in which *str is found. 00226 Search starts after line number 'start'. 00227 Returns -1 if string not found. 00228 String array must be NULL-terminated. 00229 */ 00230 int find_pos(char *str, char **strarr, int start) 00231 { 00232 int i, j; 00233 00234 /* check for valid pos */ 00235 i = 0; 00236 while (strarr[i] != NULL) { 00237 i++; 00238 } 00239 00240 if ((start < 0) || (start > (i))) { 00241 exit(ERR_REGISTER_ENTRIES_GISMAN); 00242 } 00243 00244 for (j = start; j < (i); j++) { 00245 if (strstr(strarr[j], str) != NULL) { 00246 return (j); 00247 } 00248 } 00249 00250 return (-1); 00251 } 00252 00253 00254 /* 00255 Dumps an array of strings to a file. 00256 String array must be NULL-terminated. 00257 */ 00258 void dump_str(FILE * f, char **strarr) 00259 { 00260 int i; 00261 00262 i = 0; 00263 while (strarr[i] != NULL) { 00264 fprintf(f, "%i: %s", i, strarr[i]); 00265 i++; 00266 } 00267 } 00268 00269 /* 00270 Get package name. Copies the package name as found in 00271 the 'name' info file into the char array *name. 00272 */ 00273 void get_package_name(char *path, char *name) 00274 { 00275 FILE *f; 00276 char file[MAXSTR]; 00277 char tmp[MAXSTR]; 00278 00279 sprintf(file, "%s/%s", path, "name"); 00280 00281 /* get extension name */ 00282 f = fopen(file, "r"); 00283 if (f == NULL) { 00284 print_error(ERR_INVALID_EXT, "'name' file not readable.\n"); 00285 } 00286 else { 00287 if (nc_fgets_nb(tmp, MAXSTR, f) == NULL) { 00288 fclose(f); 00289 print_error(ERR_INVALID_EXT, 00290 "invalid or missing extension name.\n"); 00291 } 00292 else { 00293 chop(tmp); 00294 strcpy(name, tmp); 00295 } 00296 } 00297 fclose(f); 00298 } 00299 00300 /* 00301 A replacement function for fgets to filter out comments and blank lines. 00302 Useful for parsing settings files. 00303 Returns a line from a file only if it does not start with '#'. 00304 Returns only the part of the line left of '#'. 00305 Otherwise, tries to read the next line from the file or returns NULL on EOF. 00306 */ 00307 char *nc_fgets(char *s, int size, FILE * stream) 00308 { 00309 char *hashmark; 00310 char *tmp; 00311 00312 if (fgets(s, size, stream) == NULL) { 00313 return (NULL); 00314 } 00315 00316 hashmark = strchr(s, '#'); 00317 00318 if (hashmark != NULL) { 00319 if (s - hashmark == 0) { 00320 /* line starts with a hashmark: recursively call nc_fgets() */ 00321 return (nc_fgets(s, size, stream)); 00322 } 00323 else { 00324 /* return only the part before '#' */ 00325 tmp = malloc(sizeof(char) * MAXSTR); 00326 strcpy(tmp, s); 00327 tmp = strtok(tmp, "#"); 00328 sprintf(s, "%s\n", tmp); 00329 free(tmp); 00330 } 00331 } 00332 return (s); 00333 } 00334 00335 00336 /* 00337 Same as nc_fgets (). Additionally, this filters for HTML tags. 00338 */ 00339 char *nc_fgets_html(char *s, int size, FILE * stream) 00340 { 00341 char *hashmark; 00342 char *tmp; 00343 char *tag; 00344 char *tag_2; 00345 char *tag_insert; 00346 char *tag_content; 00347 char *pos; 00348 char *insert; 00349 int space; 00350 00351 if (fgets(s, size, stream) == NULL) { 00352 return (NULL); 00353 } 00354 00355 /* look for HTML tags: this discards all text inside the tags except for: 00356 <br> becomes \n 00357 <p> becomes \n\n 00358 */ 00359 tmp = malloc(sizeof(char) * (strlen(s) + 1)); 00360 tag_content = malloc(sizeof(char) * (strlen(s) + 1)); 00361 00362 insert = tmp; 00363 pos = s; 00364 00365 while (*pos != '\0') { 00366 if (*pos == '<') { /* possibly an html open tag */ 00367 tag = pos; 00368 tag_insert = tag_content; 00369 pos--; 00370 if (pos >= s) { 00371 if (*pos == 32) { 00372 space = 1; 00373 } 00374 else { 00375 space = 0; 00376 } 00377 } 00378 while (*tag != '\0') { 00379 *tag_insert = *tag; 00380 (*tag_insert)++; 00381 if (*tag == '>') { /* OK, we got a tag */ 00382 *tag_insert = '\0'; 00383 00384 /* only add additional newlines, if this is not the end of the line already! */ 00385 tag_2 = tag; 00386 tag_2++; 00387 if (*tag_2 != '\n') { 00388 if (strstr(tag_content, "<br>") != NULL) { 00389 /* a <br> at the start of a line produce no additional linefeed! */ 00390 if (insert > tmp) { 00391 *insert = '\n'; 00392 (*insert)++; 00393 } 00394 } 00395 if (strstr(tag_content, "<BR>") != NULL) { 00396 if (insert > tmp) { 00397 *insert = '\n'; 00398 (*insert)++; 00399 } 00400 } 00401 if (strstr(tag_content, "<p>") != NULL) { 00402 if (insert > tmp) { 00403 *insert = '\n'; 00404 (*insert)++; 00405 } 00406 *insert = '\n'; 00407 (*insert)++; 00408 } 00409 if (strstr(tag_content, "<P>") != NULL) { 00410 if (insert > tmp) { 00411 *insert = '\n'; 00412 (*insert)++; 00413 } 00414 *insert = '\n'; 00415 (*insert)++; 00416 } 00417 } 00418 00419 pos = tag; /* skip this */ 00420 00421 /* if the next character is a space and there was none 00422 before the tag: skip that, too 00423 */ 00424 if (*pos == 32) { 00425 if (space == 1) { 00426 pos++; 00427 space = 0; 00428 } 00429 } 00430 break; 00431 } 00432 tag++; 00433 } 00434 } 00435 if (*pos != '>') { 00436 *insert = *pos; 00437 insert++; 00438 } 00439 pos++; 00440 } 00441 00442 *insert = '\0'; 00443 00444 strcpy(s, tmp); 00445 00446 free(tmp); 00447 free(tag_content); 00448 00449 hashmark = strchr(s, '#'); 00450 00451 if (hashmark != NULL) { 00452 if (s - hashmark == 0) { 00453 /* line starts with a hashmark: recursively call nc_fgets_html() */ 00454 return (nc_fgets_html(s, size, stream)); 00455 } 00456 else { 00457 /* return only the part before '#' */ 00458 tmp = malloc(sizeof(char) * MAXSTR); 00459 strcpy(tmp, s); 00460 tmp = strtok(tmp, "#"); 00461 sprintf(s, "%s\n", tmp); 00462 free(tmp); 00463 } 00464 } 00465 00466 return (s); 00467 } 00468 00469 00470 /* 00471 Checks whether a string actually contains text or is a blank line/whitespace only. 00472 Returns 1 if text , 0 if only blank/whitespace. 00473 */ 00474 int is_text(char *s) 00475 { 00476 int i; 00477 int nonws; 00478 00479 /* check for a blank or white-space only line */ 00480 nonws = 0; 00481 for (i = strlen(s) - 1; i >= 0; i--) { 00482 if ((s[i] == ' ') || (s[i] == '\t') || (s[i] == '\n') || 00483 (s[i] == '\f') || (s[i] == '\r')) { 00484 nonws = 0; 00485 } 00486 else { 00487 nonws = 1; 00488 break; /* break at first non-ws char! */ 00489 } 00490 } 00491 00492 return (nonws); 00493 } 00494 00495 00496 /* 00497 Same as nc_fgets() but also skips over blank lines and those that contain only 00498 whitespace chars. 00499 */ 00500 char *nc_fgets_nb(char *s, int size, FILE * stream) 00501 { 00502 char *hashmark; 00503 char *tmp; 00504 00505 if (fgets(s, size, stream) == NULL) { 00506 return (NULL); 00507 } 00508 00509 00510 if (is_text(s) == 0) { 00511 /* line is ws only: recursively call nc_fgets() to get next line */ 00512 return (nc_fgets_nb(s, size, stream)); 00513 } 00514 00515 hashmark = strchr(s, '#'); 00516 00517 if (hashmark != NULL) { 00518 if (s - hashmark == 0) { 00519 /* line starts with a hashmark: recursively call nc_fgets() */ 00520 return (nc_fgets_nb(s, size, stream)); 00521 } 00522 else { 00523 /* return only the part before '#' */ 00524 tmp = malloc(sizeof(char) * MAXSTR); 00525 strcpy(tmp, s); 00526 tmp = strtok(tmp, "#"); 00527 sprintf(s, "%s\n", tmp); 00528 free(tmp); 00529 } 00530 } 00531 return (s); 00532 } 00533 00534 00535 /* 00536 This just dumps an ASCII file to stdout, line by line, but 00537 skips over comments. 00538 */ 00539 void dump_ascii(char *file, char *heading) 00540 { 00541 char tmp[MAXSTR]; 00542 FILE *f; 00543 00544 fprintf(stdout, "%s\n", heading); 00545 f = fopen(file, "r"); 00546 if (f == NULL) { 00547 fprintf(stdout, " No information available.\n"); 00548 } 00549 else { 00550 while (nc_fgets_html(tmp, MAXSTR, f) != NULL) { 00551 fprintf(stdout, " %s", tmp); 00552 } 00553 fprintf(stdout, "\n"); 00554 fclose(f); 00555 } 00556 } 00557 00558 00559 /* 00560 Dumps the contents of an ASCII file without comment lines but with blank lines 00561 to a temporary file. 00562 */ 00563 void dump_plain(char *file, char *tmpfile) 00564 { 00565 char tmp[MAXSTR]; 00566 FILE *f_in; 00567 FILE *f_out; 00568 00569 /* create a temporary menu.tcl file for write access */ 00570 /* TODO: Do not hardcode temp path */ 00571 strcpy(tmpfile, "/tmp/grass.extensions.db.XXXXXX"); /* TMP_GISMAN is a global variable */ 00572 mkstemp(tmpfile); 00573 00574 f_out = fopen(tmpfile, "w+"); 00575 if (f_out == NULL) { 00576 print_error(ERR_DUMP_PLAIN_TXT, 00577 "could not create temp file '%s': %s\n \ 00578 Make sure that directory /tmp exists on your system and you have write permission.\n", tmpfile, strerror(errno)); 00579 } 00580 00581 atexit(&exit_db); /* now need to register an at exit func to remove tmpfile automatically! */ 00582 00583 f_in = fopen(file, "r"); 00584 while (nc_fgets(tmp, MAXSTR, f_in) != NULL) { 00585 fprintf(f_out, tmp); 00586 } 00587 00588 fclose(f_in); 00589 fclose(f_out); 00590 } 00591 00592 00593 /* 00594 Same as dump_plain() but adds a <br> after each newline in the stream. 00595 Also replaces blank lines with a <p>. 00596 */ 00597 void dump_html(char *file, char *tmpfile) 00598 { 00599 char tmp[MAXSTR]; 00600 char line[MAXSTR]; 00601 FILE *f_in; 00602 FILE *f_out; 00603 int fd; 00604 00605 /* create a temporary menu.tcl file for write access */ 00606 /* TODO: Do not hardcode temp path */ 00607 strcpy(tmpfile, "/tmp/grass.extensions.db.XXXXXX"); /* TMP_GISMAN is a global variable */ 00608 mkstemp(tmpfile); 00609 00610 f_out = fopen(tmpfile, "w+"); 00611 if (f_out == NULL) { 00612 print_error(ERR_DUMP_PLAIN_TXT, 00613 "could not create temp file '%s': %s\n \ 00614 Make sure that directory /tmp exists on your system and you have write permission.\n", tmpfile, strerror(errno)); 00615 } 00616 00617 atexit(&exit_db); /* now need to register an at exit func to remove tmpfile automatically! */ 00618 00619 f_in = fopen(file, "r"); 00620 while (nc_fgets(line, MAXSTR, f_in) != NULL) { 00621 chop(line); 00622 if (!is_text(line)) { /* replace blank lines with a <p> */ 00623 fprintf(f_out, "<p>\n"); 00624 } 00625 else { 00626 sprintf(tmp, "%s <br>\n", line); 00627 fprintf(f_out, tmp); 00628 } 00629 } 00630 00631 fclose(f_in); 00632 fclose(f_out); 00633 close(fd); 00634 } 00635 00636 00637 /* 00638 A pretty dumb function: this just lists all directories which are directly below 00639 top level and not called "src". It is assumed that these contain binary distributions 00640 which can be installed by just doing a "make install" in the respective directory. 00641 */ 00642 void list_binaries(char *package) 00643 { 00644 char tmp[MAXSTR]; 00645 struct stat buf; 00646 DIR *dir; 00647 struct dirent *dir_entry; 00648 int n_dirs = 0; 00649 00650 fprintf(stdout, "Binary installation files\n"); 00651 00652 dir = opendir(package); 00653 if (dir == NULL) { 00654 fprintf(stdout, " None.\n\n"); 00655 return; 00656 } 00657 00658 dir_entry = readdir(dir); 00659 while (dir_entry != NULL) { 00660 if ((strcmp(dir_entry->d_name, ".")) && 00661 (strcmp(dir_entry->d_name, "..")) && 00662 (strcmp(dir_entry->d_name, "src")) 00663 ) { 00664 /* check if it is a directory */ 00665 sprintf(tmp, "%s/%s", package, dir_entry->d_name); 00666 stat(tmp, &buf); 00667 if (S_ISDIR(buf.st_mode)) { 00668 if (n_dirs == 0) { 00669 fprintf(stdout, " %s", dir_entry->d_name); 00670 } 00671 else { 00672 fprintf(stdout, ", %s", dir_entry->d_name); 00673 } 00674 n_dirs++; 00675 } 00676 } 00677 dir_entry = readdir(dir); 00678 } 00679 if (n_dirs == 0) { 00680 fprintf(stdout, " None."); 00681 } 00682 fprintf(stdout, "\n\n"); 00683 } 00684 00685 00686 /* 00687 Just as dumb: checks, if a specified directory 'binaries' exists in addition to 'src' 00688 Returns 1 if so, 0 otherwise 00689 */ 00690 int binaries_exist(char *package, char *binaries) 00691 { 00692 char tmp[MAXSTR]; 00693 struct stat buf; 00694 DIR *dir; 00695 struct dirent *dir_entry; 00696 00697 dir = opendir(package); 00698 if (dir == NULL) { 00699 return (0); 00700 } 00701 00702 dir_entry = readdir(dir); 00703 while (dir_entry != NULL) { 00704 if ((strcmp(dir_entry->d_name, ".")) && 00705 (strcmp(dir_entry->d_name, "..")) && 00706 (strcmp(dir_entry->d_name, "src")) 00707 ) { 00708 /* check if it is a directory */ 00709 sprintf(tmp, "%s/%s", package, dir_entry->d_name); 00710 stat(tmp, &buf); 00711 if (S_ISDIR(buf.st_mode)) { 00712 if (!strcmp(dir_entry->d_name, binaries)) { 00713 return (1); /* found it */ 00714 } 00715 } 00716 } 00717 dir_entry = readdir(dir); 00718 } 00719 return (0); 00720 } 00721 00722 00723 /* 00724 Tests for a known file-extension: 00725 .tar.gz, .tgz 00726 .tar.bz2, .tbz 00727 .zip 00728 Returns: 00729 0 = unknown (TYPE_UNKNOWN) 00730 1 = tar file with gzip compression (TAR_GZIP) 00731 2 = tar file with bzip2 compression (TAR_BZIP2) 00732 3 = zip archive (ZIP) 00733 4 = plain tar archive, uncompressed (TAR) 00734 00735 VERY primitive! 00736 */ 00737 int check_filetype(char *myfile) 00738 { 00739 00740 if (strstr(myfile, ".tar.gz") != NULL) { 00741 return (1); 00742 } 00743 if (strstr(myfile, ".tgz") != NULL) { 00744 return (1); 00745 } 00746 if (strstr(myfile, ".tar.bz2") != NULL) { 00747 return (2); 00748 } 00749 if (strstr(myfile, ".tbz") != NULL) { 00750 return (2); 00751 } 00752 if (strstr(myfile, ".zip") != NULL) { 00753 return (3); 00754 } 00755 if (strstr(myfile, ".tar") != NULL) { 00756 return (4); 00757 } 00758 00759 return (0); 00760 } 00761 00762 /* 00763 Retrieves an extension from the WWW using wget and 00764 stores the file in the current directory. 00765 */ 00766 void wget_extension(char *url) 00767 { 00768 char str[MAXSTR]; 00769 int error; 00770 00771 fprintf(stdout, "Downloading..."); 00772 00773 if (VERBOSE) { 00774 sprintf(str, "wget -N %s", url); 00775 } 00776 else { 00777 sprintf(str, "wget -N -q %s", url); 00778 } 00779 error = system(str); 00780 if (error == -1) { 00781 print_error(ERR_DOWNLOAD, 00782 "could not run 'wget' to download extension. Is it installed?\n"); 00783 } 00784 if (error > 0) { 00785 print_error(ERR_DOWNLOAD, "running command '%s'.\n", str); 00786 } 00787 00788 print_done(); 00789 } 00790 00791 /* 00792 This function checks if there is write access to the GRASS directory. 00793 If not, it aborts with an error message. 00794 Otherwise, 'cmd' is simply executed as currently running user. 00795 */ 00796 void su(char *gisbase, char *cmd) 00797 { 00798 char tmpfile[MAXSTR]; 00799 int error; 00800 static unsigned long next; 00801 FILE *f; 00802 00803 /* check for permission */ 00804 next = next * 1103515245 + 54321; /* generate a random file name */ 00805 next = (next / 65536) % 32768; 00806 srand(next); 00807 sprintf(tmpfile, "%s/gem.test.%i", gisbase, rand()); 00808 00809 f = fopen(tmpfile, "w+"); 00810 00811 if (errno == EACCES) { /* permission denied */ 00812 print_error(ERR_INSTALL_EXT, 00813 "You don't have write access to your local GRASS installation.\nPlease consult your system administrator.\n"); 00814 } 00815 else { 00816 remove(tmpfile); 00817 fclose(f); 00818 error = system(cmd); 00819 if (error != 0) { 00820 print_error(ERR_MISSING_CMD, "could not run '%s'.\n", cmd); 00821 } 00822 } 00823 } 00824 00825 00826 /* 00827 Compares two version descriptions consisting of three ints each 00828 returns: -1, if major.minor.revision < major2.minor2.revision2, 00829 0, if equal 00830 1, if major.minor.revision > major2.minor2.revision2, 00831 */ 00832 int vercmp(int major, int minor, int revision, int major2, int minor2, 00833 int revision2) 00834 { 00835 if ((major == major2) && (minor == minor2) && (revision == revision2)) { 00836 return (0); 00837 } 00838 if (major2 > major) { 00839 return (-1); 00840 } 00841 if (major2 < major) { 00842 return (1); 00843 } 00844 if (minor2 > minor) { 00845 return (-1); 00846 } 00847 if (minor2 < minor) { 00848 return (1); 00849 } 00850 if (revision2 > revision) { 00851 return (-1); 00852 } 00853 if (revision2 < revision) { 00854 return (1); 00855 } 00856 00857 return (0); 00858 }