GRASS Programmer's Manual  6.4.2(2012)
actions.c
Go to the documentation of this file.
00001 
00002 /***************************************************************************
00003  *            actions.c
00004  *
00005  *  Mon Apr 18 15:25:54 2005
00006  *  Copyright  2005  Benjamin Ducke
00007  ****************************************************************************/
00008 
00009 /*
00010  *  This program is free software; you can redistribute it and/or modify
00011  *  it under the terms of the GNU General Public License as published by
00012  *  the Free Software Foundation; either version 2 of the License, or
00013  *  (at your option) any later version.
00014  *
00015  *  This program is distributed in the hope that it will be useful,
00016  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  *  GNU Library General Public License for more details.
00019  *
00020  *  You should have received a copy of the GNU General Public License
00021  *  along with this program; if not, write to the Free Software
00022  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00023  */
00024 
00025 #include "globals.h"
00026 #include <fcntl.h>
00027 
00028 
00029 void check_extension(char *package, char *name, int *major, int *minor,
00030                      int *revision)
00031 {
00032     int error;
00033     char tmp[MAXSTR] = "";
00034     FILE *f;
00035 
00036     fprintf(stdout, "Checking extension ...");
00037 
00038     sprintf(tmp, "%s", package);
00039     error = chdir(tmp);
00040     if (error < 0) {
00041         print_error(ERR_NO_ACCESS_EXT, "extension '%s' not accessible: %s\n",
00042                     package, strerror(errno));
00043     }
00044 
00045     /* get file id */
00046     f = fopen("id", "r");
00047     if (f == NULL) {
00048         print_error(ERR_INVALID_EXT, "'id' file not readable.\n");
00049     }
00050     else {
00051         fscanf(f, "%[<GRASS extension package>] ", tmp);
00052         if (strcmp("<GRASS extension package>", tmp)) {
00053             fclose(f);
00054             print_error(ERR_INVALID_EXT, "unknown file identifier.\n");
00055         }
00056     }
00057     fclose(f);
00058 
00059     get_package_name(".", name);
00060 
00061     /* get extension version */
00062     f = fopen("version", "r");
00063     if (f == NULL) {
00064         print_error(ERR_INVALID_EXT, "'version' file not readable.\n");
00065     }
00066     else {
00067         nc_fgets_nb(tmp, MAXSTR, f);
00068         *minor = 0;
00069         *revision = 0;
00070         error = sscanf(tmp, "%i.%i.%i", major, minor, revision);
00071         if (error < 1) {
00072             fclose(f);
00073             print_error(ERR_INVALID_EXT,
00074                         "invalid or missing version information.\n");
00075         }
00076     }
00077 
00078     print_done();
00079     chdir("..");
00080     fclose(f);
00081 }
00082 
00083 
00084 /* 
00085    decompresses extension file and returns path to the temporary directory where the
00086    extension has been stored. 
00087  */
00088 void unpack_extension(char *package)
00089 {
00090     int error;
00091     int fd;
00092     char tmp[MAXSTR];
00093     int ftype;
00094 
00095     fprintf(stdout, "Uncompressing files...");
00096 
00097     /* TODO: Do not hardcode temp paths */
00098     strcpy(TMPDIR, "/tmp/grass.extension.XXXXXX");      /* tmpdir is a global variable */
00099     mkstemp(TMPDIR);
00100     fd = open(TMPDIR, O_CREAT, 0777);
00101     if (fd == -1) {
00102         print_error(ERR_UNPACK_EXT,
00103                     "could not create temp directory name: %s",
00104                     strerror(errno));
00105         exit(ERR_UNPACK_EXT);
00106     }
00107 
00108     if (VERBOSE) {
00109         fprintf(stdout, "\nUncompressing to: %s.\n", TMPDIR);
00110     }
00111 
00112     /* remove tmp file and create a dir with the same name */
00113     close(fd);
00114     remove(TMPDIR);
00115     mkdir_s(TMPDIR, "0700");
00116 
00117     atexit(&exit_tmp);          /* now need to register an at exit func to remove tmpdir automatically! */
00118 
00119     /* uncompress extension to TMPDIR */
00120     /* 1. copy file */
00121     sprintf(tmp, "cp %s %s", package, TMPDIR);
00122     error = system(tmp);
00123     if (error < 0) {
00124         print_error(ERR_UNPACK_EXT,
00125                     "could not copy extension files to temp dir.\n");
00126         exit(ERR_UNPACK_EXT);
00127     }
00128 
00129     /* see what type of archive it is */
00130     ftype = check_filetype(package);
00131     if (ftype == TYPE_UNKNOWN) {
00132         print_warning
00133             ("file name not '.tar.gz', '.tgz', '.tar.bz2', '.tbz' or '.zip'. Assuming '.tgz'.\n");
00134         ftype = TAR_GZIP;
00135     }
00136     if (ftype == TAR_GZIP) {
00137         if (VERBOSE) {
00138             sprintf(tmp, "tar -xzvf %s/%s -C %s", TMPDIR, basename(package),
00139                     TMPDIR);
00140         }
00141         else {
00142             sprintf(tmp, "tar -xzf %s/%s -C %s", TMPDIR, basename(package),
00143                     TMPDIR);
00144         }
00145     }
00146     if (ftype == TAR_BZIP2) {
00147         if (VERBOSE) {
00148             sprintf(tmp, "tar -xjvf %s/%s -C %s", TMPDIR, basename(package),
00149                     TMPDIR);
00150         }
00151         else {
00152             sprintf(tmp, "tar -xjvf %s/%s -C %s", TMPDIR, basename(package),
00153                     TMPDIR);
00154         }
00155     }
00156     if (ftype == ZIP) {
00157         if (VERBOSE) {
00158             sprintf(tmp, "unzip %s/%s -d %s", TMPDIR, basename(package),
00159                     TMPDIR);
00160         }
00161         else {
00162             sprintf(tmp, "unzip -qq %s/%s -d %s", TMPDIR, basename(package),
00163                     TMPDIR);
00164         }
00165     }
00166     if (ftype == TAR) {
00167         if (VERBOSE) {
00168             sprintf(tmp, "tar -xvf %s/%s -C %s", TMPDIR, basename(package),
00169                     TMPDIR);
00170         }
00171         else {
00172             sprintf(tmp, "tar -xf %s/%s -C %s", TMPDIR, basename(package),
00173                     TMPDIR);
00174         }
00175     }
00176 
00177     error = system(tmp);
00178     if (error < 0) {
00179         if (ftype == TAR_GZIP) {
00180             print_error(ERR_UNPACK_EXT,
00181                         "could not extract files using 'tar' and 'gzip'. \n \
00182                                         Extract manually using 'tar -xzvf %s'.\n", package);
00183         }
00184         if (ftype == TAR_BZIP2) {
00185             print_error(ERR_UNPACK_EXT, "could not extract files using 'tar' and 'bunzip2'.\n \
00186                                 Extract manually using 'tar -xjvf %s'.\n",
00187                         package);
00188         }
00189         if (ftype == ZIP) {
00190             print_error(ERR_UNPACK_EXT, "could not extract files using 'unzip'.\n \
00191                                 Extract manually using 'unzip %s'.\n",
00192                         package);
00193         }
00194         exit(ERR_UNPACK_EXT);
00195     }
00196 
00197     print_done();
00198 }
00199 
00200 
00201 void query_extension(char *package, char *name, int major, int minor,
00202                      int revision, char *short_name, char *invocation,
00203                      char *org_name)
00204 {
00205     int error;
00206     char tmp[MAXSTR];
00207 
00208     sprintf(tmp, "%s", basename(package));
00209     error = chdir(tmp);
00210     if (error < 0) {
00211         print_error(ERR_NO_ACCESS_EXT, "extension '%s' not accessible: %s\n",
00212                     package, strerror(errno));
00213     }
00214 
00215     fprintf(stdout, "\nExtension '%s', version %i.%i.%i\n\n", name, major,
00216             minor, revision);
00217     dump_ascii("description", "Description");
00218     dump_ascii("commands", "Commands provided");
00219     dump_ascii("libs", "Libraries provided");
00220     dump_ascii("headers", "Header files provided");
00221     dump_ascii("depends", "Dependencies");
00222     dump_ascii("bugs", "Bugs");
00223     sprintf(tmp, "../%s", package);
00224     list_binaries(tmp);
00225     dump_ascii("authors", "Author(s)");
00226 
00227     fprintf(stdout, "Type '%s -d %s' to see more detailed information.\n",
00228             invocation, org_name);
00229     fprintf(stdout, "Type '%s -l %s' to see copyright information.\n",
00230             invocation, org_name);
00231 
00232     /* run post action script */
00233     system("sh post");
00234 
00235     exit(0);
00236 
00237 }
00238 
00239 /*
00240    Dump contents of config.msg to screen
00241  */
00242 void print_cfg(void)
00243 {
00244     FILE *fp;
00245     char line[MAXSTR];
00246 
00247     fp = fopen("config.msg", "r");
00248     if (fp != NULL) {
00249         fprintf(stdout, "\nResult of configuration: \n");
00250         while (fgets(line, MAXSTR, fp) != NULL) {
00251             fprintf(stdout, "%s", line);
00252         }
00253         fprintf(stdout, "\n");
00254     }
00255 
00256     /* remove file afterward */
00257     remove("config.msg");
00258 }
00259 
00260 
00261 /*
00262  */
00263 void source_install(char *package, char *gisbase, char *pkg_short_name,
00264                     int pkg_major, int pkg_minor, int pkg_revision,
00265                     char *grass_version)
00266 {
00267     char tmp[MAXSTR];
00268     char dir[MAXSTR];
00269     char install_cmd[MAXSTR];
00270     char post_cmd[MAXSTR];
00271     char sysstr[MAXSTR];
00272     int error;
00273     struct stat buf;
00274     FILE *f;
00275 
00276     char *verstr;
00277     char *grass_major;
00278     char *grass_minor;
00279     char *grass_revision;
00280     int major, minor, revision;
00281 
00282     /* check for valid install directory */
00283     error = stat(gisbase, &buf);
00284     if (error < 0) {
00285         print_error(ERR_INSTALL_EXT, "installation directory invalid: %s\n",
00286                     strerror(errno));
00287     }
00288 
00289     /* export environment variables for GRASS 6 build system */
00290     /* target dir for installation */
00291     sprintf(GINSTALL_DST, "GINSTALL_DST=%s", gisbase);
00292     putenv(GINSTALL_DST);
00293     /*external include path */
00294     sprintf(tmp, "%s/include", gisbase);
00295     sprintf(GINSTALL_INC, "GINSTALL_INC=%s", tmp);
00296     putenv(GINSTALL_INC);
00297     /* external linker path */
00298     sprintf(tmp, "%s/lib", gisbase);
00299     sprintf(GINSTALL_LIB, "GINSTALL_LIB=%s", tmp);
00300     putenv(GINSTALL_LIB);
00301     /* path to install files */
00302     sprintf(GEM_GRASS_DIR, "GEM_GRASS_DIR=%s", gisbase);
00303     putenv(GEM_GRASS_DIR);
00304 
00305     /* extract GRASS major and minor version numbers */
00306     verstr = strdup(grass_version);
00307     grass_major = strtok(verstr, ".");
00308     grass_minor = strtok(NULL, ".");
00309     grass_revision = strtok(NULL, ".");
00310     major = strtol(grass_major, NULL, 10);
00311     minor = strtol(grass_minor, NULL, 10);
00312     revision = strtol(grass_revision, NULL, 10);
00313     free(verstr);
00314 
00315 
00316     /* now need to register an exit function that unsets these env vars on termination! */
00317     atexit(&exit_tmp);
00318 
00319     /* step into target directory and execute configure script */
00320     sprintf(dir, "%s/src", basename(package));
00321     error = chdir(dir);
00322     if (error < 0) {
00323         print_error(ERR_NO_ACCESS_EXT,
00324                     "extension files in '%s' not accessible: %s\n", package,
00325                     strerror(errno));
00326     }
00327 
00328     if (!SKIP_CFG) {
00329         if (VERBOSE) {
00330             fprintf(stdout, "Running configure script:\n");
00331             sprintf(sysstr, "sh %s %s", CONFIG_CMD, CONFIG_OPTS);
00332             error = system(sysstr);
00333         }
00334         else {
00335             fprintf(stdout, "Configuring...");
00336             sprintf(sysstr, "sh %s %s --quiet &> %s", CONFIG_CMD, CONFIG_OPTS,
00337                     TMP_NULL);
00338             error = system(sysstr);
00339         }
00340         if (error == -1) {
00341             print_error(ERR_MISSING_CFG, "could not run configure script.\n");
00342         }
00343         if (error > 0) {
00344             print_error(ERR_CONFIGURE_EXT, "system configuration failed.\n");
00345         }
00346         print_done();
00347         print_cfg();
00348     }
00349 
00350     /* export environment variables for generation of HTML documentation directories */
00351     /* by include/Make/Rules.make */
00352     sprintf(GEM_EXT_NAME, "GEM_EXT_NAME=%s", pkg_short_name);
00353     putenv(GEM_EXT_NAME);
00354     sprintf(tmp, "%i.%i.%i", pkg_major, pkg_minor, pkg_revision);
00355     sprintf(GEM_EXT_VERSION, "GEM_EXT_VERSION=%s", tmp);
00356     putenv(GEM_EXT_VERSION);
00357     /* dump extension info text into two plain ASCII files for inclusion in HTML man page */
00358     dump_html("../description", TMP_DESCR);
00359     dump_html("../info", TMP_INFO);
00360     dump_html("../depends", TMP_DEPS);
00361     dump_html("../bugs", TMP_BUGS);
00362     dump_html("../authors", TMP_AUTHORS);
00363     sprintf(GEM_EXT_DESCR, "GEM_EXT_DESCR=%s", TMP_DESCR);
00364     putenv(GEM_EXT_DESCR);
00365     sprintf(GEM_EXT_INFO, "GEM_EXT_INFO=%s", TMP_INFO);
00366     putenv(GEM_EXT_INFO);
00367     sprintf(GEM_EXT_DEPS, "GEM_EXT_DEPS=%s", TMP_DEPS);
00368     putenv(GEM_EXT_DEPS);
00369     sprintf(GEM_EXT_BUGS, "GEM_EXT_BUGS=%s", TMP_BUGS);
00370     putenv(GEM_EXT_BUGS);
00371     sprintf(GEM_EXT_AUTHORS, "GEM_EXT_AUTHORS=%s", TMP_AUTHORS);
00372     putenv(GEM_EXT_AUTHORS);
00373 
00374     /* now need to register an exit function that unsets these env vars on termination! */
00375     atexit(&exit_tmp);
00376 
00377     /* check dependencies before compiling everything ... */
00378     check_dependencies(package, gisbase, grass_version);
00379 
00380     /* now execute Makefile in top-level directory */
00381     if (VERBOSE) {
00382         fprintf(stdout, "Running '%s':\n", MAKE_CMD);
00383         sprintf(sysstr, "%s -f Makefile", MAKE_CMD);
00384         error = system(sysstr);
00385     }
00386     else {
00387         fprintf(stdout, "Compiling...");
00388         sprintf(sysstr, "%s -f Makefile &> %s", MAKE_CMD, TMP_NULL);
00389         error = system(sysstr);
00390     }
00391     if (error == -1) {
00392         if (!VERBOSE) {
00393             print_error(ERR_MISSING_CMD,
00394                         "could not run '%s' do you have make tools installed?\n",
00395                         MAKE_CMD);
00396         }
00397     }
00398     if (error > 0) {
00399         print_error(ERR_COMPILE_EXT, "source code could not be compiled.\n \
00400                         Run again with option -v to see what is causing trouble.\n");
00401     }
00402     print_done();
00403 
00404     fprintf(stdout, "Installing...");
00405 
00406     /* check if an uninstall script exists */
00407     f = fopen("../uninstall", "r");
00408     if (f == NULL) {
00409         print_warning("error checking for uninstall script: %s\n \
00410                                 Uninstalling this extension may leave orphaned files on your system", strerror(errno));
00411     }
00412     else {
00413         /* it does: create a shell command to copy it upon installation */
00414         if (VERBOSE) {
00415             sprintf(tmp, "cp -vf ../uninstall %s/etc/uninstall.%s ;", gisbase,
00416                     pkg_short_name);
00417             strcpy(UNINSTALL_CMD, tmp);
00418         }
00419         else {
00420             sprintf(tmp, "cp -f ../uninstall %s/etc/uninstall.%s &> %s ;",
00421                     gisbase, pkg_short_name, TMP_NULL);
00422             strcpy(UNINSTALL_CMD, tmp);
00423         }
00424         fclose(f);
00425     }
00426 
00427     register_extension(gisbase, "src", pkg_short_name, pkg_major, pkg_minor,
00428                        pkg_revision);
00429 
00430     check_dependencies(package, gisbase, grass_version);
00431 
00432     /* starting with GRASS 6.1.cvs, d.m uses the same menu system as gis.m */
00433     if ((major == 6) && (minor < 1)) {
00434         register_entries_gisman(pkg_short_name, gisbase);
00435     }
00436 
00437     register_entries_gisman2(pkg_short_name, gisbase);
00438 
00439     register_html(pkg_short_name, gisbase, pkg_major, pkg_minor,
00440                   pkg_revision);
00441 
00442     /* create a shell command for the make install process and installation of extension.db */
00443     if (VERBOSE) {
00444         fprintf(stdout, "Running '%s install':\n", MAKE_CMD);
00445         sprintf(install_cmd, "%s -f Makefile install ; \
00446                                         cp -vf %s %s/etc/extensions.db ; chmod -v a+r %s/etc/extensions.db ;", MAKE_CMD, TMPDB, gisbase, gisbase);
00447     }
00448     else {
00449         sprintf(install_cmd, "%s -f Makefile -s install &> %s ; \
00450                                         cp -f %s %s/etc/extensions.db &> %s ; chmod a+r %s/etc/extensions.db &> %s ;", MAKE_CMD, TMP_NULL, TMPDB, gisbase, TMP_NULL, gisbase, TMP_NULL);
00451     }
00452 
00453 
00454     /* command to run post action script */
00455     if (VERBOSE) {
00456         sprintf(post_cmd, "sh ../post");
00457     }
00458     else {
00459         sprintf(post_cmd, "sh ../post &> %s", TMP_NULL);
00460     }
00461 
00462     /* make install */
00463     sprintf(tmp, "%s %s %s %s %s %s", install_cmd, UNINSTALL_CMD, GISMAN_CMD,
00464             GISMAN2_CMD, HTML_CMD, post_cmd);
00465 
00466     su(gisbase, tmp);
00467 
00468     print_done();
00469 }
00470 
00471 
00472 /*
00473    Install everything from a directory with pre-compiled binaries.
00474  */
00475 void bin_install(char *package, char *gisbase, char *bins,
00476                  char *pkg_short_name, int pkg_major, int pkg_minor,
00477                  int pkg_revision, char *grass_version)
00478 {
00479     char tmp[MAXSTR];
00480     char dir[MAXSTR];
00481     char install_cmd[MAXSTR];
00482     char post_cmd[MAXSTR];
00483     int error;
00484     struct stat buf;
00485     FILE *f;
00486 
00487     char *verstr;
00488     char *grass_major;
00489     char *grass_minor;
00490     char *grass_revision;
00491     int major, minor, revision;
00492 
00493     /* check for valid install directory */
00494     error = stat(gisbase, &buf);
00495     if (error < 0) {
00496         print_error(ERR_INSTALL_EXT, "installation directory invalid: %s\n",
00497                     strerror(errno));
00498     }
00499 
00500     /* export environment variables for GRASS 6 build system */
00501     /* target dir for installation */
00502     sprintf(GINSTALL_DST, "GINSTALL_DST=%s", gisbase);
00503     putenv(GINSTALL_DST);
00504     /*external include path */
00505     sprintf(tmp, "%s/include", gisbase);
00506     sprintf(GINSTALL_INC, "GINSTALL_INC=%s", tmp);
00507     putenv(GINSTALL_INC);
00508     /* external linker path */
00509     sprintf(tmp, "%s/lib", gisbase);
00510     sprintf(GINSTALL_LIB, "GINSTALL_LIB=%s", tmp);
00511     putenv(GINSTALL_LIB);
00512     /* path to install files */
00513     sprintf(GEM_GRASS_DIR, "GEM_GRASS_DIR=%s", gisbase);
00514     putenv(GEM_GRASS_DIR);
00515 
00516     /* extract GRASS major and minor version numbers */
00517     verstr = strdup(grass_version);
00518     grass_major = strtok(verstr, ".");
00519     grass_minor = strtok(NULL, ".");
00520     grass_revision = strtok(NULL, ".");
00521     major = strtol(grass_major, NULL, 10);
00522     minor = strtol(grass_minor, NULL, 10);
00523     revision = strtol(grass_revision, NULL, 10);
00524     free(verstr);
00525 
00526 
00527     /* now need to register an exit function that unsets these env vars on termination! */
00528     atexit(&exit_tmp);
00529 
00530     /* step into target directory and execute configure script */
00531     sprintf(dir, "%s/%s", basename(package), bins);
00532     error = chdir(dir);
00533     if (error < 0) {
00534         print_error(ERR_NO_ACCESS_EXT,
00535                     "extension file binaries in '%s' not accessible: %s\n",
00536                     package, strerror(errno));
00537     }
00538 
00539     /* export environment variables for generation of HTML documentation directories */
00540     /* by include/Make/Rules.make */
00541     sprintf(GEM_EXT_NAME, "GEM_EXT_NAME=%s", pkg_short_name);
00542     putenv(GEM_EXT_NAME);
00543     sprintf(tmp, "%i.%i.%i", pkg_major, pkg_minor, pkg_revision);
00544     sprintf(GEM_EXT_VERSION, "GEM_EXT_VERSION=%s", tmp);
00545     putenv(GEM_EXT_VERSION);
00546     /* dump extension info text into two plain ASCII files for inclusion in HTML man page */
00547     dump_html("../description", TMP_DESCR);
00548     dump_html("../info", TMP_INFO);
00549     dump_html("../depends", TMP_DEPS);
00550     dump_html("../bugs", TMP_BUGS);
00551     dump_html("../authors", TMP_AUTHORS);
00552     sprintf(GEM_EXT_DESCR, "GEM_EXT_DESCR=%s", TMP_DESCR);
00553     putenv(GEM_EXT_DESCR);
00554     sprintf(GEM_EXT_INFO, "GEM_EXT_INFO=%s", TMP_INFO);
00555     putenv(GEM_EXT_INFO);
00556     sprintf(GEM_EXT_DEPS, "GEM_EXT_DEPS=%s", TMP_DEPS);
00557     putenv(GEM_EXT_DEPS);
00558     sprintf(GEM_EXT_BUGS, "GEM_EXT_BUGS=%s", TMP_BUGS);
00559     putenv(GEM_EXT_BUGS);
00560     sprintf(GEM_EXT_AUTHORS, "GEM_EXT_AUTHORS=%s", TMP_AUTHORS);
00561     putenv(GEM_EXT_AUTHORS);
00562 
00563     /* now need to register an exit function that unsets these env vars on termination! */
00564     atexit(&exit_tmp);
00565 
00566     /* check dependencies before installing ... */
00567     check_dependencies(package, gisbase, grass_version);
00568 
00569     fprintf(stdout, "Installing...");
00570 
00571     /* check if an uninstall script exists */
00572     f = fopen("../uninstall", "r");
00573     if (f == NULL) {
00574         print_warning("error checking for uninstall script: %s\n \
00575                                 Uninstalling this extension may leave orphaned files on your system", strerror(errno));
00576     }
00577     else {
00578         /* it does: create a shell command to copy it upon installation */
00579         if (VERBOSE) {
00580             sprintf(tmp, "cp -vf ../uninstall %s/etc/uninstall.%s ;", gisbase,
00581                     pkg_short_name);
00582             strcpy(UNINSTALL_CMD, tmp);
00583         }
00584         else {
00585             sprintf(tmp, "cp -f ../uninstall %s/etc/uninstall.%s &> %s ;",
00586                     gisbase, pkg_short_name, TMP_NULL);
00587             strcpy(UNINSTALL_CMD, tmp);
00588         }
00589         fclose(f);
00590     }
00591 
00592     register_extension(gisbase, bins, pkg_short_name, pkg_major, pkg_minor,
00593                        pkg_revision);
00594     check_dependencies(package, gisbase, grass_version);
00595 
00596     /* starting with GRASS 6.1.cvs, d.m uses the same menu system as gis.m */
00597     if ((major == 6) && (minor < 1)) {
00598         register_entries_gisman(pkg_short_name, gisbase);
00599     }
00600 
00601     register_entries_gisman2(pkg_short_name, gisbase);
00602 
00603     register_html(pkg_short_name, gisbase, pkg_major, pkg_minor,
00604                   pkg_revision);
00605 
00606     /* create a shell command for the make install process and installation of extension.db */
00607     /* we will use a local copy of the make command for this (extension author has to supply it). */
00608     if (VERBOSE) {
00609         fprintf(stdout, "Running '%s install':\n", MAKE_CMD);
00610         sprintf(install_cmd, "bin/%s -f Makefile install ; \
00611                                         cp -vf %s %s/etc/extensions.db ; chmod -v a+r %s/etc/extensions.db ;", MAKE_CMD, TMPDB, gisbase, gisbase);
00612     }
00613     else {
00614         sprintf(install_cmd, "bin/%s -f Makefile -s install &> %s ; \
00615                                         cp -f %s %s/etc/extensions.db &> %s ; chmod a+r %s/etc/extensions.db &> %s ;", MAKE_CMD, TMP_NULL, TMPDB, gisbase, TMP_NULL, gisbase, TMP_NULL);
00616     }
00617 
00618     /* command to run post action script */
00619     if (VERBOSE) {
00620         sprintf(post_cmd, "sh ../post");
00621     }
00622     else {
00623         sprintf(post_cmd, "sh ../post &> %s", TMP_NULL);
00624     }
00625 
00626     /* make install */
00627     sprintf(tmp, "%s %s %s %s %s %s", install_cmd, UNINSTALL_CMD, GISMAN_CMD,
00628             GISMAN2_CMD, HTML_CMD, post_cmd);
00629 
00630     su(gisbase, tmp);
00631 
00632     print_done();
00633 }
00634 
00635 
00636 void test_install(char *package, char *gisbase, char *pkg_short_name,
00637                   int pkg_major, int pkg_minor, int pkg_revision,
00638                   char *grass_version)
00639 {
00640 
00641     char tmp[MAXSTR];
00642     char dir[MAXSTR];
00643     char sysstr[MAXSTR];
00644     int error;
00645     struct stat buf;
00646     FILE *f;
00647 
00648     char *verstr;
00649     char *grass_major;
00650     char *grass_minor;
00651     char *grass_revision;
00652     int major, minor, revision;
00653 
00654     /* check for valid install directory */
00655     error = stat(gisbase, &buf);
00656     if (error < 0) {
00657         print_error(ERR_INSTALL_EXT, "installation directory invalid: %s\n",
00658                     strerror(errno));
00659     }
00660 
00661     /* export environment variables for GRASS 6 build system */
00662     /* target dir for installation */
00663     sprintf(GINSTALL_DST, "GINSTALL_DST=%s", gisbase);
00664     putenv(GINSTALL_DST);
00665     /*external include path */
00666     sprintf(tmp, "%s/include", gisbase);
00667     sprintf(GINSTALL_INC, "GINSTALL_INC=%s", tmp);
00668     putenv(GINSTALL_INC);
00669     /* external linker path */
00670     sprintf(tmp, "%s/lib", gisbase);
00671     sprintf(GINSTALL_LIB, "GINSTALL_LIB=%s", tmp);
00672     putenv(GINSTALL_LIB);
00673     /* path to install files */
00674     sprintf(GEM_GRASS_DIR, "GEM_GRASS_DIR=%s", gisbase);
00675     putenv(GEM_GRASS_DIR);
00676 
00677     /* extract GRASS major and minor version numbers */
00678     verstr = strdup(grass_version);
00679     grass_major = strtok(verstr, ".");
00680     grass_minor = strtok(NULL, ".");
00681     grass_revision = strtok(NULL, ".");
00682     major = strtol(grass_major, NULL, 10);
00683     minor = strtol(grass_minor, NULL, 10);
00684     revision = strtol(grass_revision, NULL, 10);
00685     free(verstr);
00686 
00687     /* now need to register an exit function that unsets these env vars on termination! */
00688     atexit(&exit_tmp);
00689 
00690     /* step into target directory and execute configure script */
00691     sprintf(dir, "%s/src", basename(package));
00692     error = chdir(dir);
00693     if (error < 0) {
00694         print_error(ERR_NO_ACCESS_EXT,
00695                     "extension files in '%s' not accessible: %s\n", package,
00696                     strerror(errno));
00697     }
00698 
00699     if (!SKIP_CFG) {
00700         if (VERBOSE) {
00701             fprintf(stdout, "Running configure script:\n");
00702             sprintf(sysstr, "sh %s %s", CONFIG_CMD, CONFIG_OPTS);
00703             error = system(sysstr);
00704         }
00705         else {
00706             fprintf(stdout, "Configuring...");
00707             sprintf(sysstr, "sh %s %s --quiet &> %s", CONFIG_CMD, CONFIG_OPTS,
00708                     TMP_NULL);
00709             error = system(sysstr);
00710         }
00711         if (error == -1) {
00712             print_error(ERR_MISSING_CFG, "could not run configure script.\n");
00713         }
00714         if (error > 0) {
00715             print_error(ERR_CONFIGURE_EXT, "system configuration failed.\n");
00716         }
00717         print_done();
00718         print_cfg();
00719     }
00720 
00721     /* export environment variables for generation of HTML documentation directories */
00722     /* by include/Make/Rules.make */
00723     sprintf(GEM_EXT_NAME, "GEM_EXT_NAME=%s", pkg_short_name);
00724     putenv(GEM_EXT_NAME);
00725     sprintf(tmp, "%i.%i.%i", pkg_major, pkg_minor, pkg_revision);
00726     sprintf(GEM_EXT_VERSION, "GEM_EXT_VERSION=%s", tmp);
00727     putenv(GEM_EXT_VERSION);
00728     /* dump extension info text into two plain ASCII files for inclusion in HTML man page */
00729     dump_plain("../description", TMP_DESCR);
00730     dump_plain("../info", TMP_INFO);
00731     dump_plain("../depends", TMP_DEPS);
00732     dump_plain("../bugs", TMP_BUGS);
00733     dump_plain("../authors", TMP_AUTHORS);
00734     sprintf(GEM_EXT_DESCR, "GEM_EXT_DESCR=%s", TMP_DESCR);
00735     putenv(GEM_EXT_DESCR);
00736     sprintf(GEM_EXT_INFO, "GEM_EXT_INFO=%s", TMP_INFO);
00737     putenv(GEM_EXT_INFO);
00738     sprintf(GEM_EXT_DEPS, "GEM_EXT_DEPS=%s", TMP_DEPS);
00739     putenv(GEM_EXT_DEPS);
00740     sprintf(GEM_EXT_BUGS, "GEM_EXT_BUGS=%s", TMP_BUGS);
00741     putenv(GEM_EXT_BUGS);
00742     sprintf(GEM_EXT_AUTHORS, "GEM_EXT_AUTHORS=%s", TMP_AUTHORS);
00743     putenv(GEM_EXT_AUTHORS);
00744 
00745     /* now need to register an exit function that unsets these env vars on termination! */
00746     atexit(&exit_tmp);
00747 
00748     /* check dependencies before compiling everything ... */
00749     check_dependencies(package, gisbase, grass_version);
00750 
00751     /* now execute Makefile in top-level directory */
00752     if (VERBOSE) {
00753         fprintf(stdout, "Running '%s':\n", MAKE_CMD);
00754         sprintf(sysstr, "%s -f Makefile", MAKE_CMD);
00755         error = system(sysstr);
00756 
00757     }
00758     else {
00759         fprintf(stdout, "Compiling...");
00760         sprintf(sysstr, "%s -f Makefile &> %s", MAKE_CMD, TMP_NULL);
00761         error = system(sysstr);
00762     }
00763     if (error == -1) {
00764         if (!VERBOSE) {
00765             print_error(ERR_MISSING_CMD,
00766                         "could not run '%s' do you have make tools installed?\n",
00767                         MAKE_CMD);
00768         }
00769     }
00770     if (error > 0) {
00771         print_error(ERR_COMPILE_EXT, "source code could not be compiled.\n \
00772                         Run again with option -v to see what is causing trouble.\n");
00773     }
00774     print_done();
00775 
00776     fprintf(stdout, "Installing...");
00777 
00778     /* check if an uninstall script exists */
00779     f = fopen("../uninstall", "r");
00780     if (f == NULL) {
00781         print_warning("error checking for uninstall script: %s\n \
00782                                 Uninstalling this extension may leave orphaned files on your system", strerror(errno));
00783     }
00784     else {
00785         fclose(f);
00786     }
00787 
00788     register_extension(gisbase, "src", pkg_short_name, pkg_major, pkg_minor,
00789                        pkg_revision);
00790     check_dependencies(package, gisbase, grass_version);
00791 
00792     /* starting with GRASS 6.1.cvs, d.m uses the same menu system as gis.m */
00793     if ((major == 6) && (minor < 1)) {
00794         register_entries_gisman(pkg_short_name, gisbase);
00795     }
00796 
00797     register_entries_gisman2(pkg_short_name, gisbase);
00798 
00799     register_html(pkg_short_name, gisbase, pkg_major, pkg_minor,
00800                   pkg_revision);
00801 
00802     fprintf(stdout, "(skipping '%s install')...", MAKE_CMD);
00803 
00804     print_done();
00805 }
00806 
00807 
00808 /*
00809    Run the uninstall script that was (hopefully) provided by the packager.
00810    Check for unsatisfied dependencies and warn/abort accordingly.
00811  */
00812 void uninstall(char *package, char *pkg_short_name, char *gisbase,
00813                char *grass_version)
00814 {
00815     char tmp[MAXSTR];
00816     char script[MAXSTR];
00817     int error;
00818     struct stat buf;
00819     int no_script;
00820 
00821     char *verstr;
00822     char *grass_major;
00823     char *grass_minor;
00824     char *grass_revision;
00825     int major, minor, revision;
00826 
00827     fprintf(stdout, "Un-installing...");
00828 
00829     /* export environment variables for uninstall script */
00830     sprintf(UNINSTALL_BASE, "UNINSTALL_BASE=%s", gisbase);
00831     putenv(UNINSTALL_BASE);
00832 
00833     /* extract GRASS major and minor version numbers */
00834     verstr = strdup(grass_version);
00835     grass_major = strtok(verstr, ".");
00836     grass_minor = strtok(NULL, ".");
00837     grass_revision = strtok(NULL, ".");
00838     major = strtol(grass_major, NULL, 10);
00839     minor = strtol(grass_minor, NULL, 10);
00840     revision = strtol(grass_revision, NULL, 10);
00841     free(verstr);
00842 
00843     /* now need to register an exit function that unsets these env vars on termination! */
00844     atexit(&exit_tmp);
00845 
00846     /* deregister extension  */
00847     deregister_extension(package, pkg_short_name, gisbase);
00848 
00849     /* deregister menu entries in GIS Manager */
00850     /* starting with GRASS 6.1.cvs, d.m uses the same menu system as gis.m */
00851     if ((major == 6) && (minor < 1)) {
00852         error = deregister_entries_gisman(pkg_short_name, gisbase);
00853         if (error == -1) {
00854             print_warning("GIS Manager menu entries could not be removed.\n");
00855             strcpy(GISMAN_CMD, "");
00856         }
00857         if (error == 0) {
00858             print_warning("no entries found to remove from GIS Manager.\n");
00859             strcpy(GISMAN_CMD, "");
00860         }
00861     }
00862 
00863     /* deregister menu entries in GIS Manager 2 */
00864     deregister_entries_gisman2(pkg_short_name, gisbase);
00865 
00866     /* deregister HTML entries and delete man pages */
00867     deregister_html(pkg_short_name, gisbase);
00868 
00869     /* check if an uninstall script exists */
00870     sprintf(script, "%s/etc/uninstall.%s", gisbase, pkg_short_name);
00871     no_script = 0;
00872     error = stat(script, &buf);
00873     if (error < 0) {
00874         print_warning("no uninstall script available for this extension.\n \
00875                         Unneeded files may have been left on your system.\n");
00876         no_script = 1;
00877     }
00878     if (no_script) {
00879         print_warning("error checking for uninstall script: %s\n \
00880                                 Uninstalling this extension may leave orphaned files on your system", strerror(errno));
00881     }
00882     else {
00883         /* it does: create a shell command to execute and then delete it upon de-installation */
00884         if (VERBOSE) {
00885             sprintf(tmp, "sh %s ; rm -vf %s ; \
00886                                                         rm -vrf %s/docs/extensions/%s ; rm -vf %s/etc/dm/gem-entries/%s ; \
00887                                                         cp -vf %s %s/etc/extensions.db ; chmod -v a+r %s/etc/extensions.db ;", script, script, gisbase, pkg_short_name, gisbase, pkg_short_name, TMPDB, gisbase, gisbase);
00888             strcpy(UNINSTALL_CMD, tmp);
00889         }
00890         else {
00891             sprintf(tmp, "sh %s &> %s ; rm -vf %s &> %s ; \
00892                                                         rm -vrf %s/docs/extensions/%s &> %s ; rm -vf %s/etc/dm/gem-entries/%s &> %s ; \
00893                                                         cp -vf %s %s/etc/extensions.db &> %s ; chmod -v a+r %s/etc/extensions.db &> %s ;", script, TMP_NULL, script, TMP_NULL, gisbase, pkg_short_name, TMP_NULL, gisbase, pkg_short_name, TMP_NULL, TMPDB, gisbase, TMP_NULL, gisbase, TMP_NULL);
00894             strcpy(UNINSTALL_CMD, tmp);
00895         }
00896     }
00897 
00898     /* do the uninstall! */
00899     sprintf(tmp, "%s %s %s", UNINSTALL_CMD, GISMAN_CMD, HTML_CMD);
00900 
00901     su(gisbase, tmp);
00902 
00903     print_done();
00904 }
00905 
00906 
00907 int source_clean(char *package)
00908 {
00909     char dir[MAXSTR];
00910     char sysstr[MAXSTR];
00911     int error;
00912 
00913     /* step into target directory */
00914     sprintf(dir, "%s/src", basename(package));
00915     error = chdir(dir);
00916     if (error < 0) {
00917         print_error(ERR_NO_ACCESS_EXT, "extension '%s' not accessible: ",
00918                     package);
00919     }
00920 
00921     /* now execute Makefile and 'clean' from top-level directory */
00922     if (VERBOSE) {
00923         fprintf(stdout, "Running '%s clean':\n", MAKE_CMD);
00924         sprintf(sysstr, "%s -f Makefile clean", MAKE_CMD);
00925         error = system(sysstr);
00926     }
00927     else {
00928         fprintf(stdout, "Cleaning up...");
00929         sprintf(sysstr, "%s -f Makefile -s clean &> %s", MAKE_CMD, TMP_NULL);
00930         error = system(sysstr);
00931     }
00932 
00933     if (error == -1) {
00934         print_error(ERR_MISSING_CMD,
00935                     "could not run '%s clean' do you have make tools installed?\n",
00936                     MAKE_CMD);
00937     }
00938     else {
00939         print_done();
00940     }
00941 
00942     /* run post action script */
00943     system("sh ../post");
00944 
00945     return (0);
00946 }
00947 
00948 
00949 /* 
00950    Restores HTML links and GIS Manager menus, e.g. after an update of GRASS
00951  */
00952 void restore(char *gisbase, char *grass_version)
00953 {
00954     int num_restored;
00955     char tmp[MAXSTR];
00956 
00957     char *verstr;
00958     char *grass_major;
00959     char *grass_minor;
00960     char *grass_revision;
00961     int major, minor, revision;
00962 
00963 
00964     /* extract GRASS major and minor version numbers */
00965     verstr = strdup(grass_version);
00966     grass_major = strtok(verstr, ".");
00967     grass_minor = strtok(NULL, ".");
00968     grass_revision = strtok(NULL, ".");
00969     major = strtol(grass_major, NULL, 10);
00970     minor = strtol(grass_minor, NULL, 10);
00971     revision = strtol(grass_revision, NULL, 10);
00972     free(verstr);
00973 
00974     fprintf(stdout, "Restoring...");
00975 
00976     /* starting with GRASS 6.1.cvs, d.m uses the same menu system as gis.m */
00977     if ((major == 6) && (minor < 1)) {
00978         num_restored = restore_entries_gisman(gisbase);
00979         if (VERBOSE) {
00980             fprintf(stdout, "\nRestored entries for GIS Manager: %i\n",
00981                     num_restored);
00982         }
00983     }
00984 
00985     num_restored = restore_html(gisbase);
00986     if (VERBOSE) {
00987         fprintf(stdout, "\nRestored links in index.hml: %i\n", num_restored);
00988     }
00989 
00990     if (num_restored > 0) {
00991         /* copy restored files to GRASS install tree */
00992         if (VERBOSE) {
00993             sprintf(tmp,
00994                     "cp -f %s %s/etc/dm/menu.tcl ; chmod a+r %s/etc/dm/menu.tcl ; \
00995                                                         cp -f %s %s/docs/html/index.html ; chmod a+r %s/docs/html/index.html",
00996                     TMP_GISMAN, gisbase, gisbase, TMP_HTML, gisbase, gisbase);
00997         }
00998         else {
00999             sprintf(tmp,
01000                     "cp -f %s %s/etc/dm/menu.tcl ; chmod a+r %s/etc/dm/menu.tcl &> %s ; \
01001                                                         cp -f %s %s/docs/html/index.html ; chmod a+r %s/docs/html/index.html",
01002                     TMP_GISMAN, gisbase, gisbase, TMP_NULL, TMP_HTML, gisbase,
01003                     gisbase);
01004         }
01005 
01006         su(gisbase, tmp);
01007 
01008     }
01009 
01010     if (num_restored == 0) {
01011         print_error(ERR_RESTORE, "could not find anything to restore.\n");
01012     }
01013     else {
01014         print_done();
01015     }
01016 }
01017 
01018 
01019 /*
01020    List all extensions installed on system with versions and dependencies
01021  */
01022 void list_extensions(char *gisbase)
01023 {
01024     char file[MAXSTR];
01025     FILE *f_in;
01026 
01027     fprintf(stdout, "\nExtensions in '%s' (name, version, type, depends):\n",
01028             gisbase);
01029 
01030     /* check, if extensions.db exists and is readable */
01031     sprintf(file, "%s/etc/extensions.db", gisbase);
01032     f_in = fopen(file, "r");
01033     if (f_in == NULL) {
01034         if (errno == ENOENT) {
01035             /* file does not yet exist */
01036             fprintf(stderr, "NONE.\n");
01037             fclose(f_in);
01038             exit(0);
01039         }
01040         else {
01041             /* sth. strange happened */
01042             fclose(f_in);
01043             print_error(ERR_LIST, "checking for file '%s': %s\n", file,
01044                         strerror(errno));
01045         }
01046     }
01047     fclose(f_in);
01048 
01049     dump_ascii(file, "");
01050 }
01051 
01052 
01053 /*
01054    A bit of a misnomer: this does not actually run the post
01055    script but it exports all necessary env vars.
01056  */
01057 void run_post(char *package, int action, char *bins, char *gisbase)
01058 {
01059     char tmp[MAXSTR];
01060     char tmp2[MAXSTR];
01061 
01062     switch (action) {
01063     case INSTALL:
01064         sprintf(GEM_ACTION, "GEM_ACTION=INSTALL");
01065         break;
01066     case BIN_INSTALL:
01067         sprintf(GEM_ACTION, "GEM_ACTION=INSTALL");
01068         break;
01069     case QUERY:
01070         sprintf(GEM_ACTION, "GEM_ACTION=QUERY");
01071         break;
01072     case CLEAN:
01073         sprintf(GEM_ACTION, "GEM_ACTION=CLEAN");
01074         break;
01075     case LICENSE:
01076         sprintf(GEM_ACTION, "GEM_ACTION=LICENSE");
01077         break;
01078     case DETAILS:
01079         sprintf(GEM_ACTION, "GEM_ACTION=DETAILS");
01080         break;
01081     default:
01082         break;
01083     }
01084     putenv(GEM_ACTION);
01085 
01086     if (gisbase != NULL) {
01087         sprintf(INSTALL_BASE, "INSTALL_BASE=%s", gisbase);
01088     }
01089     else {
01090         sprintf(INSTALL_BASE, "INSTALL_BASE=UNDEFINED");
01091     }
01092     putenv(INSTALL_BASE);
01093 
01094     /* export absolute path to current working dir */
01095     getcwd(tmp, MAXSTR);
01096     sprintf(tmp2, "%s/%s/src", tmp, basename(package));
01097     sprintf(EXT_BASE, "EXT_BASE=%s", tmp2);
01098     putenv(EXT_BASE);
01099 
01100     if (bins == NULL) {
01101         sprintf(INSTALL_TYPE, "INSTALL_TYPE=src");
01102     }
01103     else {
01104         sprintf(INSTALL_TYPE, "INSTALL_TYPE=%s", bins);
01105     }
01106     putenv(INSTALL_TYPE);
01107 
01108     sprintf(tmp, "%i", FORCE);
01109     sprintf(GEM_FORCE, "GEM_FORCE=%s", tmp);
01110     putenv(GEM_FORCE);
01111 
01112     sprintf(tmp, "%i", VERBOSE);
01113     sprintf(GEM_VERBOSE, "GEM_VERBOSE=%s", tmp);
01114     putenv(GEM_VERBOSE);
01115 
01116     sprintf(GEM_GUI, "GEM_GUI=0");
01117     putenv(GEM_GUI);
01118 
01119 
01120     /* now need to register an exit function that unsets these env vars on termination! */
01121     atexit(&exit_tmp);
01122 }
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines