tools.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859
  1. /***************************************************************************
  2. * tools.c
  3. *
  4. * Mon Apr 18 15:00:13 2005
  5. * Copyright 2005 Benjamin Ducke
  6. ****************************************************************************/
  7. /*
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU Library General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  21. */
  22. #include "globals.h"
  23. /* the following are for cross-platform compatibility. They may already exist
  24. on a Linux or BSD system, but maybe absent e.g. in Win32, so we will define
  25. them here. */
  26. char *basename(char *path)
  27. {
  28. char *copy;
  29. char *element;
  30. char *backup;
  31. copy = strdup(path);
  32. backup = NULL;
  33. element = strtok(copy, "/");
  34. if (element == NULL) {
  35. if (copy != NULL) {
  36. free(copy);
  37. }
  38. return (NULL);
  39. }
  40. backup = strdup(element);
  41. while (element != NULL) {
  42. element = strtok(NULL, "/");
  43. if ((backup != NULL) && (element != NULL)) {
  44. free(backup);
  45. }
  46. if ((element != NULL) && (element != "")) {
  47. backup = strdup(element);
  48. }
  49. }
  50. if (copy != NULL) {
  51. free(copy);
  52. }
  53. return (backup);
  54. }
  55. /* A shell version of mkdir ()
  56. needed because the MINGW one does no accept unix style MOD specifications.
  57. THIS DOES NOT CHECK FOR ERRORS !
  58. */
  59. void mkdir_s(char *pathname, char *mode)
  60. {
  61. char tmp[5000];
  62. sprintf(tmp, "mkdir %s --mode=%s -p", pathname, mode);
  63. system(tmp);
  64. }
  65. /*
  66. Removes all dangling white-spaces and EOL chars from the end of a string.
  67. Returns total number of chopped-off characters.
  68. */
  69. int chop(char *string)
  70. {
  71. int i;
  72. int chopped;
  73. int stop = 0;
  74. chopped = 0;
  75. i = strlen(string) - 1;
  76. while (i >= 0) {
  77. stop = 1;
  78. if ((string[i] == '\n') || (string[i] == '\t') ||
  79. (string[i] == ' ') || (string[i] == '\f') ||
  80. (string[i] == '\r')) {
  81. chopped++;
  82. stop = 0;
  83. }
  84. if (stop == 1) {
  85. /* got a non white-space char: stop chopping! */
  86. break;
  87. }
  88. i--;
  89. }
  90. /* chop string */
  91. string[strlen(string) - chopped] = '\0';
  92. return (chopped);
  93. }
  94. /*
  95. Inserts a string into an array of n strings; positions start at 0
  96. The size of the array will be increased by one char*.
  97. Returns new size of array.
  98. String array must be NULL-terminated.
  99. There must be at least one slots left after the NULL-terminator to
  100. hold the new string! This function will not resize the string
  101. array to accomodate the new string!
  102. */
  103. int insert_str(char *str, int pos, char **strarr)
  104. {
  105. char save[MAXSTR];
  106. char insert[MAXSTR];
  107. char last[MAXSTR];
  108. int n, j;
  109. int len;
  110. /* check for valid pos */
  111. n = 0;
  112. while (strarr[n] != NULL) {
  113. n++;
  114. }
  115. if ((pos < 0) || (pos > (n))) {
  116. print_error(ERR_REGISTER_ENTRIES_GISMAN,
  117. "insert: invalid line number %i.\n", pos);
  118. }
  119. /* if a new string is to be added to the end of the array: */
  120. if (pos == n) {
  121. len = (1 + strlen(str)) * sizeof(char);
  122. strarr[n] = malloc(len);
  123. strcpy(strarr[n], str);
  124. n = n + 2;
  125. strarr[n - 1] = NULL;
  126. return (n);
  127. }
  128. strcpy(last, strarr[n - 1]);
  129. strcpy(insert, strarr[pos]);
  130. free(strarr[pos]);
  131. strarr[pos] = malloc((1 + strlen(str)) * sizeof(char));
  132. strcpy(strarr[pos], str);
  133. /* now move all strings > pos up one */
  134. for (j = pos; j < n - 1; j++) {
  135. strcpy(save, strarr[j + 1]); /* save string to be overwritten */
  136. free(strarr[j + 1]); /* overwrite string */
  137. len = (1 + strlen(insert)) * sizeof(char); /* make room for string to be inserted */
  138. strarr[j + 1] = malloc(len);
  139. strcpy(strarr[j + 1], insert); /* insert string */
  140. strcpy(insert, save); /* set saved string to next to be inserted */
  141. }
  142. /* overwrite NULL terminator with last item */
  143. strarr[n] = malloc((1 + strlen(last)) * sizeof(char));
  144. strcpy(strarr[n], last);
  145. /* increase size of array by one */
  146. n = n + 2;
  147. strarr[n - 1] = NULL; /* set last element of array to NULL */
  148. return (n);
  149. }
  150. /*
  151. Delete a string at position pos (o to n) from an array of n strings;
  152. positions start at 0
  153. The size of the array will be decreased by one char*.
  154. Returns new size of array.
  155. String array must be NULL-terminated.
  156. */
  157. int delete_str(int pos, char **strarr)
  158. {
  159. int i;
  160. /* check for valid pos */
  161. i = 0;
  162. while (strarr[i] != NULL) {
  163. i++;
  164. }
  165. if ((pos < 0) || (pos > (i))) {
  166. print_error(ERR_REGISTER_ENTRIES_GISMAN,
  167. "delete: invalid line number %i.\n", pos);
  168. }
  169. /* now move all strings > pos down one */
  170. i = pos;
  171. while (strarr[i] != NULL) {
  172. free(strarr[i]);
  173. if (strarr[i + 1] != NULL) {
  174. strarr[i] = malloc((1 + (strlen(strarr[i + 1]))) * sizeof(char));
  175. strcpy(strarr[i], strarr[i + 1]);
  176. }
  177. i++;
  178. }
  179. /* decrease size of array by one */
  180. i = i - 1;
  181. strarr[i] = NULL; /* set last element of array to NULL */
  182. return (i);
  183. }
  184. /*
  185. Returns the first line number in which *str is found.
  186. Search starts after line number 'start'.
  187. Returns -1 if string not found.
  188. String array must be NULL-terminated.
  189. */
  190. int find_pos(char *str, char **strarr, int start)
  191. {
  192. int i, j;
  193. /* check for valid pos */
  194. i = 0;
  195. while (strarr[i] != NULL) {
  196. i++;
  197. }
  198. if ((start < 0) || (start > (i))) {
  199. exit(ERR_REGISTER_ENTRIES_GISMAN);
  200. }
  201. for (j = start; j < (i); j++) {
  202. if (strstr(strarr[j], str) != NULL) {
  203. return (j);
  204. }
  205. }
  206. return (-1);
  207. }
  208. /*
  209. Dumps an array of strings to a file.
  210. String array must be NULL-terminated.
  211. */
  212. void dump_str(FILE * f, char **strarr)
  213. {
  214. int i;
  215. i = 0;
  216. while (strarr[i] != NULL) {
  217. fprintf(f, "%i: %s", i, strarr[i]);
  218. i++;
  219. }
  220. }
  221. /*
  222. Get package name. Copies the package name as found in
  223. the 'name' info file into the char array *name.
  224. */
  225. void get_package_name(char *path, char *name)
  226. {
  227. FILE *f;
  228. char file[MAXSTR];
  229. char tmp[MAXSTR];
  230. sprintf(file, "%s/%s", path, "name");
  231. /* get extension name */
  232. f = fopen(file, "r");
  233. if (f == NULL) {
  234. print_error(ERR_INVALID_EXT, "'name' file not readable.\n");
  235. }
  236. else {
  237. if (nc_fgets_nb(tmp, MAXSTR, f) == NULL) {
  238. fclose(f);
  239. print_error(ERR_INVALID_EXT,
  240. "invalid or missing extension name.\n");
  241. }
  242. else {
  243. chop(tmp);
  244. strcpy(name, tmp);
  245. }
  246. }
  247. fclose(f);
  248. }
  249. /*
  250. A replacement function for fgets to filter out comments and blank lines.
  251. Useful for parsing settings files.
  252. Returns a line from a file only if it does not start with '#'.
  253. Returns only the part of the line left of '#'.
  254. Otherwise, tries to read the next line from the file or returns NULL on EOF.
  255. */
  256. char *nc_fgets(char *s, int size, FILE * stream)
  257. {
  258. char *hashmark;
  259. char *tmp;
  260. if (fgets(s, size, stream) == NULL) {
  261. return (NULL);
  262. }
  263. hashmark = strchr(s, '#');
  264. if (hashmark != NULL) {
  265. if (s - hashmark == 0) {
  266. /* line starts with a hashmark: recursively call nc_fgets() */
  267. return (nc_fgets(s, size, stream));
  268. }
  269. else {
  270. /* return only the part before '#' */
  271. tmp = malloc(sizeof(char) * MAXSTR);
  272. strcpy(tmp, s);
  273. tmp = strtok(tmp, "#");
  274. sprintf(s, "%s\n", tmp);
  275. free(tmp);
  276. }
  277. }
  278. return (s);
  279. }
  280. /*
  281. Same as nc_fgets (). Additionally, this filters for HTML tags.
  282. */
  283. char *nc_fgets_html(char *s, int size, FILE * stream)
  284. {
  285. char *hashmark;
  286. char *tmp;
  287. char *tag;
  288. char *tag_2;
  289. char *tag_insert;
  290. char *tag_content;
  291. char *pos;
  292. char *insert;
  293. int space;
  294. if (fgets(s, size, stream) == NULL) {
  295. return (NULL);
  296. }
  297. /* look for HTML tags: this discards all text inside the tags except for:
  298. <br> becomes \n
  299. <p> becomes \n\n
  300. */
  301. tmp = malloc(sizeof(char) * (strlen(s) + 1));
  302. tag_content = malloc(sizeof(char) * (strlen(s) + 1));
  303. insert = tmp;
  304. pos = s;
  305. while (*pos != '\0') {
  306. if (*pos == '<') { /* possibly an html open tag */
  307. tag = pos;
  308. tag_insert = tag_content;
  309. pos--;
  310. if (pos >= s) {
  311. if (*pos == 32) {
  312. space = 1;
  313. }
  314. else {
  315. space = 0;
  316. }
  317. }
  318. while (*tag != '\0') {
  319. *tag_insert = *tag;
  320. (*tag_insert)++;
  321. if (*tag == '>') { /* OK, we got a tag */
  322. *tag_insert = '\0';
  323. /* only add additional newlines, if this is not the end of the line already! */
  324. tag_2 = tag;
  325. tag_2++;
  326. if (*tag_2 != '\n') {
  327. if (strstr(tag_content, "<br>") != NULL) {
  328. /* a <br> at the start of a line produce no additional linefeed! */
  329. if (insert > tmp) {
  330. *insert = '\n';
  331. (*insert)++;
  332. }
  333. }
  334. if (strstr(tag_content, "<BR>") != NULL) {
  335. if (insert > tmp) {
  336. *insert = '\n';
  337. (*insert)++;
  338. }
  339. }
  340. if (strstr(tag_content, "<p>") != NULL) {
  341. if (insert > tmp) {
  342. *insert = '\n';
  343. (*insert)++;
  344. }
  345. *insert = '\n';
  346. (*insert)++;
  347. }
  348. if (strstr(tag_content, "<P>") != NULL) {
  349. if (insert > tmp) {
  350. *insert = '\n';
  351. (*insert)++;
  352. }
  353. *insert = '\n';
  354. (*insert)++;
  355. }
  356. }
  357. pos = tag; /* skip this */
  358. /* if the next character is a space and there was none
  359. before the tag: skip that, too
  360. */
  361. if (*pos == 32) {
  362. if (space == 1) {
  363. pos++;
  364. space = 0;
  365. }
  366. }
  367. break;
  368. }
  369. tag++;
  370. }
  371. }
  372. if (*pos != '>') {
  373. *insert = *pos;
  374. insert++;
  375. }
  376. pos++;
  377. }
  378. *insert = '\0';
  379. strcpy(s, tmp);
  380. free(tmp);
  381. free(tag_content);
  382. hashmark = strchr(s, '#');
  383. if (hashmark != NULL) {
  384. if (s - hashmark == 0) {
  385. /* line starts with a hashmark: recursively call nc_fgets_html() */
  386. return (nc_fgets_html(s, size, stream));
  387. }
  388. else {
  389. /* return only the part before '#' */
  390. tmp = malloc(sizeof(char) * MAXSTR);
  391. strcpy(tmp, s);
  392. tmp = strtok(tmp, "#");
  393. sprintf(s, "%s\n", tmp);
  394. free(tmp);
  395. }
  396. }
  397. return (s);
  398. }
  399. /*
  400. Checks whether a string actually contains text or is a blank line/whitespace only.
  401. Returns 1 if text , 0 if only blank/whitespace.
  402. */
  403. int is_text(char *s)
  404. {
  405. int i;
  406. int nonws;
  407. /* check for a blank or white-space only line */
  408. nonws = 0;
  409. for (i = strlen(s) - 1; i >= 0; i--) {
  410. if ((s[i] == ' ') || (s[i] == '\t') || (s[i] == '\n') ||
  411. (s[i] == '\f') || (s[i] == '\r')) {
  412. nonws = 0;
  413. }
  414. else {
  415. nonws = 1;
  416. break; /* break at first non-ws char! */
  417. }
  418. }
  419. return (nonws);
  420. }
  421. /*
  422. Same as nc_fgets() but also skips over blank lines and those that contain only
  423. whitespace chars.
  424. */
  425. char *nc_fgets_nb(char *s, int size, FILE * stream)
  426. {
  427. char *hashmark;
  428. char *tmp;
  429. if (fgets(s, size, stream) == NULL) {
  430. return (NULL);
  431. }
  432. if (is_text(s) == 0) {
  433. /* line is ws only: recursively call nc_fgets() to get next line */
  434. return (nc_fgets_nb(s, size, stream));
  435. }
  436. hashmark = strchr(s, '#');
  437. if (hashmark != NULL) {
  438. if (s - hashmark == 0) {
  439. /* line starts with a hashmark: recursively call nc_fgets() */
  440. return (nc_fgets_nb(s, size, stream));
  441. }
  442. else {
  443. /* return only the part before '#' */
  444. tmp = malloc(sizeof(char) * MAXSTR);
  445. strcpy(tmp, s);
  446. tmp = strtok(tmp, "#");
  447. sprintf(s, "%s\n", tmp);
  448. free(tmp);
  449. }
  450. }
  451. return (s);
  452. }
  453. /*
  454. This just dumps an ASCII file to stdout, line by line, but
  455. skips over comments.
  456. */
  457. void dump_ascii(char *file, char *heading)
  458. {
  459. char tmp[MAXSTR];
  460. FILE *f;
  461. fprintf(stdout, "%s\n", heading);
  462. f = fopen(file, "r");
  463. if (f == NULL) {
  464. fprintf(stdout, " No information available.\n");
  465. }
  466. else {
  467. while (nc_fgets_html(tmp, MAXSTR, f) != NULL) {
  468. fprintf(stdout, " %s", tmp);
  469. }
  470. fprintf(stdout, "\n");
  471. fclose(f);
  472. }
  473. }
  474. /*
  475. Dumps the contents of an ASCII file without comment lines but with blank lines
  476. to a temporary file.
  477. */
  478. void dump_plain(char *file, char *tmpfile)
  479. {
  480. char tmp[MAXSTR];
  481. FILE *f_in;
  482. FILE *f_out;
  483. /* create a temporary menu.tcl file for write access */
  484. /* TODO: Do not hardcode temp path */
  485. strcpy(tmpfile, "/tmp/grass.extensions.db.XXXXXX"); /* TMP_GISMAN is a global variable */
  486. mkstemp(tmpfile);
  487. f_out = fopen(tmpfile, "w+");
  488. if (f_out == NULL) {
  489. print_error(ERR_DUMP_PLAIN_TXT,
  490. "could not create temp file '%s': %s\n \
  491. Make sure that directory /tmp exists on your system and you have write permission.\n", tmpfile, strerror(errno));
  492. }
  493. atexit(&exit_db); /* now need to register an at exit func to remove tmpfile automatically! */
  494. f_in = fopen(file, "r");
  495. while (nc_fgets(tmp, MAXSTR, f_in) != NULL) {
  496. fprintf(f_out, tmp);
  497. }
  498. fclose(f_in);
  499. fclose(f_out);
  500. }
  501. /*
  502. Same as dump_plain() but adds a <br> after each newline in the stream.
  503. Also replaces blank lines with a <p>.
  504. */
  505. void dump_html(char *file, char *tmpfile)
  506. {
  507. char tmp[MAXSTR];
  508. char line[MAXSTR];
  509. FILE *f_in;
  510. FILE *f_out;
  511. int fd;
  512. /* create a temporary menu.tcl file for write access */
  513. /* TODO: Do not hardcode temp path */
  514. strcpy(tmpfile, "/tmp/grass.extensions.db.XXXXXX"); /* TMP_GISMAN is a global variable */
  515. mkstemp(tmpfile);
  516. f_out = fopen(tmpfile, "w+");
  517. if (f_out == NULL) {
  518. print_error(ERR_DUMP_PLAIN_TXT,
  519. "could not create temp file '%s': %s\n \
  520. Make sure that directory /tmp exists on your system and you have write permission.\n", tmpfile, strerror(errno));
  521. }
  522. atexit(&exit_db); /* now need to register an at exit func to remove tmpfile automatically! */
  523. f_in = fopen(file, "r");
  524. while (nc_fgets(line, MAXSTR, f_in) != NULL) {
  525. chop(line);
  526. if (!is_text(line)) { /* replace blank lines with a <p> */
  527. fprintf(f_out, "<p>\n");
  528. }
  529. else {
  530. sprintf(tmp, "%s <br>\n", line);
  531. fprintf(f_out, tmp);
  532. }
  533. }
  534. fclose(f_in);
  535. fclose(f_out);
  536. close(fd);
  537. }
  538. /*
  539. A pretty dumb function: this just lists all directories which are directly below
  540. top level and not called "src". It is assumed that these contain binary distributions
  541. which can be installed by just doing a "make install" in the respective directory.
  542. */
  543. void list_binaries(char *package)
  544. {
  545. char tmp[MAXSTR];
  546. struct stat buf;
  547. DIR *dir;
  548. struct dirent *dir_entry;
  549. int n_dirs = 0;
  550. fprintf(stdout, "Binary installation files\n");
  551. dir = opendir(package);
  552. if (dir == NULL) {
  553. fprintf(stdout, " None.\n\n");
  554. return;
  555. }
  556. dir_entry = readdir(dir);
  557. while (dir_entry != NULL) {
  558. if ((strcmp(dir_entry->d_name, ".")) &&
  559. (strcmp(dir_entry->d_name, "..")) &&
  560. (strcmp(dir_entry->d_name, "src"))
  561. ) {
  562. /* check if it is a directory */
  563. sprintf(tmp, "%s/%s", package, dir_entry->d_name);
  564. stat(tmp, &buf);
  565. if (S_ISDIR(buf.st_mode)) {
  566. if (n_dirs == 0) {
  567. fprintf(stdout, " %s", dir_entry->d_name);
  568. }
  569. else {
  570. fprintf(stdout, ", %s", dir_entry->d_name);
  571. }
  572. n_dirs++;
  573. }
  574. }
  575. dir_entry = readdir(dir);
  576. }
  577. if (n_dirs == 0) {
  578. fprintf(stdout, " None.");
  579. }
  580. fprintf(stdout, "\n\n");
  581. }
  582. /*
  583. Just as dumb: checks, if a specified directory 'binaries' exists in addition to 'src'
  584. Returns 1 if so, 0 otherwise
  585. */
  586. int binaries_exist(char *package, char *binaries)
  587. {
  588. char tmp[MAXSTR];
  589. struct stat buf;
  590. DIR *dir;
  591. struct dirent *dir_entry;
  592. dir = opendir(package);
  593. if (dir == NULL) {
  594. return (0);
  595. }
  596. dir_entry = readdir(dir);
  597. while (dir_entry != NULL) {
  598. if ((strcmp(dir_entry->d_name, ".")) &&
  599. (strcmp(dir_entry->d_name, "..")) &&
  600. (strcmp(dir_entry->d_name, "src"))
  601. ) {
  602. /* check if it is a directory */
  603. sprintf(tmp, "%s/%s", package, dir_entry->d_name);
  604. stat(tmp, &buf);
  605. if (S_ISDIR(buf.st_mode)) {
  606. if (!strcmp(dir_entry->d_name, binaries)) {
  607. return (1); /* found it */
  608. }
  609. }
  610. }
  611. dir_entry = readdir(dir);
  612. }
  613. return (0);
  614. }
  615. /*
  616. Tests for a known file-extension:
  617. .tar.gz, .tgz
  618. .tar.bz2, .tbz
  619. .zip
  620. Returns:
  621. 0 = unknown (TYPE_UNKNOWN)
  622. 1 = tar file with gzip compression (TAR_GZIP)
  623. 2 = tar file with bzip2 compression (TAR_BZIP2)
  624. 3 = zip archive (ZIP)
  625. 4 = plain tar archive, uncompressed (TAR)
  626. VERY primitive!
  627. */
  628. int check_filetype(char *myfile)
  629. {
  630. if (strstr(myfile, ".tar.gz") != NULL) {
  631. return (1);
  632. }
  633. if (strstr(myfile, ".tgz") != NULL) {
  634. return (1);
  635. }
  636. if (strstr(myfile, ".tar.bz2") != NULL) {
  637. return (2);
  638. }
  639. if (strstr(myfile, ".tbz") != NULL) {
  640. return (2);
  641. }
  642. if (strstr(myfile, ".zip") != NULL) {
  643. return (3);
  644. }
  645. if (strstr(myfile, ".tar") != NULL) {
  646. return (4);
  647. }
  648. return (0);
  649. }
  650. /*
  651. Retrieves an extension from the WWW using wget and
  652. stores the file in the current directory.
  653. */
  654. void wget_extension(char *url)
  655. {
  656. char str[MAXSTR];
  657. int error;
  658. fprintf(stdout, "Downloading...");
  659. if (VERBOSE) {
  660. sprintf(str, "wget -N %s", url);
  661. }
  662. else {
  663. sprintf(str, "wget -N -q %s", url);
  664. }
  665. error = system(str);
  666. if (error == -1) {
  667. print_error(ERR_DOWNLOAD,
  668. "could not run 'wget' to download extension. Is it installed?\n");
  669. }
  670. if (error > 0) {
  671. print_error(ERR_DOWNLOAD, "running command '%s'.\n", str);
  672. }
  673. print_done();
  674. }
  675. /*
  676. This function checks if there is write access to the GRASS directory.
  677. If not, it aborts with an error message.
  678. Otherwise, 'cmd' is simply executed as currently running user.
  679. */
  680. void su(char *gisbase, char *cmd)
  681. {
  682. char tmpfile[MAXSTR];
  683. int error;
  684. static unsigned long next;
  685. FILE *f;
  686. /* check for permission */
  687. next = next * 1103515245 + 54321; /* generate a random file name */
  688. next = (next / 65536) % 32768;
  689. srand(next);
  690. sprintf(tmpfile, "%s/gem.test.%i", gisbase, rand());
  691. f = fopen(tmpfile, "w+");
  692. if (errno == EACCES) { /* permission denied */
  693. print_error(ERR_INSTALL_EXT,
  694. "You don't have write access to your local GRASS installation.\nPlease consult your system administrator.\n");
  695. }
  696. else {
  697. remove(tmpfile);
  698. fclose(f);
  699. error = system(cmd);
  700. if (error != 0) {
  701. print_error(ERR_MISSING_CMD, "could not run '%s'.\n", cmd);
  702. }
  703. }
  704. }
  705. /*
  706. Compares two version descriptions consisting of three ints each
  707. returns: -1, if major.minor.revision < major2.minor2.revision2,
  708. 0, if equal
  709. 1, if major.minor.revision > major2.minor2.revision2,
  710. */
  711. int vercmp(int major, int minor, int revision, int major2, int minor2,
  712. int revision2)
  713. {
  714. if ((major == major2) && (minor == minor2) && (revision == revision2)) {
  715. return (0);
  716. }
  717. if (major2 > major) {
  718. return (-1);
  719. }
  720. if (major2 < major) {
  721. return (1);
  722. }
  723. if (minor2 > minor) {
  724. return (-1);
  725. }
  726. if (minor2 < minor) {
  727. return (1);
  728. }
  729. if (revision2 > revision) {
  730. return (-1);
  731. }
  732. if (revision2 < revision) {
  733. return (1);
  734. }
  735. return (0);
  736. }