GRASS Programmer's Manual  6.4.2(2012)
reg_entries.c
Go to the documentation of this file.
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 }
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines