GRASS Programmer's Manual  6.5.svn(2014)-r66266
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
gem/main.c
Go to the documentation of this file.
1 
2 /***************************************************************************
3  * main.c
4  *
5  * Mon Apr 18 15:19:04 2005
6  * Copyright 2005 Benjamin Ducke
7  ****************************************************************************/
8 
9 /*
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU Library General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23  */
24 
25 
26 /* TODO:
27 
28  for 1.04:
29 
30  EASY STUFF:
31 
32 
33  - tried to install GeneralStatistics w/o first installing RasterTools or anything else: attempts to install, fails because
34  of missing raster tools headers! Even though line 379 in reg_deps.c should check for this case !!!
35 
36  - include $GISBASE/lib in linker path for compilation of extensions [NOT FIXED: see lines preceeding INSTALL action case: 693
37  -L is added to command line, but problems still exist]
38  MAYBE EXPORT LD_LIBRARY_PATH ??? (only add $GISBASE/lib if it does not already exist)
39 
40  - version number in HTML documentation index seems to not get updated when installing a newer version of an extension
41 
42  - remember to update version number in globals.h
43 
44 
45  for 1.2 (GRASS 6.4 ?):
46  - make GRASS store its ./configure command line options in a file in the GISBASE/etc directory, so that
47  it will be possible for GEM to automatically configure extensions according to the system setup
48  [this means that configure file needs to be kept in sync with GEM; --configure option can be used
49  to overwrite this behaviour]
50  - configure script should not fail but disable options and create config.msgs the
51  contents of this should be displayed and deleted afterwards
52  - check if it works with this Mac version of GRASS, as well: http://openosx.com/grass/
53  - before release: any problems expected with native Win32-Kompilation?:
54  - location for tmp-files?
55  - a simple wrapper g.install with GRASS style parameters. Should start an xterm and ask for su pwd,
56  if necessary
57  - action to check dependencies of installed extensions
58  - instead of aborting on each failed dependency: build list of all failed
59  dependencies before aborting
60  - mechanism to recursively download and install missing deps from a
61  provided list of URLs
62  - instead of calling external tar, switch to tarlib and zlib
63  - action --validate for checking an extension archive/dir
64  - add link to HTML help index into each extension's submenu in GIS Manager
65  - g.install with a real custom-made GUI
66  [VARIABLE GUI must be set appropriately in run_post() for post script]
67  this should be an independent Tcl/Tk GUI: install/uninstall/query extensions
68  - extension database on the internet that can be queried and used with either gem
69  or g.install
70  - entries for QGIS
71  - simplified scheme for installing just a single module
72  - new scheme for registering menu entries in GIS Manager with stable hooks in menu.tcl
73 
74 
75  NEED HELP
76  - GRASS' make install installs all files BENEATH top level dir with UID
77  set to benni !!! Is this intentional?
78  - provide gem6x as link in /usr/local/bin as part of grass 6.x base install
79  - description.html should not contain </body> or </html> as Rules.Make seems
80  to append those ?
81  - source install copies files COPYING README REQUIREMENTS.html to somewhere (but where?)
82  -> into <extension>/src but where else ?
83  - menu.tcl in GRASS 6.0.0 has "all options 1", but 6.1 will have "all options $tmenu".
84  How to cater for such things? Maybe in the future there should always be an
85  Xtns menu provided by GIS Manager and always delimited by reliable tags
86  - d.m window is a bit to small horizontally
87 
88  CAVEATS:
89  - does not allow installation of different versions of the same extension within
90  the same GRASS bin tree
91  - does not have a real upgrading mechanism: option --upgrade has been disabled for now
92  - restore cannot fix partially corrupted entries in HTML and TCL files
93  - Links to other extension's modules will only work if those extensions are installed
94 
95  DOCS:
96 
97  - skeleton contains GPL as default license. Creators of new extensions
98  need to be aware of this!
99 
100  - menu.tcl will be backed up as menu.tcl.gem.bak
101 
102  - HTML docs: users must prefix references to GRASS modules outside the Extension with
103  "../../html/" !!!
104  - description files: things inside "<" and ">" will be filtered out as HTML tags, even
105  if they are none!
106  - make clear that there are some files which will be rendered both as text and HTML
107  and therefore need things like <br> while others DO NOT (which ones?)!
108 
109  - configure script should not fail but disable options and create 'config.msgs'
110  - deletes config.msg after display
111 
112  - State clearly that it is recommended to uninstall an older
113  extension version before installing a new one. STATE CLEARLY that --upgrade is rather
114  another version of --force than a real updating mechanism (RENAME to --newer)
115  - document all env vars that gem sets
116  - STATE CLEARLY, that users should not meddle with stuff in index.html, menu.tcl,
117  gem-entries/ and docs/extensions/ !!!
118  - provide a unix man page, ASCII and HTML documentation (write HTML and convert)
119  - files in the skeleton should always be present, even if they do not containing
120  information
121  - make it clear, that uninstall and postinstall are run with su privileges! thus,
122  author must make sure, that only objects in the GRASS install tree are affected
123  - user may specify either file name or extension name for uninstall action
124  - user may list installed extensions by using -q w/o filename. Explain
125  what is meant by type (e.g. 'src')
126  - uninstallation works only by extension name, NOT file name !
127  - compiling extensions on a GRASS install with all but the most basic options
128  disabled should give very portable binaries! (statically linked binaries?)
129 
130  BUGS:
131  - remove cva, install again: WARNING: list item 'cva' exists in index.html (?)
132  - superfluous warning upon uninstall of extension w/o "entries-gisman"
133  - due to bad command line parsing, listing installed extensions only works like this:
134  ./gem65 --grass=/usr/local/grass-6.5.svn -q
135  NOT like this:
136  ./gem65 -q --grass=/usr/local/grass-6.5.svn
137 
138 
139  */
140 
141 #include <getopt.h>
142 #include <fcntl.h>
143 
144 #define LOCAL
145 #include "globals.h"
146 
147 
148 void show_help(void)
149 {
150  fprintf(stdout, "Usage: gem65 [OPTION] [ACTION] [FILE|DIR]\n");
151  fprintf(stdout, "Install a GRASS extension from FILE or DIR.\n");
152  fprintf(stdout, "Manage (installed) GRASS extension(s).\n");
153  fprintf(stdout, "\nPossible ACTIONs are:\n");
154  fprintf(stdout, " -i, --install=EXT\tinstall a GRASS extension\n");
155  fprintf(stdout,
156  " -u, --uninstall=EXT\tremove an extension from GRASS\n");
157  fprintf(stdout,
158  " -q, --query=EXT\tdisplay information about extension/list installed\n");
159  fprintf(stdout,
160  " -d, --details=EXT\tdisplay additional details about an extension\n");
161  fprintf(stdout,
162  " -c, --clean=EXT\tclean extension's source code directories\n");
163  fprintf(stdout,
164  " -t, --test=EXT\tconfigure and compile extension, but don't install\n");
165  fprintf(stdout,
166  " -l, --license=EXT\tshow copyright information for an extension\n");
167  fprintf(stdout,
168  " -r, --restore\t\trecreate HTML links and GIS Manager entries\n");
169  fprintf(stdout, " -h, --help\t\tdisplay this help and exit\n");
170  fprintf(stdout,
171  " -V, --version\t\toutput version information and exit\n\n");
172  fprintf(stdout, "\nPossible OPTIONs are:\n");
173  fprintf(stdout, " -g, --grass=PATH\tpath to GRASS installation dir\n");
174  fprintf(stdout,
175  " -b, --binary=NAME\tno compilation: use binary files for system NAME\n");
176  fprintf(stdout,
177  " -f, --force\t\tforce action, regardless of dependencies\n");
178  fprintf(stdout,
179  " -v, --verbose\t\tdisplay detailed status information\n");
180  fprintf(stdout, " -s, --skip-config\tskip configure script\n");
181  fprintf(stdout,
182  " -x, --config-opts=OPTS\tpass OPTS to configure script\n");
183  fprintf(stdout,
184  " -o, --options=OPTS\toptions to pass to the C compiler/linker\n");
185  fprintf(stdout,
186  " -C, --config-cmd=CMD\tDefine custom 'configure' command (default=configure)\n");
187  fprintf(stdout,
188  " -m, --make-cmd=CMD\tDefine custom 'make' command (default=make)\n");
189  fprintf(stdout,
190  "\nWhen run from within a GRASS session, locations of libs, header files\n");
191  fprintf(stdout,
192  "and installation target dir will be assumed to match those of the active\n");
193  fprintf(stdout, "GRASS version. ");
194  fprintf(stdout,
195  "Option -g can be used to override these or install extensions\nfrom outside");
196  fprintf(stdout, "of a GRASS session.\n");
197  fprintf(stdout,
198  "Per default, extensions will be compiled from source and then installed.\n");
199  fprintf(stdout,
200  "If the exension package contains binaries for the user's platform, they can\n");
201  fprintf(stdout, "be installed instead using the -b option. ");
202  fprintf(stdout,
203  "For installation from source code, a C compiler and make tools are needed.\n");
204  fprintf(stdout, "\nExample:\n");
205  fprintf(stdout,
206  "\tgem65 -b macosx --grass=/usr/local/grass-6.5.0 -i myExtension\n");
207  fprintf(stdout,
208  "Installs the MacOS X binaries for 'myExtension' in /usr/local/grass-6.5.0.\n");
209  exit(0);
210 }
211 
212 
213 void show_details(char *package)
214 {
215  int error;
216  char tmp[MAXSTR];
217 
218  sprintf(tmp, "%s", basename(package));
219  error = chdir(tmp);
220  if (error < 0) {
222  "extension '%s' not accessible: (%s)\n", package,
223  strerror(errno));
224  }
225 
226  dump_ascii("info", "Detailed information");
227 
228 
229  /* run post action script */
230  system("sh post");
231 
232  exit(0);
233 }
234 
235 
236 void show_license(char *package)
237 {
238  int error;
239  char tmp[MAXSTR];
240 
241  sprintf(tmp, "%s", basename(package));
242  error = chdir(tmp);
243  if (error < 0) {
245  "extension '%s' not accessible: (%s)\n", package,
246  strerror(errno));
247  }
248 
249  dump_ascii("license", "Detailed information");
250 
251  /* run post action script */
252  system("sh post");
253 
254  exit(0);
255 }
256 
257 
258 void show_version(void)
259 {
260  fprintf(stdout, "gem65 (GRASS extensions manager) %.2f\n", PROGVERSION);
261  fprintf(stdout, "Written by Benjamin Ducke\n");
262  fprintf(stdout, "\nCopyright (C) 2005 Benjamin Ducke\n");
263  fprintf(stdout,
264  "This is free software; see the source for copying conditions. There is NO\n");
265  fprintf(stdout,
266  "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n");
267  exit(0);
268 }
269 
270 
271 /* determine options to pass to extension's configure script */
272 /* TODO: check, if system configuration meets a set of requirements */
273 /* THIS FUNCTION IS CURRENTLY NOT USED */
275 {
276 
277  FILE *fp;
278  char str[MAXSTR];
279 
280  if (strcmp(CONFIG_OPTS, "")) {
281  /* if user has specified config options on the GEM command line: override anything else */
282  return;
283  }
284 
285  /* check if GISBASE/etc/config.system exists and if so, read options from it */
286  sprintf(str, "%s/etc/config.system", gisbase);
287  fp = fopen(str, "r");
288  if (fp == NULL) {
290  ("could not open %s for read access. Using default configure options.\n",
291  str);
292  return;
293  }
294 
295  /* config.system may also contain nothing, only comments and/or whitespace */
296  if (nc_fgets_nb(str, MAXSTR, fp) != NULL) {
297  strcpy(CONFIG_OPTS, str);
298  }
299 }
300 
301 
302 int main(int argc, char *argv[])
303 {
304  char *gisbase;
305  char *grass_version;
306  char *grass_major;
307  char *grass_minor;
308  char *grass_revision;
309  char *tmp;
310  char *url;
311  char *filepart;
312  char version_file[MAXSTR];
313  char package[MAXSTR];
314  char orgname[MAXSTR];
315  char pkg_name[MAXSTR];
316  char *bins;
317  int pkg_major, pkg_minor, pkg_revision;
318  FILE *f;
319  int fd;
320 
321  char pkg_short_name[MAXSTR];
322  char invocation[MAXSTR];
323 
324  char coptions[MAXSTR];
325 
326  int major, minor, revision;
327  int option;
328  int action;
329  int valid;
330 
331  struct stat buf;
332  struct stat buf2;
333  int error;
334  int is_directory = 0;
335  DIR *dir;
336  struct dirent *dir_entry;
337  int dir_found;
338 
339  int option_index = 0;
340  static struct option long_options[] = {
341  {"install", 1, NULL, 'i'},
342  {"uninstall", 1, NULL, 'u'},
343  {"query", 2, NULL, 'q'},
344  {"details", 1, NULL, 'd'},
345  {"clean", 1, NULL, 'c'},
346  {"test", 1, NULL, 't'},
347  {"license", 1, NULL, 'l'},
348  {"restore", 0, NULL, 'r'},
349  {"help", 0, NULL, 'h'},
350  {"version", 0, NULL, 'V'},
351 
352  {"grass", 1, NULL, 'g'},
353  {"options", 1, NULL, 'o'},
354  {"binary", 1, NULL, 'b'},
355  {"force", 0, NULL, 'f'},
356  {"verbose", 0, NULL, 'v'},
357  {"skip-config", 0, NULL, 's'},
358  {"config-opts", 1, NULL, 'x'},
359 
360  {"config-cmd", 1, NULL, 'C'},
361  {"make-cmd", 1, NULL, 'm'},
362 
363  {0, 0, 0, 0}
364  };
365 
366 
367  /* set global variables to defaults */
368  VERBOSE = 0;
369  TMPCLEAN = 0;
370  TMPDBCLEAN = 0;
371  FORCE = 0;
372  UPGRADE = 0;
373  ERROR = 0;
374  WARNINGS = 0;
375  SKIP_CFG = 0;
376 
377  strcpy(GISMAN_CMD, "");
378  strcpy(GISMAN2_CMD, "");
379  strcpy(QGIS_CMD, "");
380  strcpy(UNINSTALL_CMD, "");
381  strcpy(HTML_CMD, "");
382 
383  strcpy(TMPDIR, "");
384  strcpy(TMPDB, "");
385  strcpy(TMP_GISMAN, "");
386  strcpy(TMP_DESCR, "");
387  strcpy(TMP_INFO, "");
388  strcpy(TMP_DEPS, "");
389  strcpy(TMP_BUGS, "");
390  strcpy(TMP_AUTHORS, "");
391  strcpy(TMP_HTML, "");
392  strcpy(TMP_NULL, "");
393 
394  strcpy(CONFIG_OPTS, "");
395 
396  strcpy(CONFIG_CMD, "configure");
397  strcpy(MAKE_CMD, "make");
398 
399  getcwd(CWD, MAXSTR);
400 
401  /* reset terminal colors */
402  fprintf(stdout, "\033[0m");
403 
404  tmp = malloc(sizeof(char) * MAXSTR);
405  strncpy(invocation, argv[0], MAXSTR);
406  invocation[MAXSTR-1] = '\0';
407 
408  /* all output should be unbuffered */
409  setvbuf(stdout, (char *)NULL, _IONBF, 0);
410 
411  /* if run with no arguments: show help */
412  if (argc == 1) {
413  /* show usage info and exit */
414  show_help();
415  exit(0);
416  }
417 
418  atexit(&exit_msg); /* show a message after program termination */
419 
420  valid = 0;
421  bins = NULL;
422  gisbase = NULL;
423 
424  opterr = 0;
425  option =
426  getopt_long(argc, argv, ":i:u:q:d:c:C:t:l:m:o:x:rhVg:b:fvs",
427  long_options, &option_index);
428  while (option != -1) {
429 
430  if (option == '?') {
432  "unknown option or action specified.\n");
433  }
434 
435 
436  /* check for missing arguments */
437  if (option == ':') {
438  if ((optopt == 'i') || (optopt == 'u') || (optopt == 'd') ||
439  (optopt == 'c') || (optopt == 't') || (optopt == 'l') ||
440  (optopt == 'r')) {
442  "missing file or directory name.\n");
443  }
444  if (optopt == 'g') {
445  print_error(ERR_INVOCATION, "missing path to GRASS 6.\n");
446  }
447  if (optopt == 'b') {
449  "missing name of binary architecture.\n");
450  }
451  if (optopt == 'b') {
452  print_error(ERR_INVOCATION, "missing configure options.\n");
453  }
454  if (optopt == 'q') {
455  /* '-q' w/o filename is list action */
456  action = LIST;
457  valid++;
458  break;
459  }
460  }
461 
462  if ((option == 'i') || (option == 'u') || (option == 'q') ||
463  (option == 'd') || (option == 'c') || (option == 't') ||
464  (option == 'l') || (option == 'r') || (option == 'h') ||
465  (option == 'V')) {
466  /* got a valid action specifier */
467  valid++;
468  /* set action accordingly */
469  switch (option) {
470  case 'i':
471  if (action != BIN_INSTALL) {
472  action = INSTALL;
473  }
474  break;
475  case 'u':
476  action = UNINSTALL;
477  break;
478  case 'q':
479  action = QUERY;
480  break;
481  case 'd':
482  action = DETAILS;
483  break;
484  case 'c':
485  action = CLEAN;
486  break;
487  case 't':
488  action = TEST_INSTALL;
489  break;
490  case 'l':
491  action = LICENSE;
492  break;
493  case 'r':
494  action = RESTORE;
495  break;
496  case 'h':
497  action = HELP;
498  break;
499  case 'V':
500  action = VERSION;
501  break;
502  }
503  if (optarg != NULL) {
504  /* save package name as given on command line */
505  strcpy(package, optarg);
506  /* orgname will always preserve the commandline option */
507  strcpy(orgname, optarg);
508  }
509  }
510 
511  /* set options */
512  if (option == 'g') {
513  gisbase = malloc(sizeof(char) * (strlen(optarg) + 1));
514  strcpy(gisbase, optarg);
515  }
516  if (option == 'b') {
517  bins = malloc(sizeof(char) * (strlen(optarg) + 1));
518  strcpy(bins, optarg);
519  action = BIN_INSTALL;
520  }
521  if (option == 'x') {
522  /* configure script options */
523  strcpy(&CONFIG_OPTS[0], optarg);
524  }
525 
526  if (option == 'f') {
527  FORCE = 1;
528  }
529  if (option == 'v') {
530  VERBOSE = 1;
531  }
532 
533  if (option == 's') {
534  SKIP_CFG = 1;
535  }
536  if (option == 'o') {
537  /* GEM_C_OPTS gets passed to the C compiler via the GRASS/GEM Makefiles:
538  <EXT>/src/include/Make/Grass.make.in:
539  CFLAGS = $(INC) $(COMPILE_FLAGS) $(USE_TERMIO) $(GEM_C_OPTS)
540  */
541  strcat(coptions, optarg);
542  }
543  /* define a custom configure command */
544  if (option == 'C') {
545  strcpy(CONFIG_CMD, optarg);
546  }
547  /* define a custom make command */
548  if (option == 'm') {
549  strcpy(MAKE_CMD, optarg);
550  }
551  /* get next option from command line */
552  option =
553  getopt_long(argc, argv, ":i:u:q:d:c:t:l:o:x:rhVg:b:fvs",
554  long_options, &option_index);
555  }
556 
557 
558  if (valid < 1) {
559  print_error(ERR_INVOCATION, "please specify a valid action.\n");
560  }
561  if (valid > 1) {
562  print_error(ERR_INVOCATION, "please specify only one action.\n");
563  }
564 
565  /* export compiler options for use by Makefiles */
566  sprintf(GEM_C_OPTS, "GEM_C_OPTS=%s", coptions);
567  putenv(GEM_C_OPTS);
568 
569  /* these actions can be done without any extension checking */
570  if (action == HELP) {
571  /* show usage info and exit */
572  show_help();
573  exit(0);
574  }
575 
576  if (action == VERSION) {
577  /* show version info and exit */
578  show_version();
579  exit(0);
580  }
581 
582  if (!VERBOSE) {
583  /* set temp file to pipe output to for silent operation */
584  /* TODO: Do not hardcode temp paths */
585  strcpy(TMP_NULL, "/tmp/grass.extension.log.XXXXXX"); /* TMP_NULL is a global variable */
586  mkstemp(TMP_NULL);
587  fd = open(TMP_NULL, O_CREAT, 0777);
588  if (fd == -1) {
589  print_error(ERR_TMPFILE, "could not create temp file: %s",
590  strerror(errno));
591  exit(ERR_TMPFILE);
592  }
593  }
594 
595 
596  /* these actions need a valid GRASS path but no extensions */
597  if (action == RESTORE) {
598  /* figure out path to GRASS installation */
599  /* GIS base not given? */
600  if (gisbase == NULL) {
601  /* try to read from GRASS environment */
602  gisbase = getenv("GISBASE");
603  if (gisbase == NULL) {
604  /* still NULL? Abort! */
606  "GISBASE environment variable not set and path to GRASS not given.\n");
607  }
608  }
609 
610  if (VERBOSE) {
611  fprintf(stdout, "Path to GRASS is %s.\n", gisbase);
612  }
613 
614  restore(gisbase, grass_version);
615  exit(0);
616  }
617 
618  if (action == LIST) {
619  /* figure out path to GRASS installation */
620  /* GIS base not given? */
621  if (gisbase == NULL) {
622  /* try to read from GRASS environment */
623  gisbase = getenv("GISBASE");
624  if (gisbase == NULL) {
625  /* still NULL? Abort! */
627  "GISBASE environment variable not set and path to GRASS not given.\n");
628  }
629  }
630 
631  if (VERBOSE) {
632  fprintf(stdout, "Path to GRASS is %s.\n", gisbase);
633  }
634  list_extensions(gisbase);
635  exit(0);
636  }
637 
638  /* check if extension is stored in a remote URL */
639  if ((strstr(package, "http://")) || (strstr(package, "ftp://"))) {
640  wget_extension(package); /* download into current dir using wget */
641  /* cut off the path specification */
642  url = malloc(sizeof(char) * MAXSTR);
643  strcpy(url, package);
644  filepart = strrchr(url, '/');
645  filepart++;
646  strcpy(package, filepart);
647  free(url);
648  }
649 
650  if (VERBOSE) {
651  fprintf(stdout, "Extension location is '%s'.\n", package);
652  }
653 
654  if (action != UNINSTALL) {
655  error = stat(package, &buf);
656  if (error < 0) {
658  "extension FILE or DIR '%s' invalid: %s\n", package,
659  strerror(errno));
660  }
661  if (S_ISDIR(buf.st_mode)) {
662  is_directory = 1;
663  if (VERBOSE) {
664  fprintf(stdout, "Extension files stored in a directory.\n");
665  }
666  }
667  else {
668  if (VERBOSE) {
669  fprintf(stdout,
670  "Extension files stored in a package file.\n");
671  }
672  /* DECOMPRESS INTO TEMP DIR, CHANGE NAME OF package TO THAT DIR */
673  unpack_extension(package);
674  /* find name of directory containing extension files */
675  /* very primitive: just picks the first directory */
676  dir = opendir(TMPDIR);
677  dir_entry = readdir(dir);
678  dir_found = 0;
679  while (dir_entry != NULL) {
680  if ((strcmp(dir_entry->d_name, ".")) &&
681  (strcmp(dir_entry->d_name, ".."))
682  ) {
683  /* check if it is a directory */
684  sprintf(tmp, "%s/%s", TMPDIR, dir_entry->d_name);
685  stat(tmp, &buf2);
686  if (S_ISDIR(buf2.st_mode)) {
687  dir_found = 1;
688  break;
689  }
690  }
691  dir_entry = readdir(dir);
692  }
693  strcpy(package, tmp);
694 
695  if (dir_found == 0) {
697  "no top-level directory found in extension package.\n");
698  }
699  }
700  }
701 
702  /* copy package name into this maliciously named variable */
703  /* (sorry about the mess ...) */
704  /* This name will be used for all registration actions and */
705  /* for creating files and directories that store extension */
706  /* information for uninstall and restore actions */
707  /* For uninstall, we take the last argument as package, NOT */
708  /* file name */
709  if (action == UNINSTALL) {
710  strcpy(pkg_short_name, package);
711  }
712  else {
713  get_package_name(package, pkg_short_name);
714  }
715 
716  /* export relevant VARS for use by post script */
717  if (valid > 0) {
718  /* export all relevant env vars for the post script */
719  if (gisbase == NULL) {
720  /* try to read from GRASS environment */
721  gisbase = getenv("GISBASE");
722  }
723  run_post(package, action, bins, gisbase);
724  }
725 
726  if (VERBOSE) {
727  fprintf(stdout, "Extension will be installed from '%s'\n", package);
728  }
729 
730  /* CHECK PACKAGE FOR VALIDITY */
731  if (action != UNINSTALL) {
732  check_extension(package, pkg_name, &pkg_major, &pkg_minor,
733  &pkg_revision);
734  }
735 
736  /* these actions can be done without GRASS checking */
737  if (action == QUERY) {
738  query_extension(package, pkg_name, pkg_major, pkg_minor, pkg_revision,
739  pkg_short_name, invocation, orgname);
740  exit(0);
741  }
742 
743  if (action == DETAILS) {
744  show_details(package);
745  exit(0);
746  }
747 
748  if (action == LICENSE) {
749  show_license(package);
750  exit(0);
751  }
752 
753  if (action == CLEAN) {
754  source_clean(package);
755  exit(0);
756  }
757 
758 
759  /* The following checks need to be done for all other actions! */
760 
761  /* figure out path to GRASS installation */
762  /* GIS base not given? */
763  if (gisbase == NULL) {
764  /* try to read from GRASS environment */
765  gisbase = getenv("GISBASE");
766  if (gisbase == NULL) {
767  /* still NULL? Abort! */
769  "GISBASE environment variable not set and path to GRASS not given.\n");
770  }
771  }
772 
773  if (VERBOSE) {
774  fprintf(stdout, "Path to GRASS is %s.\n", gisbase);
775  }
776 
777  /* figure out GRASS version */
778  grass_version = getenv("GRASS_VERSION");
779  if (grass_version == NULL) {
780  /* GRASS version can be read from gisbase/etc/VERSIONNUMBER */
781  sprintf(version_file, "%s/etc/VERSIONNUMBER", gisbase);
782  f = fopen(version_file, "r");
783  if (f == NULL) {
784  /* still NULL? Abort! */
786  "Could not read GRASS version. Did you specify the right path?\n");
787  }
788  else {
789  grass_version = malloc(sizeof(char) * 16);
790  error = fscanf(f, "%s", grass_version);
791  fclose(f);
792  if (error < 1) {
794  "Could not read GRASS version. Did you specify the right path?\n");
795  }
796  }
797  }
798 
799  if (grass_version != NULL) {
800  /* extract major and minor version numbers */
801  tmp = strdup(grass_version);
802 
803  grass_major = strtok(tmp, ".");
804  grass_minor = strtok(NULL, ".");
805  grass_revision = strtok(NULL, ".");
806 
807  major = strtol(grass_major, NULL, 10);
808  minor = strtol(grass_minor, NULL, 10);
809  revision = strtol(grass_revision, NULL, 10);
810 
811  grass_version = malloc(sizeof(char) * MAXSTR);
812  sprintf(grass_version, "%i.%i.%i", major, minor, revision);
813  if (VERBOSE) {
814  fprintf(stdout, "GRASS version is %s.\n", grass_version);
815  }
816 
817  if (major < 6) {
819  "extensions only work with GRASS version 6 and above.\n");
820  }
821  }
822 
823  /* for GDAL compatibility and
824  for the sake of people using Lorenzo Moretti's GRASS for MacOS, we always export the following
825  compiler options */
826  sprintf(coptions, "-L%s/lib -I/usr/local/grasslib/include/ ", gisbase);
827 
828  /* these actions can only be done after everything has been checked */
829  if (action == INSTALL) {
830  source_install(package, gisbase, pkg_short_name, pkg_major, pkg_minor,
831  pkg_revision, grass_version);
832  exit(0);
833  }
834 
835  if (action == UNINSTALL) {
836  uninstall(package, pkg_short_name, gisbase, grass_version);
837  exit(0);
838  }
839 
840  if (action == TEST_INSTALL) {
841  test_install(package, gisbase, pkg_short_name, pkg_major, pkg_minor,
842  pkg_revision, grass_version);
843  exit(0);
844  }
845 
846  if (action == BIN_INSTALL) {
847  if (binaries_exist(package, bins)) {
848  bin_install(package, gisbase, bins, pkg_short_name, pkg_major,
849  pkg_minor, pkg_revision, grass_version);
850  exit(0);
851  }
852  else {
853  print_error(ERR_MISSING_BINS, "no binaries for system '%s'\n",
854  bins);
855  }
856  }
857 
858  exit(0);
859 }
EXTERN int VERBOSE
Definition: globals.h:147
void query_extension(char *package, char *name, int major, int minor, int revision, char *short_name, char *invocation, char *org_name)
Definition: actions.c:201
void source_install(char *package, char *gisbase, char *pkg_short_name, int pkg_major, int pkg_minor, int pkg_revision, char *grass_version)
Definition: actions.c:263
EXTERN int SKIP_CFG
Definition: globals.h:163
void list_extensions(char *gisbase)
Definition: actions.c:1022
sprintf(buf2,"%s", G3D_CATS_ELEMENT)
char * basename(char *path)
Definition: tools.c:33
DIR * opendir()
#define LICENSE
Definition: globals.h:69
void bin_install(char *package, char *gisbase, char *bins, char *pkg_short_name, int pkg_major, int pkg_minor, int pkg_revision, char *grass_version)
Definition: actions.c:475
#define DETAILS
Definition: globals.h:71
EXTERN char CONFIG_OPTS[MAXSTR]
Definition: globals.h:170
string action
#define MAXSTR
Definition: globals.h:59
EXTERN char CONFIG_CMD[MAXSTR]
Definition: globals.h:171
FILE * fd
Definition: g3dcolor.c:368
void get_package_name(char *path, char *name)
Definition: tools.c:273
Definition: pad.h:5
EXTERN char TMPDIR[MAXSTR]
Definition: globals.h:148
EXTERN char GISMAN2_CMD[MAXSTR]
Definition: globals.h:166
EXTERN char TMP_NULL[MAXSTR]
Definition: globals.h:156
void print_error(int err_code, char *msg,...)
Definition: gem/error.c:32
#define RESTORE
Definition: globals.h:73
#define QUERY
Definition: globals.h:67
void uninstall(char *package, char *pkg_short_name, char *gisbase, char *grass_version)
Definition: actions.c:812
EXTERN int WARNINGS
Definition: globals.h:179
#define BIN_INSTALL
Definition: globals.h:66
void show_version(void)
Definition: gem/main.c:258
EXTERN char TMP_HTML[MAXSTR]
Definition: globals.h:158
struct _list LIST
void test_install(char *package, char *gisbase, char *pkg_short_name, int pkg_major, int pkg_minor, int pkg_revision, char *grass_version)
Definition: actions.c:636
#define ERR_VERSION
Definition: globals.h:87
tuple gisbase
Definition: forms.py:59
void get_configure_options(char *gisbase)
Definition: gem/main.c:274
void wget_extension(char *url)
Definition: tools.c:766
void show_license(char *package)
Definition: gem/main.c:236
void unpack_extension(char *package)
Definition: actions.c:88
char * getenv()
dir_entry * readdir()
EXTERN char QGIS_CMD[MAXSTR]
Definition: globals.h:168
EXTERN char UNINSTALL_CMD[MAXSTR]
Definition: globals.h:169
EXTERN int TMPCLEAN
Definition: globals.h:159
EXTERN char TMP_AUTHORS[MAXSTR]
Definition: globals.h:155
int stat
Definition: g3dcolor.c:369
void show_details(char *package)
Definition: gem/main.c:213
EXTERN char TMP_BUGS[MAXSTR]
Definition: globals.h:154
void * malloc(YYSIZE_T)
EXTERN char HTML_CMD[MAXSTR]
Definition: globals.h:167
void check_extension(char *package, char *name, int *major, int *minor, int *revision)
Definition: actions.c:29
int main(int argc, char *argv[])
Definition: gem/main.c:302
#define PROGVERSION
Definition: globals.h:57
#define ERR_MISSING_BINS
Definition: globals.h:88
#define CLEAN
Definition: globals.h:68
EXTERN int UPGRADE
Definition: globals.h:162
EXTERN char TMP_DESCR[MAXSTR]
Definition: globals.h:151
#define ERR_NO_ACCESS_EXT
Definition: globals.h:78
EXTERN char TMPDB[MAXSTR]
Definition: globals.h:149
void restore(char *gisbase, char *grass_version)
Definition: actions.c:952
EXTERN char CWD[MAXSTR]
Definition: globals.h:175
void run_post(char *package, int action, char *bins, char *gisbase)
Definition: actions.c:1057
EXTERN char MAKE_CMD[MAXSTR]
Definition: globals.h:172
EXTERN int FORCE
Definition: globals.h:161
#define INSTALL
Definition: globals.h:65
int binaries_exist(char *package, char *binaries)
Definition: tools.c:690
void print_warning(char *msg,...)
Definition: gem/error.c:52
return NULL
Definition: dbfopen.c:1394
#define ERR_UNPACK_EXT
Definition: globals.h:83
#define VERSION
Definition: globals.h:64
#define UNINSTALL
Definition: globals.h:72
void dump_ascii(char *file, char *heading)
Definition: tools.c:539
#define ERR_INVOCATION
Definition: globals.h:77
fclose(fd)
EXTERN char TMP_INFO[MAXSTR]
Definition: globals.h:152
void exit_msg(void)
EXTERN int ERROR
Definition: globals.h:178
void free(void *)
#define TEST_INSTALL
Definition: globals.h:70
EXTERN char TMP_DEPS[MAXSTR]
Definition: globals.h:153
EXTERN char GEM_C_OPTS[MAXSTR]
Definition: globals.h:142
int errno
struct dirent dir_entry
Definition: dirent.c:16
#define HELP
Definition: globals.h:63
int source_clean(char *package)
Definition: actions.c:907
EXTERN int TMPDBCLEAN
Definition: globals.h:160
char * nc_fgets_nb(char *s, int size, FILE *stream)
Definition: tools.c:500
#define ERR_TMPFILE
Definition: globals.h:106
void show_help(void)
Definition: gem/main.c:148
EXTERN char GISMAN_CMD[MAXSTR]
Definition: globals.h:165
EXTERN char TMP_GISMAN[MAXSTR]
Definition: globals.h:150