~ubuntu-branches/ubuntu/vivid/grass/vivid-proposed

« back to all changes in this revision

Viewing changes to gem/reg_entries.c

  • Committer: Package Import Robot
  • Author(s): Bas Couwenberg
  • Date: 2015-02-20 23:12:08 UTC
  • mfrom: (8.2.6 experimental)
  • Revision ID: package-import@ubuntu.com-20150220231208-1u6qvqm84v430b10
Tags: 7.0.0-1~exp1
* New upstream release.
* Update python-ctypes-ternary.patch to use if/else instead of and/or.
* Drop check4dev patch, rely on upstream check.
* Add build dependency on libpq-dev to grass-dev for libpq-fe.h.
* Drop patches applied upstream, refresh remaining patches.
* Update symlinks for images switched from jpg to png.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
 
2
 
/***************************************************************************
3
 
 *            reg_entries.c
4
 
 *
5
 
 *  Fri May 13 11:35:33 2005
6
 
 *  Copyright  2005  User
7
 
 *  Email
8
 
 ****************************************************************************/
9
 
 
10
 
/*
11
 
 *  This program is free software; you can redistribute it and/or modify
12
 
 *  it under the terms of the GNU General Public License as published by
13
 
 *  the Free Software Foundation; either version 2 of the License, or
14
 
 *  (at your option) any later version.
15
 
 *
16
 
 *  This program is distributed in the hope that it will be useful,
17
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
 
 *  GNU Library General Public License for more details.
20
 
 *
21
 
 *  You should have received a copy of the GNU General Public License
22
 
 *  along with this program; if not, write to the Free Software
23
 
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24
 
 */
25
 
 
26
 
#include <dirent.h>
27
 
#include "globals.h"
28
 
 
29
 
int menu_created;
30
 
 
31
 
 
32
 
 /*
33
 
    Returns 1, if the string is a submenu item, 0 otherwise.
34
 
    Very primitive
35
 
  */
36
 
int is_submenu(char *item)
37
 
{
38
 
    if (strchr(item, '[') == NULL) {
39
 
        return (0);
40
 
    }
41
 
    if (strrchr(item, ']') == NULL) {
42
 
        return (0);
43
 
    }
44
 
    if (strchr(item, '[') > strrchr(item, ']')) {
45
 
        return (0);
46
 
    }
47
 
    return (1);
48
 
}
49
 
 
50
 
 
51
 
/*
52
 
   If "Extensions" menu does not yet exist, it will be created immediately
53
 
   to the left of the "Help" menu in GIS Manager's main menu bar.
54
 
   Returns the line nr after which the "Extension" menu entries should be
55
 
   inserted.
56
 
 */
57
 
int check_ext_menu(char **tcl_lines)
58
 
{
59
 
    int idx;
60
 
 
61
 
    /* check if "Extensions" menu exists */
62
 
    idx = find_pos("\"&Xtns\" all options 1", tcl_lines, 0);
63
 
    if (idx == -1) {            /* does not exist: create a new one */
64
 
        idx = find_pos("\"&Help\" all options", tcl_lines, 0);
65
 
        if (idx == -1) {        /* Help menu does not exist: place at far right */
66
 
            idx = find_pos("}]", tcl_lines, 0);
67
 
            if (idx == -1) {
68
 
                print_error(ERR_REGISTER_ENTRIES_GISMAN,
69
 
                            "could not parse 'menu.tcl'.\n");
70
 
            }
71
 
            insert_str(" \"&Xtns\" all options 1 {\n", idx, tcl_lines);
72
 
            idx++;
73
 
            insert_str(" }\n", idx, tcl_lines);
74
 
            return (idx);
75
 
        }
76
 
        insert_str(" \"&Xtns\" all options 1 {\n", idx, tcl_lines);
77
 
        idx++;
78
 
        insert_str(" }\n", idx, tcl_lines);
79
 
    }
80
 
    return (idx);
81
 
}
82
 
 
83
 
 
84
 
 /*
85
 
    Creates a new submenu for this extension under "Extensions" in GIS Managers
86
 
    main menu bar.
87
 
    Returns line no. of submenu, after which additional entries should be appended
88
 
    to menu.tcl.
89
 
  */
90
 
int new_submenu(char *pkg_short_name, char *menu, char **tcl_lines)
91
 
