GRASS Programmer's Manual
6.4.2(2012)
|
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 }