GRASS Programmer's Manual
6.4.2(2012)
|
00001 00002 /*************************************************************************** 00003 * reg_entries.c 00004 * 00005 * Fri May 13 11:35:33 2005 00006 * Copyright 2005 User 00007 * Email 00008 ****************************************************************************/ 00009 00010 /* 00011 * This program is free software; you can redistribute it and/or modify 00012 * it under the terms of the GNU General Public License as published by 00013 * the Free Software Foundation; either version 2 of the License, or 00014 * (at your option) any later version. 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU Library General Public License for more details. 00020 * 00021 * You should have received a copy of the GNU General Public License 00022 * along with this program; if not, write to the Free Software 00023 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 00024 */ 00025 00026 #include <dirent.h> 00027 #include "globals.h" 00028 00029 int menu_created; 00030 00031 00032 /* 00033 Returns 1, if the string is a submenu item, 0 otherwise. 00034 Very primitive 00035 */ 00036 int is_submenu(char *item) 00037 { 00038 if (strchr(item, '[') == NULL) { 00039 return (0); 00040 } 00041 if (strrchr(item, ']') == NULL) { 00042 return (0); 00043 } 00044 if (strchr(item, '[') > strrchr(item, ']')) { 00045 return (0); 00046 } 00047 return (1); 00048 } 00049 00050 00051 /* 00052 If "Extensions" menu does not yet exist, it will be created immediately 00053 to the left of the "Help" menu in GIS Manager's main menu bar. 00054 Returns the line nr after which the "Extension" menu entries should be 00055 inserted. 00056 */ 00057 int check_ext_menu(char **tcl_lines) 00058 { 00059 int idx; 00060 00061 /* check if "Extensions" menu exists */ 00062 idx = find_pos("\"&Xtns\" all options 1", tcl_lines, 0); 00063 if (idx == -1) { /* does not exist: create a new one */ 00064 idx = find_pos("\"&Help\" all options", tcl_lines, 0); 00065 if (idx == -1) { /* Help menu does not exist: place at far right */ 00066 idx = find_pos("}]", tcl_lines, 0); 00067 if (idx == -1) { 00068 print_error(ERR_REGISTER_ENTRIES_GISMAN, 00069 "could not parse 'menu.tcl'.\n"); 00070 } 00071 insert_str(" \"&Xtns\" all options 1 {\n", idx, tcl_lines); 00072 idx++; 00073 insert_str(" }\n", idx, tcl_lines); 00074 return (idx); 00075 } 00076 insert_str(" \"&Xtns\" all options 1 {\n", idx, tcl_lines); 00077 idx++; 00078 insert_str(" }\n", idx, tcl_lines); 00079 } 00080 return (idx); 00081 } 00082 00083 00084 /* 00085 Creates a new submenu for this extension under "Extensions" in GIS Managers 00086 main menu bar. 00087 Returns line no. of submenu, after which additional entries should be appended 00088 to menu.tcl. 00089 */ 00090 int new_submenu(char *pkg_short_name, char *menu, char **tcl_lines) 00091 { 00092 char tmp[MAXSTR]; 00093 char tmp2[MAXSTR]; 00094 char searchstr[MAXSTR]; 00095 int idx, idx2; 00096 int insert_here; 00097 int last; 00098 char *first_quote; 00099 char *second_quote; 00100 int len; 00101 int terminator; 00102 00103 /* Store the position of the "Extensions" entry and start looking for submenu from there */ 00104 idx = find_pos("\"&Xtns\" all options", tcl_lines, 0); 00105 last = find_pos("\" all options", tcl_lines, idx + 1) - 1; /* find end of "Extensions" menu */ 00106 if (last == -1) { 00107 last = find_pos("}]", tcl_lines, 0); /* end of menu.tcl */ 00108 } 00109 00110 /* check if the line is a valid submenu specifier */ 00111 if (!is_submenu(menu)) { 00112 print_warning 00113 ("first line not a submenu specifier in 'entries-gisman'.\n"); 00114 return (-1); 00115 } 00116 else { 00117 /* check if a submenu with this name does already exist */ 00118 len = (strrchr(menu, ']') - strchr(menu, '[')) / sizeof(char); 00119 strncpy(tmp, strchr(menu, '[') + sizeof(char), len); 00120 tmp[len - 1] = '\0'; /* get rid of [] */ 00121 sprintf(searchstr, "{cascad \"%s\"", tmp); /* this is what we need to look for */ 00122 00123 idx2 = find_pos(searchstr, tcl_lines, idx); 00124 if ((idx2 != -1) && (idx2 < last)) { 00125 print_warning("submenu '%s' exists in GIS Manager's Xtns menu.\n", 00126 tmp); 00127 return (-1); 00128 } 00129 00130 /* ELSE: create a new submenu in the right place */ 00131 insert_here = idx + 1; /* by default: place submenu in first line after "Extensions" menu */ 00132 idx2 = find_pos("{cascad ", tcl_lines, idx); /* go through all submenus in "Extensions" */ 00133 while ((idx2 != -1) && (idx2 < last)) { 00134 /* check for alphabetical order */ 00135 first_quote = strchr(tcl_lines[idx2], '\"'); /* get name of submenu w/o quotation marks */ 00136 second_quote = strchr(first_quote + sizeof(char), '\"'); 00137 len = (second_quote - first_quote) / sizeof(char); 00138 strncpy(tmp2, first_quote + sizeof(char), len); 00139 tmp2[len - 1] = '\0'; /* get rid of "" */ 00140 if (strcmp(tmp, tmp2) < 0) { 00141 insert_here = idx2; 00142 break; 00143 } 00144 idx++; 00145 idx2 = find_pos("{cascad ", tcl_lines, idx); 00146 } 00147 00148 /* create new submenu and return line no in menu.tcl for insertion of entries */ 00149 sprintf(tmp, " \t\t\t%s {} \"\" 1 {\n", searchstr); 00150 insert_str(tmp, insert_here, tcl_lines); 00151 insert_str(" \t\t\t}}\n", insert_here + 1, tcl_lines); 00152 00153 /* create an uninstall entry in menu.tcl */ 00154 terminator = find_pos("}]", tcl_lines, 0); 00155 /* this is just a comment that tells the uninstall function which submenu to remove */ 00156 sprintf(tmp, "#(DO_NOT_REMOVE_THIS_COMMENT) <%s> %s {} \"\" 1 {\n", 00157 pkg_short_name, searchstr); 00158 insert_str(tmp, terminator + 1, tcl_lines); 00159 00160 /* return next line for insertion of menu entries and commands! */ 00161 return (insert_here + 1); 00162 } 00163 00164 return (-1); 00165 } 00166 00167 00168 /* 00169 Inserts a new menu entry into the extension's own submenu under "Extensions". 00170 Returns the line number in menu.tcl after which the next entry should be 00171 inserted. 00172 */ 00173 int new_item(char *item, char *menu, char **tcl_lines, int line_no) 00174 { 00175 char *token; 00176 int num_tokens; 00177 char entry[MAXSTR]; 00178 char command[MAXSTR]; 00179 char tmp[MAXSTR]; 00180 00181 00182 /* remove dangling white spaces and EOL chars */ 00183 chop(item); 00184 00185 token = strtok(item, ";"); 00186 if (token == NULL) { 00187 print_warning("invalid token in 'entries-gisman'.\n"); 00188 return (-1); 00189 } 00190 00191 strcpy(entry, token); /* get menu entry string */ 00192 00193 num_tokens = 0; 00194 while (token != NULL) { 00195 token = strtok(NULL, ";"); 00196 if (token != NULL) { 00197 strcpy(command, token); /* get command string */ 00198 } 00199 num_tokens++; 00200 } 00201 00202 if (num_tokens > 2) { 00203 print_warning("invalid number of tokens (%i) in 'entries-gisman'.\n", 00204 num_tokens); 00205 return (-1); 00206 } 00207 00208 /* just a separator or a 'real' menu entry? */ 00209 if ((!strcmp(entry, "-")) && (!strcmp(entry, "-"))) { 00210 sprintf(tmp, " \t\t\t {separator}\n"); 00211 } 00212 else { 00213 sprintf(tmp, " \t\t\t {command \"%s\" {} \"%s\" {} -command {%s }}\n", 00214 entry, command, command); 00215 } 00216 insert_str(tmp, line_no, tcl_lines); 00217 00218 /* return line no. for next entry */ 00219 line_no++; 00220 return (line_no); 00221 } 00222 00223 00224 /* 00225 Checks if there are any entries in entries-gisman. 00226 Reads GISBASE/etc/dm/menu.tcl into an array of strings. 00227 Adds a new item "Extensions" to the menu bar, if it is missing. 00228 Adds new submenus and menu items to the GIS manager, as stated in entries-gisman 00229 Writes the new menu structure to a temporary file which will then be installed 00230 using the 'su' function. 00231 */ 00232 void register_entries_gisman(char *pkg_short_name, char *gisbase) 00233 { 00234 00235 char file[MAXSTR]; 00236 char str[MAXSTR]; 00237 char menu[MAXSTR]; 00238 int len; 00239 char **line; 00240 int n_entries, n_lines, i; 00241 int n_lines_org, n_lines_new; 00242 int line_no; 00243 FILE *f_gisman, *f_in, *f_out; 00244 00245 /* check if entries-gisman exists and is readable */ 00246 sprintf(file, "../entries-gisman"); 00247 f_gisman = fopen(file, "r"); 00248 if (f_gisman == NULL) { 00249 if (errno == ENOENT) { 00250 /* file does not exist */ 00251 return; 00252 } 00253 else { 00254 /* sth. strange happened */ 00255 fclose(f_gisman); 00256 print_error(ERR_REGISTER_ENTRIES_GISMAN, 00257 "checking for file '%s': %s\n", file, 00258 strerror(errno)); 00259 } 00260 } 00261 00262 /* check if menu.tcl exists and is readable */ 00263 sprintf(file, "%s/etc/dm/menu.tcl", gisbase); 00264 f_in = fopen(file, "r"); 00265 if (f_in == NULL) { 00266 if (errno == ENOENT) { 00267 /* file does not exist */ 00268 return; 00269 } 00270 else { 00271 /* sth. strange happened */ 00272 fclose(f_in); 00273 print_error(ERR_REGISTER_ENTRIES_GISMAN, 00274 "checking for file '%s': %s\n", file, 00275 strerror(errno)); 00276 } 00277 } 00278 00279 /* create a temporary menu.tcl file for write access */ 00280 /* TODO: Do not hardcode temp paths */ 00281 strcpy(TMP_GISMAN, "/tmp/grass.extensions.db.XXXXXX"); /* TMP_GISMAN is a global variable */ 00282 mkstemp(TMP_GISMAN); 00283 00284 f_out = fopen(TMP_GISMAN, "w+"); 00285 if (f_out == NULL) { 00286 print_error(ERR_REGISTER_ENTRIES_GISMAN, 00287 "could not create temp file '%s': %s\n \ 00288 Make sure that directory /tmp exists on your system and you have write permission.\n", TMP_GISMAN, strerror(errno)); 00289 } 00290 atexit(&exit_db); /* now need to register an at exit func to remove tmpdb automatically! */ 00291 00292 /* everything fine: create a shell command to install gisman-entries and modified menu.tcl */ 00293 /* this also creates a backup-copy of menu.tcl */ 00294 if (VERBOSE) { 00295 sprintf(str, 00296 "mkdir --verbose %s/etc/dm/gem-entries ; cp -vf ../entries-gisman %s/etc/dm/gem-entries/%s ; \ 00297 cp -vf %s/etc/dm/menu.tcl %s/etc/dm/menu.tcl.gem.bak ; \ 00298 cp -vf %s %s/etc/dm/menu.tcl ; chmod -v a+r %s/etc/dm/menu.tcl ;", 00299 gisbase, gisbase, pkg_short_name, gisbase, gisbase, TMP_GISMAN, gisbase, gisbase); 00300 } 00301 else { 00302 sprintf(str, 00303 "mkdir %s/etc/dm/gem-entries &> %s ; cp -f ../entries-gisman %s/etc/dm/gem-entries/%s &> %s ; \ 00304 cp -f %s/etc/dm/menu.tcl %s/etc/dm/menu.tcl.gem.bak &> %s ; \ 00305 cp -f %s %s/etc/dm/menu.tcl &> %s ; chmod a+r %s/etc/dm/menu.tcl &> %s ;", 00306 gisbase, TMP_NULL, gisbase, pkg_short_name, TMP_NULL, gisbase, gisbase, TMP_NULL, TMP_GISMAN, gisbase, TMP_NULL, gisbase, TMP_NULL); 00307 } 00308 strcpy(GISMAN_CMD, str); 00309 00310 /* count number of lines in entries-gisman */ 00311 n_entries = 0; 00312 while (fgets(str, MAXSTR, f_gisman) != NULL) { 00313 n_entries++; 00314 } 00315 if (n_entries == 0) { 00316 return; 00317 } 00318 rewind(f_gisman); 00319 00320 /* count number of lines in menu.tcl */ 00321 n_lines = 0; 00322 while (fgets(str, MAXSTR, f_in) != NULL) { 00323 n_lines++; 00324 } 00325 if (n_lines == 0) { 00326 return; 00327 } 00328 n_lines_org = n_lines; 00329 rewind(f_in); 00330 00331 /* create an array large enough to hold all lines in menu.tcl */ 00332 /* plus the entries that are to be added from entries-gisman */ 00333 /* plus one NULL terminator */ 00334 /* and copy all lines from menu.tcl into this */ 00335 line = (char **)calloc(n_lines + (n_entries * 2) + 6, sizeof(char *)); 00336 for (i = 0; i < (n_lines + (n_entries * 2) + 6); i++) { 00337 line[i] = NULL; 00338 } 00339 i = 0; 00340 while (fgets(str, MAXSTR, f_in) != NULL) { 00341 line[i] = (char *)malloc((1 + strlen(str)) * sizeof(char)); 00342 strcpy(line[i], str); 00343 i++; 00344 } 00345 00346 check_ext_menu(line); /* create "Extensions" menu if necessary */ 00347 00348 /* read all lines from entries-gisman and add to menus */ 00349 i = 1; 00350 while (nc_fgets_nb(str, MAXSTR, f_gisman) != NULL) { 00351 if (i == 1) { 00352 /* store name of menu item */ 00353 len = (strrchr(str, ']') - strchr(str, '[')) / sizeof(char); 00354 strncpy(menu, strchr(str, '[') + sizeof(char), len); 00355 menu[len - 1] = '\0'; /* get rid of [] */ 00356 line_no = new_submenu(pkg_short_name, str, line); 00357 if (line_no < 0) { 00358 print_warning("no GIS Manager menu entries created.\n"); 00359 break; 00360 } 00361 i++; 00362 } 00363 else { 00364 line_no = new_item(str, menu, line, line_no); 00365 if (line_no < 0) { 00366 print_warning("error creating GIS Manager menu entries.\n"); 00367 break; 00368 } 00369 i++; 00370 } 00371 } 00372 00373 /* write output to tmpfile */ 00374 i = 0; 00375 while (line[i] != NULL) { 00376 fprintf(f_out, line[i]); 00377 i++; 00378 } 00379 fflush(f_out); 00380 00381 /* check for accidental corruption of menu.tcl: if tmpfile has less lines than installed 00382 menu.tcl, we did sth. wrong and should leave the orginal file untouched! */ 00383 rewind(f_out); 00384 n_lines_new = 0; 00385 while (fgets(str, MAXSTR, f_out) != NULL) { 00386 n_lines_new++; 00387 } 00388 if ((n_lines_new == 0) || (n_lines_new < n_lines_org)) { 00389 print_warning 00390 ("file truncation detected. Retaining orginal file 'menu.tcl'.\n"); 00391 strcpy(GISMAN_CMD, ""); 00392 } 00393 00394 /* close files */ 00395 fclose(f_in); 00396 fclose(f_gisman); 00397 fclose(f_out); 00398 00399 /* free memory */ 00400 for (i = 0; i < (n_lines + (n_entries * 2) + 6); i++) { 00401 free(line[i]); 00402 } 00403 free(line); 00404 } 00405 00406 00407 /* 00408 This version is for Michael Barton's new version of the GIS Manager (gis.m) 00409 It is much simpler and more flexible, because gis.m can build menus 00410 from files at runtime. 00411 All we have to do is make sure there is a folder 'Xtns' in $GISBASE/etc/gm 00412 and we copy 'entries-gisman2' (if provided) into that folder using a 00413 filename 'extension name'.gem! 00414 */ 00415 void register_entries_gisman2(char *pkg_short_name, char *gisbase) 00416 { 00417 char file[MAXSTR]; 00418 FILE *f_gisman2; 00419 char str[MAXSTR]; 00420 00421 /* check if entries-gisman2 exists and is readable */ 00422 sprintf(file, "../entries-gisman2"); 00423 f_gisman2 = fopen(file, "r"); 00424 if (f_gisman2 == NULL) { 00425 if (errno == ENOENT) { 00426 /* file does not exist */ 00427 return; 00428 } 00429 else { 00430 /* sth. strange happened */ 00431 fclose(f_gisman2); 00432 print_error(ERR_REGISTER_ENTRIES_GISMAN2, 00433 "checking for file '%s': %s\n", file, 00434 strerror(errno)); 00435 } 00436 } 00437 00438 /* let's just blindly create an 'Xtns' dir: if it exists already: no problem */ 00439 /* and then copy file into it! */ 00440 if (VERBOSE) { 00441 sprintf(str, 00442 "mkdir --verbose -p %s/etc/gm/Xtns ; cp -fv ../entries-gisman2 %s/etc/gm/Xtns/%s.gem ; ", 00443 gisbase, gisbase, pkg_short_name); 00444 } 00445 else { 00446 sprintf(str, 00447 "mkdir -p %s/etc/gm/Xtns ; cp -f ../entries-gisman2 %s/etc/gm/Xtns/%s.gem ; ", 00448 gisbase, gisbase, pkg_short_name); 00449 } 00450 strcpy(GISMAN2_CMD, str); 00451 } 00452 00453 00454 /* 00455 Checks for a comment left by the new_submenu () function in menu.tcl. 00456 If it exists, the submenu specified in that comment will be removed along 00457 with all its entries. 00458 Returns -1 on failure, number of removed entries otherwise. 00459 If no more submenu entries exist, this will also remove the "Xtns" menu. 00460 */ 00461 int deregister_entries_gisman(char *pkg_short_name, char *gisbase) 00462 { 00463 char file[MAXSTR]; 00464 char str[MAXSTR]; 00465 char tmp[MAXSTR]; 00466 char **line; 00467 int n_lines, i; 00468 int n_lines_org, n_lines_new; 00469 FILE *f_in, *f_out; 00470 int pos; 00471 int start, end; 00472 int start_sub, end_sub; 00473 char *lq, *rq; 00474 int num_removed; 00475 00476 /* check if menu.tcl exists and is readable */ 00477 sprintf(file, "%s/etc/dm/menu.tcl", gisbase); 00478 f_in = fopen(file, "r"); 00479 if (f_in == NULL) { 00480 if (errno == ENOENT) { 00481 /* file does not exist */ 00482 return (0); 00483 } 00484 else { 00485 /* sth. strange happened */ 00486 fclose(f_in); 00487 print_error(ERR_DEREGISTER_ENTRIES_GISMAN, 00488 "checking for file '%s': %s\n", file, 00489 strerror(errno)); 00490 } 00491 } 00492 00493 /* create a temporary menu.tcl file for write access */ 00494 /* TODO: Do not hardcode temp paths */ 00495 strcpy(TMP_GISMAN, "/tmp/grass.extensions.db.XXXXXX"); /* TMP_GISMAN is a global variable */ 00496 mkstemp(TMP_GISMAN); 00497 00498 f_out = fopen(TMP_GISMAN, "w+"); 00499 if (f_out == NULL) { 00500 print_error(ERR_REGISTER_ENTRIES_GISMAN, 00501 "could not create temp file '%s': %s\n \ 00502 Make sure that directory /tmp exists on your system and you have write permission.\n", TMP_GISMAN, strerror(errno)); 00503 } 00504 atexit(&exit_db); /* now need to register an at exit func to remove tmpdb automatically! */ 00505 00506 /* everything fine: create a shell command to copy modified menu.tcl on uninstall */ 00507 if (VERBOSE) { 00508 sprintf(str, "cp -vf %s/etc/dm/menu.tcl %s/etc/dm/menu.tcl.gem.bak ; \ 00509 cp -vf %s %s/etc/dm/menu.tcl ; chmod -v a+r %s/etc/dm/menu.tcl ;", gisbase, gisbase, TMP_GISMAN, gisbase, gisbase); 00510 } 00511 else { 00512 sprintf(str, 00513 "cp -f %s/etc/dm/menu.tcl %s/etc/dm/menu.tcl.gem.bak &> %s ; \ 00514 cp -f %s %s/etc/dm/menu.tcl &> %s ; chmod a+r %s/etc/dm/menu.tcl &> %s ;", gisbase, gisbase, TMP_NULL, TMP_GISMAN, gisbase, TMP_NULL, gisbase, TMP_NULL); 00515 } 00516 strcpy(GISMAN_CMD, str); 00517 00518 00519 /* count number of lines in menu.tcl */ 00520 n_lines = 0; 00521 while (fgets(str, MAXSTR, f_in) != NULL) { 00522 n_lines++; 00523 } 00524 if (n_lines == 0) { 00525 return (-1); 00526 } 00527 rewind(f_in); 00528 n_lines_org = n_lines; 00529 00530 /* create an array large enough to hold all lines in menu.tcl */ 00531 /* plus one NULL terminator */ 00532 /* and copy all lines from menu.tcl into this */ 00533 line = (char **)calloc(n_lines + 1, sizeof(char *)); 00534 for (i = 0; i < n_lines + 1; i++) { 00535 line[i] = NULL; 00536 } 00537 i = 0; 00538 while (fgets(str, MAXSTR, f_in) != NULL) { 00539 line[i] = (char *)malloc((1 + strlen(str)) * sizeof(char)); 00540 strcpy(line[i], str); 00541 i++; 00542 } 00543 00544 /* search for uninstall comment */ 00545 sprintf(str, "#(DO_NOT_REMOVE_THIS_COMMENT) <%s> {cascad", 00546 pkg_short_name); 00547 pos = find_pos(str, line, 0); 00548 if (pos == -1) { 00549 print_warning 00550 ("could not find uninstall information in 'menu.tcl'.\n"); 00551 return (-1); 00552 } 00553 00554 /* copy name of submenu to search for */ 00555 lq = strchr(line[pos], '\"'); 00556 lq++; 00557 rq = strchr(lq, '\"'); 00558 strcpy(tmp, lq); 00559 tmp[(rq - lq) / sizeof(char)] = '\0'; 00560 00561 /* now find "Xtns" menu start and end */ 00562 start = find_pos("\"&Xtns\" all options 1", line, 0); 00563 end = find_pos("\" all options", line, start + 1) - 1; 00564 if (end == -1) { 00565 end = find_pos("}]", line, 0); /* end of menu.tcl */ 00566 } 00567 00568 if (start == -1) { 00569 print_warning("menu 'Xtns' does not exist.\n"); 00570 return (-1); 00571 } 00572 00573 /* now find our submenu and set the search range to it */ 00574 sprintf(str, "{cascad \"%s\"", tmp); 00575 start_sub = find_pos(str, line, start); 00576 if ((start_sub == -1) || (start_sub > end)) { 00577 print_warning("could not find submenu entry '%s' in 'menu.tcl'.\n", 00578 tmp); 00579 return (-1); 00580 } 00581 end_sub = find_pos(" \t\t\t}}", line, start_sub); 00582 if ((end_sub == -1) || (end_sub > end)) { 00583 print_warning 00584 ("could not find end of submenu entry '%s' in 'menu.tcl'.\n", 00585 tmp); 00586 return (-1); 00587 } 00588 00589 num_removed = 0; 00590 00591 /* now kill every line in between start and end! */ 00592 for (i = 0; i < ((end_sub - start_sub) + 1); i++) { 00593 delete_str(start_sub, line); 00594 num_removed++; 00595 } 00596 00597 /* now kill the uninstall comment */ 00598 sprintf(str, "#(DO_NOT_REMOVE_THIS_COMMENT) <%s> {cascad", 00599 pkg_short_name); 00600 pos = find_pos(str, line, 0); 00601 delete_str(pos, line); 00602 num_removed++; 00603 00604 /* check if there are any submenus left in "Xtns" and if not: remove Xtns menu */ 00605 start = find_pos("\"&Xtns\" all options 1", line, 0); 00606 end = find_pos("\" all options", line, start + 1) - 1; 00607 if (end - start < 3) { 00608 for (i = 0; i < ((end - start) + 1); i++) { 00609 delete_str(start, line); 00610 num_removed++; 00611 } 00612 } 00613 00614 /* write output to tmpfile */ 00615 i = 0; 00616 while (line[i] != NULL) { 00617 fprintf(f_out, line[i]); 00618 i++; 00619 } 00620 fflush(f_out); 00621 00622 /* check for accidental corruption of menu.tcl: if tmpfile is empty (=0 lines), 00623 we did sth. wrong and should leave the orginal file untouched! */ 00624 rewind(f_out); 00625 n_lines_new = 0; 00626 while (fgets(str, MAXSTR, f_out) != NULL) { 00627 n_lines_new++; 00628 } 00629 if ((n_lines_new == 0)) { 00630 print_warning 00631 ("file truncation detected. Retaining orginal file 'menu.tcl'.\n"); 00632 strcpy(GISMAN_CMD, ""); 00633 } 00634 00635 /* close files */ 00636 fclose(f_in); 00637 fclose(f_out); 00638 00639 /* free memory */ 00640 for (i = 0; i < n_lines + 1; i++) { 00641 free(line[i]); 00642 } 00643 free(line); 00644 00645 return (num_removed); 00646 } 00647 00648 00649 /* 00650 This version is for Michael Barton's new GIS Manager. 00651 In this case, all we have to do is delete the .gem file! 00652 */ 00653 void deregister_entries_gisman2(char *pkg_short_name, char *gisbase) 00654 { 00655 char file[MAXSTR]; 00656 FILE *f_gisman2; 00657 char str[MAXSTR]; 00658 00659 /* check if entries-gisman2 exists and is readable */ 00660 sprintf(file, "%s/etc/gm/Xtns/%s.gem", gisbase, pkg_short_name); 00661 f_gisman2 = fopen(file, "r"); 00662 if (f_gisman2 == NULL) { 00663 if (errno == ENOENT) { 00664 /* file does not exist */ 00665 return; 00666 } 00667 else { 00668 /* sth. strange happened */ 00669 fclose(f_gisman2); 00670 print_error(ERR_DEREGISTER_ENTRIES_GISMAN2, 00671 "checking for file '%s': %s\n", file, 00672 strerror(errno)); 00673 } 00674 } 00675 00676 if (VERBOSE) { 00677 sprintf(str, "rm -vf %s/etc/gm/Xtns/%s.gem ; ", 00678 gisbase, pkg_short_name); 00679 } 00680 else { 00681 sprintf(str, "rm -f %s/etc/gm/Xtns/%s.gem ; ", 00682 gisbase, pkg_short_name); 00683 00684 } 00685 strcpy(GISMAN_CMD, str); 00686 } 00687 00688 00689 /* 00690 Returns number of restored entries 00691 */ 00692 int restore_entries_gisman(char *gisbase) 00693 { 00694 char str[MAXSTR]; 00695 char menu[MAXSTR]; 00696 char file[MAXSTR]; 00697 char dir[MAXSTR]; 00698 char pkg_short_name[MAXSTR]; 00699 int len; 00700 char **line; 00701 int n_entries, n_lines, i; 00702 int line_no; 00703 FILE *f_gisman, *f_in, *f_out; 00704 DIR *dirp; 00705 struct dirent *ep; 00706 int num_restored; 00707 int n_files; 00708 00709 /* check if menu.tcl exists and is readable */ 00710 sprintf(file, "%s/etc/dm/menu.tcl", gisbase); 00711 f_in = fopen(file, "r"); 00712 if (f_in == NULL) { 00713 if (errno == ENOENT) { 00714 /* file does not exist */ 00715 return (0); 00716 } 00717 else { 00718 /* sth. strange happened */ 00719 fclose(f_in); 00720 print_error(ERR_REGISTER_ENTRIES_GISMAN, 00721 "checking for file '%s': %s\n", file, 00722 strerror(errno)); 00723 } 00724 } 00725 00726 /* create a temporary menu.tcl file for write access */ 00727 /* TODO: Do not hardcode temp paths */ 00728 strcpy(TMP_GISMAN, "/tmp/grass.extensions.db.XXXXXX"); /* TMP_GISMAN is a global variable */ 00729 mkstemp(TMP_GISMAN); 00730 00731 f_out = fopen(TMP_GISMAN, "w+"); 00732 if (f_out == NULL) { 00733 print_error(ERR_REGISTER_ENTRIES_GISMAN, 00734 "could not create temp file '%s': %s\n \ 00735 Make sure that directory /tmp exists on your system and you have write permission.\n", TMP_GISMAN, strerror(errno)); 00736 } 00737 atexit(&exit_db); /* now need to register an at exit func to remove tmpdb automatically! */ 00738 00739 /* everything fine: create a shell command to copy modified menu.tcl on uninstall */ 00740 if (VERBOSE) { 00741 sprintf(str, "cp -vf %s/etc/dm/menu.tcl %s/etc/dm/menu.tcl.gem.bak ; \ 00742 cp -vf %s %s/etc/dm/menu.tcl ; chmod -v a+r %s/etc/dm/menu.tcl ;", gisbase, gisbase, TMP_GISMAN, gisbase, gisbase); 00743 } 00744 else { 00745 sprintf(str, 00746 "cp -f %s/etc/dm/menu.tcl %s/etc/dm/menu.tcl.gem.bak &> %s ; \ 00747 cp -f %s %s/etc/dm/menu.tcl &> %s ; chmod a+r %s/etc/dm/menu.tcl &> %s ;", gisbase, gisbase, TMP_NULL, TMP_GISMAN, gisbase, TMP_NULL, gisbase, TMP_NULL); 00748 } 00749 strcpy(GISMAN_CMD, str); 00750 00751 /* allocate a pointer to the directory structure */ 00752 sprintf(dir, "%s/etc/dm/gem-entries", gisbase); 00753 dirp = opendir(dir); 00754 if (dirp == NULL) { 00755 /* directory does not exist or is not accessible */ 00756 return (0); 00757 } 00758 00759 /* PASS 1 */ 00760 /* open all files in gem-entries and count the number of lines each has */ 00761 n_entries = 0; 00762 n_files = 0; 00763 while ((ep = readdir(dirp))) { 00764 sprintf(file, "%s/%s", dir, ep->d_name); 00765 f_gisman = fopen(file, "r"); 00766 if ((!strcmp(ep->d_name, ".")) || (!strcmp(ep->d_name, ".."))) { 00767 fclose(f_gisman); 00768 continue; 00769 } 00770 if (f_gisman == NULL) { 00771 fclose(f_gisman); 00772 continue; 00773 } 00774 /* count number of lines in file */ 00775 while (fgets(str, MAXSTR, f_gisman) != NULL) { 00776 n_entries++; 00777 } 00778 n_files++; 00779 fclose(f_gisman); 00780 } 00781 closedir(dirp); 00782 00783 /* count number of lines in menu.tcl */ 00784 n_lines = 0; 00785 while (fgets(str, MAXSTR, f_in) != NULL) { 00786 n_lines++; 00787 } 00788 if (n_lines == 0) { 00789 return (0); 00790 } 00791 rewind(f_in); 00792 00793 /* create an array large enough to hold all lines in menu.tcl */ 00794 /* plus the entries that are to be added from the files in gem-entries/ */ 00795 /* plus space for uninstall comments */ 00796 /* plus one NULL terminator */ 00797 /* and copy all lines from menu.tcl into this */ 00798 line = 00799 (char **)calloc(n_lines + (n_entries * 2) + (n_files * 5) + 1, 00800 sizeof(char *)); 00801 for (i = 0; i < (n_lines + (n_entries * 2) + (n_files * 5) + 1); i++) { 00802 line[i] = NULL; 00803 } 00804 i = 0; 00805 while (fgets(str, MAXSTR, f_in) != NULL) { 00806 line[i] = (char *)malloc((1 + strlen(str)) * sizeof(char)); 00807 strcpy(line[i], str); 00808 i++; 00809 } 00810 line[i] = NULL; /* add NULL terminator */ 00811 00812 check_ext_menu(line); /* create "Extensions" menu if necessary */ 00813 00814 /* PASS 2: re-create submenus and all menu items if necessary */ 00815 dirp = opendir(dir); 00816 num_restored = 0; 00817 while ((ep = readdir(dirp))) { 00818 sprintf(file, "%s/%s", dir, ep->d_name); 00819 if ((!strcmp(ep->d_name, ".")) || (!strcmp(ep->d_name, ".."))) { 00820 continue; 00821 } 00822 f_gisman = fopen(file, "r"); 00823 if (f_gisman == NULL) { 00824 continue; 00825 } 00826 /* read all lines from entries-gisman and add to menus */ 00827 i = 1; 00828 while (nc_fgets_nb(str, MAXSTR, f_gisman) != NULL) { 00829 if (i == 1) { 00830 /* store name of menu item */ 00831 len = (strrchr(str, ']') - strchr(str, '[')) / sizeof(char); 00832 strncpy(menu, strchr(str, '[') + sizeof(char), len); 00833 menu[len - 1] = '\0'; /* get rid of [] */ 00834 line_no = new_submenu(pkg_short_name, str, line); 00835 if (line_no < 0) { 00836 break; 00837 } 00838 i++; 00839 num_restored++; 00840 } 00841 else { 00842 line_no = new_item(str, menu, line, line_no); 00843 if (line_no < 0) { 00844 break; 00845 } 00846 i++; 00847 num_restored++; 00848 } 00849 } 00850 fclose(f_gisman); 00851 } 00852 closedir(dirp); 00853 00854 /* write output to tmpfile */ 00855 i = 0; 00856 while (line[i] != NULL) { 00857 fprintf(f_out, line[i]); 00858 i++; 00859 } 00860 fflush(f_out); 00861 00862 /* close remaining files */ 00863 fclose(f_in); 00864 fclose(f_out); 00865 00866 /* free memory */ 00867 for (i = 0; i < (n_lines + (n_entries * 2) + (n_files * 5) + 1); i++) { 00868 free(line[i]); 00869 } 00870 free(line); 00871 00872 return (num_restored); 00873 }