{
92
 
    char tmp[MAXSTR];
93
 
    char tmp2[MAXSTR];
94
 
    char searchstr[MAXSTR];
95
 
    int idx, idx2;
96
 
    int insert_here;
97
 
    int last;
98
 
    char *first_quote;
99
 
    char *second_quote;
100
 
    int len;
101
 
    int terminator;
102
 
 
103
 
    /* Store the position of the "Extensions" entry and start looking for submenu from there */
104
 
    idx = find_pos("\"&Xtns\" all options", tcl_lines, 0);
105
 
    last = find_pos("\" all options", tcl_lines, idx + 1) - 1;  /* find end of "Extensions" menu */
106
 
    if (last == -1) {
107
 
        last = find_pos("}]", tcl_lines, 0);    /* end of menu.tcl */
108
 
    }
109
 
 
110
 
    /* check if the line is a valid submenu specifier */
111
 
    if (!is_submenu(menu)) {
112
 
        print_warning
113
 
            ("first line not a submenu specifier in 'entries-gisman'.\n");
114
 
        return (-1);
115
 
    }
116
 
    else {
117
 
        /* check if a submenu with this name does already exist */
118
 
        len = (strrchr(menu, ']') - strchr(menu, '[')) / sizeof(char);
119
 
        strncpy(tmp, strchr(menu, '[') + sizeof(char), len);
120
 
        tmp[len - 1] = '\0';    /* get rid of [] */
121
 
        sprintf(searchstr, "{cascad \"%s\"", tmp);      /* this is what we need to look for */
122
 
 
123
 
        idx2 = find_pos(searchstr, tcl_lines, idx);
124
 
        if ((idx2 != -1) && (idx2 < last)) {
125
 
            print_warning("submenu '%s' exists in GIS Manager's Xtns menu.\n",
126
 
                          tmp);
127
 
            return (-1);
128
 
        }
129
 
 
130
 
        /* ELSE: create a new submenu in the right place */
131
 
        insert_here = idx + 1;  /* by default: place submenu in first line after "Extensions" menu */
132
 
        idx2 = find_pos("{cascad ", tcl_lines, idx);    /* go through all submenus in "Extensions" */
133
 
        while ((idx2 != -1) && (idx2 < last)) {
134
 
            /* check for alphabetical order */
135
 
            first_quote = strchr(tcl_lines[idx2], '\"');        /* get name of submenu w/o quotation marks */
136
 
            second_quote = strchr(first_quote + sizeof(char), '\"');
137
 
            len = (second_quote - first_quote) / sizeof(char);
138
 
            strncpy(tmp2, first_quote + sizeof(char), len);
139
 
            tmp2[len - 1] = '\0';       /* get rid of "" */
140
 
            if (strcmp(tmp, tmp2) < 0) {
141
 
                insert_here = idx2;
142
 
                break;
143
 
            }
144
 
            idx++;
145
 
            idx2 = find_pos("{cascad ", tcl_lines, idx);
146
 
        }
147
 
 
148
 
        /* create new submenu and return line no in menu.tcl for insertion of entries */
149
 
        sprintf(tmp, " \t\t\t%s {} \"\" 1 {\n", searchstr);
150
 
        insert_str(tmp, insert_here, tcl_lines);
151
 
        insert_str(" \t\t\t}}\n", insert_here + 1, tcl_lines);
152
 
 
153
 
        /* create an uninstall entry in menu.tcl */
154
 
        terminator = find_pos("}]", tcl_lines, 0);
155
 
        /* this is just a comment that tells the uninstall function which submenu to remove */
156
 
        sprintf(tmp, "#(DO_NOT_REMOVE_THIS_COMMENT) <%s> %s {} \"\" 1 {\n",
157
 
                pkg_short_name, searchstr);
158
 
        insert_str(tmp, terminator + 1, tcl_lines);
159
 
 
160
 
        /* return next line for insertion of menu entries and commands! */
161
 
        return (insert_here + 1);
162
 
    }
163
 
 
164
 
    return (-1);
165
 
}
166
 
 
167
 
 
168
 
/*
169
 
   Inserts a new menu entry into the extension's own submenu under "Extensions".
170
 
   Returns the line number in menu.tcl after which the next entry should be
171
 
   inserted.
172
 
 */
173
 
int new_item(char *item, char *menu, char **tcl_lines, int line_no)
174
 
{
175
 
    char *token;
176
 
    int num_tokens;
177
 
    char entry[MAXSTR];
178
 
    char command[MAXSTR];
179
 
    char tmp[MAXSTR];
180
 
 
181
 
 
182
 
    /* remove dangling white spaces and EOL chars */
183
 
    chop(item);
184
 
 
185
 
    token = strtok(item, ";");
186
 
    if (token == NULL) {
187
 
        print_warning("invalid token in 'entries-gisman'.\n");
188
 
        return (-1);
189
 
    }
190
 
 
191
 
    strcpy(entry, token);       /* get menu entry string */
192
 
 
193
 
    num_tokens = 0;
194
 
    while (token != NULL) {
195
 
        token = strtok(NULL, ";");
196
 
        if (token != NULL) {
197
 
            strcpy(command, token);     /* get command string */
198
 
        }
199
 
        num_tokens++;
200
 
    }
201
 
 
202
 
    if (num_tokens > 2) {
203
 
        print_warning("invalid number of tokens (%i) in 'entries-gisman'.\n",
204
 
                      num_tokens);
205
 
        return (-1);
206
 
    }
207
 
 
208
 
    /* just a separator or a 'real' menu entry? */
209
 
    if ((!strcmp(entry, "-")) && (!strcmp(entry, "-"))) {
210
 
        sprintf(tmp, " \t\t\t {separator}\n");
211
 
    }
212
 
    else {
213
 
        sprintf(tmp, " \t\t\t {command \"%s\" {} \"%s\" {} -command {%s }}\n",
214
 
                entry, command, command);
215
 
    }
216
 
    insert_str(tmp, line_no, tcl_lines);
217
 
 
218
 
    /* return line no. for next entry */
219
 
    line_no++;
220
 
    return (line_no);
221
 
}
222
 
 
223
 
 
224
 
 /* 
225
 
    Checks if there are any entries in entries-gisman.
226
 
    Reads GISBASE/etc/dm/menu.tcl into an array of strings.
227
 
    Adds a new item "Extensions" to the menu bar, if it is missing.
228
 
    Adds new submenus and menu items to the GIS manager, as stated in entries-gisman
229
 
    Writes the new menu structure to a temporary file which will then be installed
230
 
    using the 'su' function.
231
 
  */
232
 
void register_entries_gisman(char *pkg_short_name, char *gisbase)
233
 
{
234
 
 
235
 
    char file[MAXSTR];
236
 
    char str[MAXSTR];
237
 
    char menu[MAXSTR];
238
 
    int len;
239
 
    char **line;
240
 
    int n_entries, n_lines, i;
241
 
    int n_lines_org, n_lines_new;
242
 
    int line_no;
243
 
    FILE *f_gisman, *f_in, *f_out;
244
 
 
245
 
    /* check if entries-gisman exists and is readable */
246
 
    sprintf(file, "../entries-gisman");
247
 
    f_gisman = fopen(file, "r");
248
 
    if (f_gisman == NULL) {
249
 
        if (errno == ENOENT) {
250
 
            /* file does not exist */
251
 
            return;
252
 
        }
253
 
        else {
254
 
            /* sth. strange happened */
255
 
            fclose(f_gisman);
256
 
            print_error(ERR_REGISTER_ENTRIES_GISMAN,
257
 
                        "checking for file '%s': %s\n", file,
258
 
                        strerror(errno));
259
 
        }
260
 
    }
261
 
 
262
 
    /* check if menu.tcl exists and is readable */
263
 
    sprintf(file, "%s/etc/dm/menu.tcl", gisbase);
264
 
    f_in = fopen(file, "r");
265
 
    if (f_in == NULL) {
266
 
        if (errno == ENOENT) {
267
 
            /* file does not exist */
268
 
            return;
269
 
        }
270
 
        else {
271
 
            /* sth. strange happened */
272
 
            fclose(f_in);
273
 
            print_error(ERR_REGISTER_ENTRIES_GISMAN,
274
 
                        "checking for file '%s': %s\n", file,
275
 
                        strerror(errno));
276
 
        }
277
 
    }
278
 
 
279
 
    /* create a temporary menu.tcl file for write access */
280
 
    /* TODO: Do not hardcode temp paths */
281
 
    strcpy(TMP_GISMAN, "/tmp/grass.extensions.db.XXXXXX");      /* TMP_GISMAN is a global variable */
282
 
    mkstemp(TMP_GISMAN);
283
 
 
284
 
    f_out = fopen(TMP_GISMAN, "w+");
285
 
    if (f_out == NULL) {
286
 
        print_error(ERR_REGISTER_ENTRIES_GISMAN,
287
 
                    "could not create temp file '%s': %s\n \
288
 
                        Make sure that directory /tmp exists on your system and you have write permission.\n", TMP_GISMAN, strerror(errno));
289
 
    }
290
 
    atexit(&exit_db);           /* now need to register an at exit func to remove tmpdb automatically! */
291
 
 
292
 
    /* everything fine: create a shell command to install gisman-entries and modified menu.tcl */
293
 
    /* this also creates a backup-copy of menu.tcl */
294
 
    if (VERBOSE) {
295
 
        sprintf(str,
296
 
                "mkdir --verbose %s/etc/dm/gem-entries ; cp -vf ../entries-gisman %s/etc/dm/gem-entries/%s ; \
297
 
                                        cp -vf %s/etc/dm/menu.tcl %s/etc/dm/menu.tcl.gem.bak ; \
298
 
                                        cp -vf %s %s/etc/dm/menu.tcl ; chmod -v a+r %s/etc/dm/menu.tcl ;",
299
 
                gisbase, gisbase, pkg_short_name, gisbase, gisbase, TMP_GISMAN, gisbase, gisbase);
300
 
    }
301
 
    else {
302
 
        sprintf(str,
303
 
                "mkdir %s/etc/dm/gem-entries &> %s ; cp -f ../entries-gisman %s/etc/dm/gem-entries/%s &> %s ; \
304
 
                                        cp -f %s/etc/dm/menu.tcl %s/etc/dm/menu.tcl.gem.bak &> %s ; \
305
 
                                        cp -f %s %s/etc/dm/menu.tcl &> %s ; chmod a+r %s/etc/dm/menu.tcl &> %s ;",
306
 
                gisbase, TMP_NULL, gisbase, pkg_short_name, TMP_NULL, gisbase, gisbase, TMP_NULL, TMP_GISMAN, gisbase, TMP_NULL, gisbase, TMP_NULL);
307
 
    }
308
 
    strcpy(GISMAN_CMD, str);
309
 
 
310
 
    /* count number of lines in entries-gisman */
311
 
    n_entries = 0;
312
 
    while (fgets(str, MAXSTR, f_gisman) != NULL) {
313
 
        n_entries++;
314
 
    }
315
 
    if (n_entries == 0) {
316
 
        return;
317
 
    }
318
 
    rewind(f_gisman);
319
 
 
320
 
    /* count number of lines in menu.tcl */
321
 
    n_lines = 0;
322
 
    while (fgets(str, MAXSTR, f_in) != NULL) {
323
 
        n_lines++;
324
 
    }
325
 
    if (n_lines == 0) {
326
 
        return;
327
 
    }
328
 
    n_lines_org = n_lines;
329
 
    rewind(f_in);
330
 
 
331
 
    /* create an array large enough to hold all lines in menu.tcl */
332
 
    /* plus the entries that are to be added from entries-gisman */
333
 
    /* plus one NULL terminator */
334
 
    /* and copy all lines from menu.tcl into this */
335
 
    line = (char **)calloc(n_lines + (n_entries * 2) + 6, sizeof(char *));
336
 
    for (i = 0; i < (n_lines + (n_entries * 2) + 6); i++) {
337
 
        line[i] = NULL;
338
 
    }
339
 
    i = 0;
340
 
    while (fgets(str, MAXSTR, f_in) != NULL) {
341
 
        line[i] = (char *)malloc((1 + strlen(str)) * sizeof(char));
342
 
        strcpy(line[i], str);
343
 
        i++;
344
 
    }
345
 
 
346
 
    check_ext_menu(line);       /* create "Extensions" menu if necessary */
347
 
 
348
 
    /* read all lines from entries-gisman and add to menus */
349
 
    i = 1;
350
 
    while (nc_fgets_nb(str, MAXSTR, f_gisman) != NULL) {
351
 
        if (i == 1) {
352
 
            /* store name of menu item */
353
 
            len = (strrchr(str, ']') - strchr(str, '[')) / sizeof(char);
354
 
            strncpy(menu, strchr(str, '[') + sizeof(char), len);
355
 
            menu[len - 1] = '\0';       /* get rid of [] */
356
 
            line_no = new_submenu(pkg_short_name, str, line);
357
 
            if (line_no < 0) {
358
 
                print_warning("no GIS Manager menu entries created.\n");
359
 
                break;
360
 
            }
361
 
            i++;
362
 
        }
363
 
        else {
364
 
            line_no = new_item(str, menu, line, line_no);
365
 
            if (line_no < 0) {
366
 
                print_warning("error creating GIS Manager menu entries.\n");
367
 
                break;
368
 
            }
369
 
            i++;
370
 
        }
371
 
    }
372
 
 
373
 
    /* write output to tmpfile */
374
 
    i = 0;
375
 
    while (line[i] != NULL) {
376
 
        fprintf(f_out, line[i]);
377
 
        i++;
378
 
    }
379
 
    fflush(f_out);
380
 
 
381
 
    /* check for accidental corruption of menu.tcl: if tmpfile has less lines than installed
382
 
       menu.tcl, we did sth. wrong and should leave the orginal file untouched! */
383
 
    rewind(f_out);
384
 
    n_lines_new = 0;
385
 
    while (fgets(str, MAXSTR, f_out) != NULL) {
386
 
        n_lines_new++;
387
 
    }
388
 
    if ((n_lines_new == 0) || (n_lines_new < n_lines_org)) {
389
 
        print_warning
390
 
            ("file truncation detected. Retaining orginal file 'menu.tcl'.\n");
391
 
        strcpy(GISMAN_CMD, "");
392
 
    }
393
 
 
394
 
    /* close files */
395
 
    fclose(f_in);
396
 
    fclose(f_gisman);
397
 
    fclose(f_out);
398
 
 
399
 
    /* free memory */
400
 
    for (i = 0; i < (n_lines + (n_entries * 2) + 6); i++) {
401
 
        free(line[i]);
402
 
    }
403
 
    free(line);
404
 
}
405
 
 
406
 
 
407
 
/*
408
 
   This version is for Michael Barton's new version of the GIS Manager (gis.m)
409
 
   It is much simpler and more flexible, because gis.m can build menus
410
 
   from files at runtime.
411
 
   All we have to do is make sure there is a folder 'Xtns' in $GISBASE/etc/gm
412
 
   and we copy 'entries-gisman2' (if provided) into that folder using a
413
 
   filename 'extension name'.gem!
414
 
 */
415
 
void register_entries_gisman2(char *pkg_short_name, char *gisbase)
416
 
{
417
 
    char file[MAXSTR];
418
 
    FILE *f_gisman2;
419
 
    char str[MAXSTR];
420
 
 
421
 
    /* check if entries-gisman2 exists and is readable */
422
 
    sprintf(file, "../entries-gisman2");
423
 
    f_gisman2 = fopen(file, "r");
424
 
    if (f_gisman2 == NULL) {
425
 
        if (errno == ENOENT) {
426
 
            /* file does not exist */
427
 
            return;
428
 
        }
429
 
        else {
430
 
            /* sth. strange happened */
431
 
            fclose(f_gisman2);
432
 
            print_error(ERR_REGISTER_ENTRIES_GISMAN2,
433
 
                        "checking for file '%s': %s\n", file,
434
 
                        strerror(errno));
435
 
        }
436
 
    }
437
 
 
438
 
    /* let's just blindly create an 'Xtns' dir: if it exists already: no problem */
439
 
    /* and then copy file into it! */
440
 
    if (VERBOSE) {
441
 
        sprintf(str,
442
 
                "mkdir --verbose -p %s/etc/gm/Xtns ; cp -fv ../entries-gisman2 %s/etc/gm/Xtns/%s.gem ; ",
443
 
                gisbase, gisbase, pkg_short_name);
444
 
    }
445
 
    else {
446
 
        sprintf(str,
447
 
                "mkdir -p %s/etc/gm/Xtns ; cp -f ../entries-gisman2 %s/etc/gm/Xtns/%s.gem ; ",
448
 
                gisbase, gisbase, pkg_short_name);
449
 
    }
450
 
    strcpy(GISMAN2_CMD, str);
451
 
}
452
 
 
453
 
 
454
 
/*
455
 
   Checks for a comment left by the new_submenu () function in menu.tcl.        
456
 
   If it exists, the submenu specified in that comment will be removed along
457
 
   with all its entries.
458
 
   Returns -1 on failure, number of removed entries otherwise.
459
 
   If no more submenu entries exist, this will also remove the "Xtns" menu.
460
 
 */
461
 
int deregister_entries_gisman(char *pkg_short_name, char *gisbase)
462
 
{
463
 
    char file[MAXSTR];
464
 
    char str[MAXSTR];
465
 
    char tmp[MAXSTR];
466
 
    char **line;
467
 
    int n_lines, i;
468
 
    int n_lines_org, n_lines_new;
469
 
    FILE *f_in, *f_out;
470
 
    int pos;
471
 
    int start, end;
472
 
    int start_sub, end_sub;
473
 
    char *lq, *rq;
474
 
    int num_removed;
475
 
 
476
 
    /* check if menu.tcl exists and is readable */
477
 
    sprintf(file, "%s/etc/dm/menu.tcl", gisbase);
478
 
    f_in = fopen(file, "r");
479
 
    if (f_in == NULL) {
480
 
        if (errno == ENOENT) {
481
 
            /* file does not exist */
482
 
            return (0);
483
 
        }
484
 
        else {
485
 
            /* sth. strange happened */
486
 
            fclose(f_in);
487
 
            print_error(ERR_DEREGISTER_ENTRIES_GISMAN,
488
 
                        "checking for file '%s': %s\n", file,
489
 
                        strerror(errno));
490
 
        }
491
 
    }
492
 
 
493
 
    /* create a temporary menu.tcl file for write access */
494
 
    /* TODO: Do not hardcode temp paths */
495
 
    strcpy(TMP_GISMAN, "/tmp/grass.extensions.db.XXXXXX");      /* TMP_GISMAN is a global variable */
496
 
    mkstemp(TMP_GISMAN);
497
 
 
498
 
    f_out = fopen(TMP_GISMAN, "w+");
499
 
    if (f_out == NULL) {
500
 
        print_error(ERR_REGISTER_ENTRIES_GISMAN,
501
 
                    "could not create temp file '%s': %s\n \
502
 
                        Make sure that directory /tmp exists on your system and you have write permission.\n", TMP_GISMAN, strerror(errno));
503
 
    }
504
 
    atexit(&exit_db);           /* now need to register an at exit func to remove tmpdb automatically! */
505
 
 
506
 
    /* everything fine: create a shell command to copy modified menu.tcl on uninstall */
507
 
    if (VERBOSE) {
508
 
        sprintf(str, "cp -vf %s/etc/dm/menu.tcl %s/etc/dm/menu.tcl.gem.bak ; \
509
 
                                                cp -vf %s %s/etc/dm/menu.tcl ; chmod -v a+r %s/etc/dm/menu.tcl ;", gisbase, gisbase, TMP_GISMAN, gisbase, gisbase);
510
 
    }
511
 
    else {
512
 
        sprintf(str,
513
 
                "cp -f %s/etc/dm/menu.tcl %s/etc/dm/menu.tcl.gem.bak &> %s ; \
514
 
                                                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);
515
 
    }
516
 
    strcpy(GISMAN_CMD, str);
517
 
 
518
 
 
519
 
    /* count number of lines in menu.tcl */
520
 
    n_lines = 0;
521
 
    while (fgets(str, MAXSTR, f_in) != NULL) {
522
 
        n_lines++;
523
 
    }
524
 
    if (n_lines == 0) {
525
 
        return (-1);
526
 
    }
527
 
    rewind(f_in);
528
 
    n_lines_org = n_lines;
529
 
 
530
 
    /* create an array large enough to hold all lines in menu.tcl */
531
 
    /* plus one NULL terminator */
532
 
    /* and copy all lines from menu.tcl into this */
533
 
    line = (char **)calloc(n_lines + 1, sizeof(char *));
534
 
    for (i = 0; i < n_lines + 1; i++) {
535
 
        line[i] = NULL;
536
 
    }
537
 
    i = 0;
538
 
    while (fgets(str, MAXSTR, f_in) != NULL) {
539
 
        line[i] = (char *)malloc((1 + strlen(str)) * sizeof(char));
540
 
        strcpy(line[i], str);
541
 
        i++;
542
 
    }
543
 
 
544
 
    /* search for uninstall comment */
545
 
    sprintf(str, "#(DO_NOT_REMOVE_THIS_COMMENT) <%s> {cascad",
546
 
            pkg_short_name);
547
 
    pos = find_pos(str, line, 0);
548
 
    if (pos == -1) {
549
 
        print_warning
550
 
            ("could not find uninstall information in 'menu.tcl'.\n");
551
 
        return (-1);
552
 
    }
553
 
 
554
 
    /* copy name of submenu to search for */
555
 
    lq = strchr(line[pos], '\"');
556
 
    lq++;
557
 
    rq = strchr(lq, '\"');
558
 
    strcpy(tmp, lq);
559
 
    tmp[(rq - lq) / sizeof(char)] = '\0';
560
 
 
561
 
    /* now find "Xtns" menu start and end */
562
 
    start = find_pos("\"&Xtns\" all options 1", line, 0);
563
 
    end = find_pos("\" all options", line, start + 1) - 1;
564
 
    if (end == -1) {
565
 
        end = find_pos("}]", line, 0);  /* end of menu.tcl */
566
 
    }
567
 
 
568
 
    if (start == -1) {
569
 
        print_warning("menu 'Xtns' does not exist.\n");
570
 
        return (-1);
571
 
    }
572
 
 
573
 
    /* now find our submenu and set the search range to it */
574
 
    sprintf(str, "{cascad \"%s\"", tmp);
575
 
    start_sub = find_pos(str, line, start);
576
 
    if ((start_sub == -1) || (start_sub > end)) {
577
 
        print_warning("could not find submenu entry '%s' in 'menu.tcl'.\n",
578
 
                      tmp);
579
 
        return (-1);
580
 
    }
581
 
    end_sub = find_pos(" \t\t\t}}", line, start_sub);
582
 
    if ((end_sub == -1) || (end_sub > end)) {
583
 
        print_warning
584
 
            ("could not find end of submenu entry '%s' in 'menu.tcl'.\n",
585
 
             tmp);
586
 
        return (-1);
587
 
    }
588
 
 
589
 
    num_removed = 0;
590
 
 
591
 
    /* now kill every line in between start and end! */
592
 
    for (i = 0; i < ((end_sub - start_sub) + 1); i++) {
593
 
        delete_str(start_sub, line);
594
 
        num_removed++;
595
 
    }
596
 
 
597
 
    /* now kill the uninstall comment */
598
 
    sprintf(str, "#(DO_NOT_REMOVE_THIS_COMMENT) <%s> {cascad",
599
 
            pkg_short_name);
600
 
    pos = find_pos(str, line, 0);
601
 
    delete_str(pos, line);
602
 
    num_removed++;
603
 
 
604
 
    /* check if there are any submenus left in "Xtns" and if not: remove Xtns menu */
605
 
    start = find_pos("\"&Xtns\" all options 1", line, 0);
606
 
    end = find_pos("\" all options", line, start + 1) - 1;
607
 
    if (end - start < 3) {
608
 
        for (i = 0; i < ((end - start) + 1); i++) {
609
 
            delete_str(start, line);
610
 
            num_removed++;
611
 
        }
612
 
    }
613
 
 
614
 
    /* write output to tmpfile */
615
 
    i = 0;
616
 
    while (line[i] != NULL) {
617
 
        fprintf(f_out, line[i]);
618
 
        i++;
619
 
    }
620
 
    fflush(f_out);
621
 
 
622
 
    /* check for accidental corruption of menu.tcl: if tmpfile is empty (=0 lines), 
623
 
       we did sth. wrong and should leave the orginal file untouched! */
624
 
    rewind(f_out);
625
 
    n_lines_new = 0;
626
 
    while (fgets(str, MAXSTR, f_out) != NULL) {
627
 
        n_lines_new++;
628
 
    }
629
 
    if ((n_lines_new == 0)) {
630
 
        print_warning
631
 
            ("file truncation detected. Retaining orginal file 'menu.tcl'.\n");
632
 
        strcpy(GISMAN_CMD, "");
633
 
    }
634
 
 
635
 
    /* close files */
636
 
    fclose(f_in);
637
 
    fclose(f_out);
638
 
 
639
 
    /* free memory */
640
 
    for (i = 0; i < n_lines + 1; i++) {
641
 
        free(line[i]);
642
 
    }
643
 
    free(line);
644
 
 
645
 
    return (num_removed);
646
 
}
647
 
 
648
 
 
649
 
/*
650
 
   This version is for Michael Barton's new GIS Manager.
651
 
   In this case, all we have to do is delete the .gem file!
652
 
 */
653
 
void deregister_entries_gisman2(char *pkg_short_name, char *gisbase)
654
 
{
655
 
    char file[MAXSTR];
656
 
    FILE *f_gisman2;
657
 
    char str[MAXSTR];
658
 
 
659
 
    /* check if entries-gisman2 exists and is readable */
660
 
    sprintf(file, "%s/etc/gm/Xtns/%s.gem", gisbase, pkg_short_name);
661
 
    f_gisman2 = fopen(file, "r");
662
 
    if (f_gisman2 == NULL) {
663
 
        if (errno == ENOENT) {
664
 
            /* file does not exist */
665
 
            return;
666
 
        }
667
 
        else {
668
 
            /* sth. strange happened */
669
 
            fclose(f_gisman2);
670
 
            print_error(ERR_DEREGISTER_ENTRIES_GISMAN2,
671
 
                        "checking for file '%s': %s\n", file,
672
 
                        strerror(errno));
673
 
        }
674
 
    }
675
 
 
676
 
    if (VERBOSE) {
677
 
        sprintf(str, "rm -vf %s/etc/gm/Xtns/%s.gem ; ",
678
 
                gisbase, pkg_short_name);
679
 
    }
680
 
    else {
681
 
        sprintf(str, "rm -f %s/etc/gm/Xtns/%s.gem ; ",
682
 
                gisbase, pkg_short_name);
683
 
 
684
 
    }
685
 
    strcpy(GISMAN_CMD, str);
686
 
}
687
 
 
688
 
 
689
 
/*
690
 
   Returns number of restored entries 
691
 
 */
692
 
int restore_entries_gisman(char *gisbase)
693
 
{
694
 
    char str[MAXSTR];
695
 
    char menu[MAXSTR];
696
 
    char file[MAXSTR];
697
 
    char dir[MAXSTR];
698
 
    char pkg_short_name[MAXSTR];
699
 
    int len;
700
 
    char **line;
701
 
    int n_entries, n_lines, i;
702
 
    int line_no;
703
 
    FILE *f_gisman, *f_in, *f_out;
704
 
    DIR *dirp;
705
 
    struct dirent *ep;
706
 
    int num_restored;
707
 
    int n_files;
708
 
 
709
 
    /* check if menu.tcl exists and is readable */
710
 
    sprintf(file, "%s/etc/dm/menu.tcl", gisbase);
711
 
    f_in = fopen(file, "r");
712
 
    if (f_in == NULL) {
713
 
        if (errno == ENOENT) {
714
 
            /* file does not exist */
715
 
            return (0);
716
 
        }
717
 
        else {
718
 
            /* sth. strange happened */
719
 
            fclose(f_in);
720
 
            print_error(ERR_REGISTER_ENTRIES_GISMAN,
721
 
                        "checking for file '%s': %s\n", file,
722
 
                        strerror(errno));
723
 
        }
724
 
    }
725
 
 
726
 
    /* create a temporary menu.tcl file for write access */
727
 
    /* TODO: Do not hardcode temp paths */
728
 
    strcpy(TMP_GISMAN, "/tmp/grass.extensions.db.XXXXXX");      /* TMP_GISMAN is a global variable */
729
 
    mkstemp(TMP_GISMAN);
730
 
 
731
 
    f_out = fopen(TMP_GISMAN, "w+");
732
 
    if (f_out == NULL) {
733
 
        print_error(ERR_REGISTER_ENTRIES_GISMAN,
734
 
                    "could not create temp file '%s': %s\n \
735
 
                        Make sure that directory /tmp exists on your system and you have write permission.\n", TMP_GISMAN, strerror(errno));
736
 
    }
737
 
    atexit(&exit_db);           /* now need to register an at exit func to remove tmpdb automatically! */
738
 
 
739
 
    /* everything fine: create a shell command to copy modified menu.tcl on uninstall */
740
 
    if (VERBOSE) {
741
 
        sprintf(str, "cp -vf %s/etc/dm/menu.tcl %s/etc/dm/menu.tcl.gem.bak ; \
742
 
                                                cp -vf %s %s/etc/dm/menu.tcl ; chmod -v a+r %s/etc/dm/menu.tcl ;", gisbase, gisbase, TMP_GISMAN, gisbase, gisbase);
743
 
    }
744
 
    else {
745
 
        sprintf(str,
746
 
                "cp -f %s/etc/dm/menu.tcl %s/etc/dm/menu.tcl.gem.bak &> %s ; \
747
 
                                                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);
748
 
    }
749
 
    strcpy(GISMAN_CMD, str);
750
 
 
751
 
    /* allocate a pointer to the directory structure */
752
 
    sprintf(dir, "%s/etc/dm/gem-entries", gisbase);
753
 
    dirp = opendir(dir);
754
 
    if (dirp == NULL) {
755
 
        /* directory does not exist or is not accessible */
756
 
        return (0);
757
 
    }
758
 
 
759
 
    /* PASS 1 */
760
 
    /* open all files in gem-entries and count the number of lines each has */
761
 
    n_entries = 0;
762
 
    n_files = 0;
763
 
    while ((ep = readdir(dirp))) {
764
 
        sprintf(file, "%s/%s", dir, ep->d_name);
765
 
        f_gisman = fopen(file, "r");
766
 
        if ((!strcmp(ep->d_name, ".")) || (!strcmp(ep->d_name, ".."))) {
767
 
            fclose(f_gisman);
768
 
            continue;
769
 
        }
770
 
        if (f_gisman == NULL) {
771
 
            fclose(f_gisman);
772
 
            continue;
773
 
        }
774
 
        /* count number of lines in file */
775
 
        while (fgets(str, MAXSTR, f_gisman) != NULL) {
776
 
            n_entries++;
777
 
        }
778
 
        n_files++;
779
 
        fclose(f_gisman);
780
 
    }
781
 
    closedir(dirp);
782
 
 
783
 
    /* count number of lines in menu.tcl */
784
 
    n_lines = 0;
785
 
    while (fgets(str, MAXSTR, f_in) != NULL) {
786
 
        n_lines++;
787
 
    }
788
 
    if (n_lines == 0) {
789
 
        return (0);
790
 
    }
791
 
    rewind(f_in);
792
 
 
793
 
    /* create an array large enough to hold all lines in menu.tcl */
794
 
    /* plus the entries that are to be added from the files in gem-entries/ */
795
 
    /* plus space for uninstall comments */
796
 
    /* plus one NULL terminator */
797
 
    /* and copy all lines from menu.tcl into this */
798
 
    line =
799
 
        (char **)calloc(n_lines + (n_entries * 2) + (n_files * 5) + 1,
800
 
                        sizeof(char *));
801
 
    for (i = 0; i < (n_lines + (n_entries * 2) + (n_files * 5) + 1); i++) {
802
 
        line[i] = NULL;
803
 
    }
804
 
    i = 0;
805
 
    while (fgets(str, MAXSTR, f_in) != NULL) {
806
 
        line[i] = (char *)malloc((1 + strlen(str)) * sizeof(char));
807
 
        strcpy(line[i], str);
808
 
        i++;
809
 
    }
810
 
    line[i] = NULL;             /* add NULL terminator */
811
 
 
812
 
    check_ext_menu(line);       /* create "Extensions" menu if necessary */
813
 
 
814
 
    /* PASS 2: re-create submenus and all menu items if necessary */
815
 
    dirp = opendir(dir);
816
 
    num_restored = 0;
817
 
    while ((ep = readdir(dirp))) {
818
 
        sprintf(file, "%s/%s", dir, ep->d_name);
819
 
        if ((!strcmp(ep->d_name, ".")) || (!strcmp(ep->d_name, ".."))) {
820
 
            continue;
821
 
        }
822
 
        f_gisman = fopen(file, "r");
823
 
        if (f_gisman == NULL) {
824
 
            continue;
825
 
        }
826
 
        /* read all lines from entries-gisman and add to menus */
827
 
        i = 1;
828
 
        while (nc_fgets_nb(str, MAXSTR, f_gisman) != NULL) {
829
 
            if (i == 1) {
830
 
                /* store name of menu item */
831
 
                len = (strrchr(str, ']') - strchr(str, '[')) / sizeof(char);
832
 
                strncpy(menu, strchr(str, '[') + sizeof(char), len);
833
 
                menu[len - 1] = '\0';   /* get rid of [] */
834
 
                line_no = new_submenu(pkg_short_name, str, line);
835
 
                if (line_no < 0) {
836
 
                    break;
837
 
                }
838
 
                i++;
839
 
                num_restored++;
840
 
            }
841
 
            else {
842
 
                line_no = new_item(str, menu, line, line_no);
843
 
                if (line_no < 0) {
844
 
                    break;
845
 
                }
846
 
                i++;
847
 
                num_restored++;
848
 
            }
849
 
        }
850
 
        fclose(f_gisman);
851
 
    }
852
 
    closedir(dirp);
853
 
 
854
 
    /* write output to tmpfile */
855
 
    i = 0;
856
 
    while (line[i] != NULL) {
857
 
        fprintf(f_out, line[i]);
858
 
        i++;
859
 
    }
860
 
    fflush(f_out);
861
 
 
862
 
    /* close remaining files */
863
 
    fclose(f_in);
864
 
    fclose(f_out);
865
 
 
866
 
    /* free memory */
867
 
    for (i = 0; i < (n_lines + (n_entries * 2) + (n_files * 5) + 1); i++) {
868
 
        free(line[i]);
869
 
    }
870
 
    free(line);
871
 
 
872
 
    return (num_restored);
873
 
}