actions.c 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123
  1. /***************************************************************************
  2. * actions.c
  3. *
  4. * Mon Apr 18 15:25:54 2005
  5. * Copyright 2005 Benjamin Ducke
  6. ****************************************************************************/
  7. /*
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU Library General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  21. */
  22. #include "globals.h"
  23. #include <fcntl.h>
  24. void check_extension(char *package, char *name, int *major, int *minor,
  25. int *revision)
  26. {
  27. int error;
  28. char tmp[MAXSTR] = "";
  29. FILE *f;
  30. fprintf(stdout, "Checking extension ...");
  31. sprintf(tmp, "%s", package);
  32. error = chdir(tmp);
  33. if (error < 0) {
  34. print_error(ERR_NO_ACCESS_EXT, "extension '%s' not accessible: %s\n",
  35. package, strerror(errno));
  36. }
  37. /* get file id */
  38. f = fopen("id", "r");
  39. if (f == NULL) {
  40. print_error(ERR_INVALID_EXT, "'id' file not readable.\n");
  41. }
  42. else {
  43. fscanf(f, "%[<GRASS extension package>] ", tmp);
  44. if (strcmp("<GRASS extension package>", tmp)) {
  45. fclose(f);
  46. print_error(ERR_INVALID_EXT, "unknown file identifier.\n");
  47. }
  48. }
  49. fclose(f);
  50. get_package_name(".", name);
  51. /* get extension version */
  52. f = fopen("version", "r");
  53. if (f == NULL) {
  54. print_error(ERR_INVALID_EXT, "'version' file not readable.\n");
  55. }
  56. else {
  57. nc_fgets_nb(tmp, MAXSTR, f);
  58. *minor = 0;
  59. *revision = 0;
  60. error = sscanf(tmp, "%i.%i.%i", major, minor, revision);
  61. if (error < 1) {
  62. fclose(f);
  63. print_error(ERR_INVALID_EXT,
  64. "invalid or missing version information.\n");
  65. }
  66. }
  67. print_done();
  68. chdir("..");
  69. fclose(f);
  70. }
  71. /*
  72. decompresses extension file and returns path to the temporary directory where the
  73. extension has been stored.
  74. */
  75. void unpack_extension(char *package)
  76. {
  77. int error;
  78. int fd;
  79. char tmp[MAXSTR];
  80. int ftype;
  81. fprintf(stdout, "Uncompressing files...");
  82. /* TODO: Do not hardcode temp paths */
  83. strcpy(TMPDIR, "/tmp/grass.extension.XXXXXX"); /* tmpdir is a global variable */
  84. mkstemp(TMPDIR);
  85. fd = open(TMPDIR, O_CREAT);
  86. if (fd == -1) {
  87. print_error(ERR_UNPACK_EXT,
  88. "could not create temp directory name: %s",
  89. strerror(errno));
  90. exit(ERR_UNPACK_EXT);
  91. }
  92. if (VERBOSE) {
  93. fprintf(stdout, "\nUncompressing to: %s.\n", TMPDIR);
  94. }
  95. /* remove tmp file and create a dir with the same name */
  96. close(fd);
  97. remove(TMPDIR);
  98. mkdir_s(TMPDIR, "0700");
  99. atexit(&exit_tmp); /* now need to register an at exit func to remove tmpdir automatically! */
  100. /* uncompress extension to TMPDIR */
  101. /* 1. copy file */
  102. sprintf(tmp, "cp %s %s", package, TMPDIR);
  103. error = system(tmp);
  104. if (error < 0) {
  105. print_error(ERR_UNPACK_EXT,
  106. "could not copy extension files to temp dir.\n");
  107. exit(ERR_UNPACK_EXT);
  108. }
  109. /* see what type of archive it is */
  110. ftype = check_filetype(package);
  111. if (ftype == TYPE_UNKNOWN) {
  112. print_warning
  113. ("file name not '.tar.gz', '.tgz', '.tar.bz2', '.tbz' or '.zip'. Assuming '.tgz'.\n");
  114. ftype = TAR_GZIP;
  115. }
  116. if (ftype == TAR_GZIP) {
  117. if (VERBOSE) {
  118. sprintf(tmp, "tar -xzvf %s/%s -C %s", TMPDIR, basename(package),
  119. TMPDIR);
  120. }
  121. else {
  122. sprintf(tmp, "tar -xzf %s/%s -C %s", TMPDIR, basename(package),
  123. TMPDIR);
  124. }
  125. }
  126. if (ftype == TAR_BZIP2) {
  127. if (VERBOSE) {
  128. sprintf(tmp, "tar -xjvf %s/%s -C %s", TMPDIR, basename(package),
  129. TMPDIR);
  130. }
  131. else {
  132. sprintf(tmp, "tar -xjvf %s/%s -C %s", TMPDIR, basename(package),
  133. TMPDIR);
  134. }
  135. }
  136. if (ftype == ZIP) {
  137. if (VERBOSE) {
  138. sprintf(tmp, "unzip %s/%s -d %s", TMPDIR, basename(package),
  139. TMPDIR);
  140. }
  141. else {
  142. sprintf(tmp, "unzip -qq %s/%s -d %s", TMPDIR, basename(package),
  143. TMPDIR);
  144. }
  145. }
  146. if (ftype == TAR) {
  147. if (VERBOSE) {
  148. sprintf(tmp, "tar -xvf %s/%s -C %s", TMPDIR, basename(package),
  149. TMPDIR);
  150. }
  151. else {
  152. sprintf(tmp, "tar -xf %s/%s -C %s", TMPDIR, basename(package),
  153. TMPDIR);
  154. }
  155. }
  156. error = system(tmp);
  157. if (error < 0) {
  158. if (ftype == TAR_GZIP) {
  159. print_error(ERR_UNPACK_EXT,
  160. "could not extract files using 'tar' and 'gzip'. \n \
  161. Extract manually using 'tar -xzvf %s'.\n", package);
  162. }
  163. if (ftype == TAR_BZIP2) {
  164. print_error(ERR_UNPACK_EXT, "could not extract files using 'tar' and 'bunzip2'.\n \
  165. Extract manually using 'tar -xjvf %s'.\n",
  166. package);
  167. }
  168. if (ftype == ZIP) {
  169. print_error(ERR_UNPACK_EXT, "could not extract files using 'unzip'.\n \
  170. Extract manually using 'unzip %s'.\n",
  171. package);
  172. }
  173. exit(ERR_UNPACK_EXT);
  174. }
  175. print_done();
  176. }
  177. void query_extension(char *package, char *name, int major, int minor,
  178. int revision, char *short_name, char *invocation,
  179. char *org_name)
  180. {
  181. int error;
  182. char tmp[MAXSTR];
  183. sprintf(tmp, "%s", basename(package));
  184. error = chdir(tmp);
  185. if (error < 0) {
  186. print_error(ERR_NO_ACCESS_EXT, "extension '%s' not accessible: %s\n",
  187. package, strerror(errno));
  188. }
  189. fprintf(stdout, "\nExtension '%s', version %i.%i.%i\n\n", name, major,
  190. minor, revision);
  191. dump_ascii("description", "Description");
  192. dump_ascii("commands", "Commands provided");
  193. dump_ascii("libs", "Libraries provided");
  194. dump_ascii("headers", "Header files provided");
  195. dump_ascii("depends", "Dependencies");
  196. dump_ascii("bugs", "Bugs");
  197. sprintf(tmp, "../%s", package);
  198. list_binaries(tmp);
  199. dump_ascii("authors", "Author(s)");
  200. fprintf(stdout, "Type '%s -d %s' to see more detailed information.\n",
  201. invocation, org_name);
  202. fprintf(stdout, "Type '%s -l %s' to see copyright information.\n",
  203. invocation, org_name);
  204. /* run post action script */
  205. system("sh post");
  206. exit(0);
  207. }
  208. /*
  209. Dump contents of config.msg to screen
  210. */
  211. void print_cfg(void)
  212. {
  213. FILE *fp;
  214. char line[MAXSTR];
  215. fp = fopen("config.msg", "r");
  216. if (fp != NULL) {
  217. fprintf(stdout, "\nResult of configuration: \n");
  218. while (fgets(line, MAXSTR, fp) != NULL) {
  219. fprintf(stdout, "%s", line);
  220. }
  221. fprintf(stdout, "\n");
  222. }
  223. /* remove file afterward */
  224. remove("config.msg");
  225. }
  226. /*
  227. */
  228. void source_install(char *package, char *gisbase, char *pkg_short_name,
  229. int pkg_major, int pkg_minor, int pkg_revision,
  230. char *grass_version)
  231. {
  232. char tmp[MAXSTR];
  233. char dir[MAXSTR];
  234. char install_cmd[MAXSTR];
  235. char post_cmd[MAXSTR];
  236. char sysstr[MAXSTR];
  237. int error;
  238. struct stat buf;
  239. FILE *f;
  240. char *verstr;
  241. char *grass_major;
  242. char *grass_minor;
  243. char *grass_revision;
  244. int major, minor, revision;
  245. /* check for valid install directory */
  246. error = stat(gisbase, &buf);
  247. if (error < 0) {
  248. print_error(ERR_INSTALL_EXT, "installation directory invalid: %s\n",
  249. strerror(errno));
  250. }
  251. /* export environment variables for GRASS 6 build system */
  252. /* target dir for installation */
  253. sprintf(GINSTALL_DST, "GINSTALL_DST=%s", gisbase);
  254. putenv(GINSTALL_DST);
  255. /*external include path */
  256. sprintf(tmp, "%s/include", gisbase);
  257. sprintf(GINSTALL_INC, "GINSTALL_INC=%s", tmp);
  258. putenv(GINSTALL_INC);
  259. /* external linker path */
  260. sprintf(tmp, "%s/lib", gisbase);
  261. sprintf(GINSTALL_LIB, "GINSTALL_LIB=%s", tmp);
  262. putenv(GINSTALL_LIB);
  263. /* path to install files */
  264. sprintf(GEM_GRASS_DIR, "GEM_GRASS_DIR=%s", gisbase);
  265. putenv(GEM_GRASS_DIR);
  266. /* extract GRASS major and minor version numbers */
  267. verstr = strdup(grass_version);
  268. grass_major = strtok(verstr, ".");
  269. grass_minor = strtok(NULL, ".");
  270. grass_revision = strtok(NULL, ".");
  271. major = strtol(grass_major, NULL, 10);
  272. minor = strtol(grass_minor, NULL, 10);
  273. revision = strtol(grass_revision, NULL, 10);
  274. free(verstr);
  275. /* now need to register an exit function that unsets these env vars on termination! */
  276. atexit(&exit_tmp);
  277. /* step into target directory and execute configure script */
  278. sprintf(dir, "%s/src", basename(package));
  279. error = chdir(dir);
  280. if (error < 0) {
  281. print_error(ERR_NO_ACCESS_EXT,
  282. "extension files in '%s' not accessible: %s\n", package,
  283. strerror(errno));
  284. }
  285. if (!SKIP_CFG) {
  286. if (VERBOSE) {
  287. fprintf(stdout, "Running configure script:\n");
  288. sprintf(sysstr, "sh %s %s", CONFIG_CMD, CONFIG_OPTS);
  289. error = system(sysstr);
  290. }
  291. else {
  292. fprintf(stdout, "Configuring...");
  293. sprintf(sysstr, "sh %s %s --quiet &> %s", CONFIG_CMD, CONFIG_OPTS,
  294. TMP_NULL);
  295. error = system(sysstr);
  296. }
  297. if (error == -1) {
  298. print_error(ERR_MISSING_CFG, "could not run configure script.\n");
  299. }
  300. if (error > 0) {
  301. print_error(ERR_CONFIGURE_EXT, "system configuration failed.\n");
  302. }
  303. print_done();
  304. print_cfg();
  305. }
  306. /* export environment variables for generation of HTML documentation directories */
  307. /* by include/Make/Rules.make */
  308. sprintf(GEM_EXT_NAME, "GEM_EXT_NAME=%s", pkg_short_name);
  309. putenv(GEM_EXT_NAME);
  310. sprintf(tmp, "%i.%i.%i", pkg_major, pkg_minor, pkg_revision);
  311. sprintf(GEM_EXT_VERSION, "GEM_EXT_VERSION=%s", tmp);
  312. putenv(GEM_EXT_VERSION);
  313. /* dump extension info text into two plain ASCII files for inclusion in HTML man page */
  314. dump_html("../description", TMP_DESCR);
  315. dump_html("../info", TMP_INFO);
  316. dump_html("../depends", TMP_DEPS);
  317. dump_html("../bugs", TMP_BUGS);
  318. dump_html("../authors", TMP_AUTHORS);
  319. sprintf(GEM_EXT_DESCR, "GEM_EXT_DESCR=%s", TMP_DESCR);
  320. putenv(GEM_EXT_DESCR);
  321. sprintf(GEM_EXT_INFO, "GEM_EXT_INFO=%s", TMP_INFO);
  322. putenv(GEM_EXT_INFO);
  323. sprintf(GEM_EXT_DEPS, "GEM_EXT_DEPS=%s", TMP_DEPS);
  324. putenv(GEM_EXT_DEPS);
  325. sprintf(GEM_EXT_BUGS, "GEM_EXT_BUGS=%s", TMP_BUGS);
  326. putenv(GEM_EXT_BUGS);
  327. sprintf(GEM_EXT_AUTHORS, "GEM_EXT_AUTHORS=%s", TMP_AUTHORS);
  328. putenv(GEM_EXT_AUTHORS);
  329. /* now need to register an exit function that unsets these env vars on termination! */
  330. atexit(&exit_tmp);
  331. /* check dependencies before compiling everything ... */
  332. check_dependencies(package, gisbase, grass_version);
  333. /* now execute Makefile in top-level directory */
  334. if (VERBOSE) {
  335. fprintf(stdout, "Running '%s':\n", MAKE_CMD);
  336. sprintf(sysstr, "%s -f Makefile", MAKE_CMD);
  337. error = system(sysstr);
  338. }
  339. else {
  340. fprintf(stdout, "Compiling...");
  341. sprintf(sysstr, "%s -f Makefile &> %s", MAKE_CMD, TMP_NULL);
  342. error = system(sysstr);
  343. }
  344. if (error == -1) {
  345. if (!VERBOSE) {
  346. print_error(ERR_MISSING_CMD,
  347. "could not run '%s' do you have make tools installed?\n",
  348. MAKE_CMD);
  349. }
  350. }
  351. if (error > 0) {
  352. print_error(ERR_COMPILE_EXT, "source code could not be compiled.\n \
  353. Run again with option -v to see what is causing trouble.\n");
  354. }
  355. print_done();
  356. fprintf(stdout, "Installing...");
  357. /* check if an uninstall script exists */
  358. f = fopen("../uninstall", "r");
  359. if (f == NULL) {
  360. print_warning("error checking for uninstall script: %s\n \
  361. Uninstalling this extension may leave orphaned files on your system", strerror(errno));
  362. }
  363. else {
  364. /* it does: create a shell command to copy it upon installation */
  365. if (VERBOSE) {
  366. sprintf(tmp, "cp -vf ../uninstall %s/etc/uninstall.%s ;", gisbase,
  367. pkg_short_name);
  368. strcpy(UNINSTALL_CMD, tmp);
  369. }
  370. else {
  371. sprintf(tmp, "cp -f ../uninstall %s/etc/uninstall.%s &> %s ;",
  372. gisbase, pkg_short_name, TMP_NULL);
  373. strcpy(UNINSTALL_CMD, tmp);
  374. }
  375. fclose(f);
  376. }
  377. register_extension(gisbase, "src", pkg_short_name, pkg_major, pkg_minor,
  378. pkg_revision);
  379. check_dependencies(package, gisbase, grass_version);
  380. /* starting with GRASS 6.1.cvs, d.m uses the same menu system as gis.m */
  381. if ((major == 6) && (minor < 1)) {
  382. register_entries_gisman(pkg_short_name, gisbase);
  383. }
  384. register_entries_gisman2(pkg_short_name, gisbase);
  385. register_html(pkg_short_name, gisbase, pkg_major, pkg_minor,
  386. pkg_revision);
  387. /* create a shell command for the make install process and installation of extension.db */
  388. if (VERBOSE) {
  389. fprintf(stdout, "Running '%s install':\n", MAKE_CMD);
  390. sprintf(install_cmd, "%s -f Makefile install ; \
  391. cp -vf %s %s/etc/extensions.db ; chmod -v a+r %s/etc/extensions.db ;", MAKE_CMD, TMPDB, gisbase, gisbase);
  392. }
  393. else {
  394. sprintf(install_cmd, "%s -f Makefile -s install &> %s ; \
  395. 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);
  396. }
  397. /* command to run post action script */
  398. if (VERBOSE) {
  399. sprintf(post_cmd, "sh ../post");
  400. }
  401. else {
  402. sprintf(post_cmd, "sh ../post &> %s", TMP_NULL);
  403. }
  404. /* make install */
  405. sprintf(tmp, "%s %s %s %s %s %s", install_cmd, UNINSTALL_CMD, GISMAN_CMD,
  406. GISMAN2_CMD, HTML_CMD, post_cmd);
  407. su(gisbase, tmp);
  408. print_done();
  409. }
  410. /*
  411. Install everything from a directory with pre-compiled binaries.
  412. */
  413. void bin_install(char *package, char *gisbase, char *bins,
  414. char *pkg_short_name, int pkg_major, int pkg_minor,
  415. int pkg_revision, char *grass_version)
  416. {
  417. char tmp[MAXSTR];
  418. char dir[MAXSTR];
  419. char install_cmd[MAXSTR];
  420. char post_cmd[MAXSTR];
  421. int error;
  422. struct stat buf;
  423. FILE *f;
  424. char *verstr;
  425. char *grass_major;
  426. char *grass_minor;
  427. char *grass_revision;
  428. int major, minor, revision;
  429. /* check for valid install directory */
  430. error = stat(gisbase, &buf);
  431. if (error < 0) {
  432. print_error(ERR_INSTALL_EXT, "installation directory invalid: %s\n",
  433. strerror(errno));
  434. }
  435. /* export environment variables for GRASS 6 build system */
  436. /* target dir for installation */
  437. sprintf(GINSTALL_DST, "GINSTALL_DST=%s", gisbase);
  438. putenv(GINSTALL_DST);
  439. /*external include path */
  440. sprintf(tmp, "%s/include", gisbase);
  441. sprintf(GINSTALL_INC, "GINSTALL_INC=%s", tmp);
  442. putenv(GINSTALL_INC);
  443. /* external linker path */
  444. sprintf(tmp, "%s/lib", gisbase);
  445. sprintf(GINSTALL_LIB, "GINSTALL_LIB=%s", tmp);
  446. putenv(GINSTALL_LIB);
  447. /* path to install files */
  448. sprintf(GEM_GRASS_DIR, "GEM_GRASS_DIR=%s", gisbase);
  449. putenv(GEM_GRASS_DIR);
  450. /* extract GRASS major and minor version numbers */
  451. verstr = strdup(grass_version);
  452. grass_major = strtok(verstr, ".");
  453. grass_minor = strtok(NULL, ".");
  454. grass_revision = strtok(NULL, ".");
  455. major = strtol(grass_major, NULL, 10);
  456. minor = strtol(grass_minor, NULL, 10);
  457. revision = strtol(grass_revision, NULL, 10);
  458. free(verstr);
  459. /* now need to register an exit function that unsets these env vars on termination! */
  460. atexit(&exit_tmp);
  461. /* step into target directory and execute configure script */
  462. sprintf(dir, "%s/%s", basename(package), bins);
  463. error = chdir(dir);
  464. if (error < 0) {
  465. print_error(ERR_NO_ACCESS_EXT,
  466. "extension file binaries in '%s' not accessible: %s\n",
  467. package, strerror(errno));
  468. }
  469. /* export environment variables for generation of HTML documentation directories */
  470. /* by include/Make/Rules.make */
  471. sprintf(GEM_EXT_NAME, "GEM_EXT_NAME=%s", pkg_short_name);
  472. putenv(GEM_EXT_NAME);
  473. sprintf(tmp, "%i.%i.%i", pkg_major, pkg_minor, pkg_revision);
  474. sprintf(GEM_EXT_VERSION, "GEM_EXT_VERSION=%s", tmp);
  475. putenv(GEM_EXT_VERSION);
  476. /* dump extension info text into two plain ASCII files for inclusion in HTML man page */
  477. dump_html("../description", TMP_DESCR);
  478. dump_html("../info", TMP_INFO);
  479. dump_html("../depends", TMP_DEPS);
  480. dump_html("../bugs", TMP_BUGS);
  481. dump_html("../authors", TMP_AUTHORS);
  482. sprintf(GEM_EXT_DESCR, "GEM_EXT_DESCR=%s", TMP_DESCR);
  483. putenv(GEM_EXT_DESCR);
  484. sprintf(GEM_EXT_INFO, "GEM_EXT_INFO=%s", TMP_INFO);
  485. putenv(GEM_EXT_INFO);
  486. sprintf(GEM_EXT_DEPS, "GEM_EXT_DEPS=%s", TMP_DEPS);
  487. putenv(GEM_EXT_DEPS);
  488. sprintf(GEM_EXT_BUGS, "GEM_EXT_BUGS=%s", TMP_BUGS);
  489. putenv(GEM_EXT_BUGS);
  490. sprintf(GEM_EXT_AUTHORS, "GEM_EXT_AUTHORS=%s", TMP_AUTHORS);
  491. putenv(GEM_EXT_AUTHORS);
  492. /* now need to register an exit function that unsets these env vars on termination! */
  493. atexit(&exit_tmp);
  494. /* check dependencies before installing ... */
  495. check_dependencies(package, gisbase, grass_version);
  496. fprintf(stdout, "Installing...");
  497. /* check if an uninstall script exists */
  498. f = fopen("../uninstall", "r");
  499. if (f == NULL) {
  500. print_warning("error checking for uninstall script: %s\n \
  501. Uninstalling this extension may leave orphaned files on your system", strerror(errno));
  502. }
  503. else {
  504. /* it does: create a shell command to copy it upon installation */
  505. if (VERBOSE) {
  506. sprintf(tmp, "cp -vf ../uninstall %s/etc/uninstall.%s ;", gisbase,
  507. pkg_short_name);
  508. strcpy(UNINSTALL_CMD, tmp);
  509. }
  510. else {
  511. sprintf(tmp, "cp -f ../uninstall %s/etc/uninstall.%s &> %s ;",
  512. gisbase, pkg_short_name, TMP_NULL);
  513. strcpy(UNINSTALL_CMD, tmp);
  514. }
  515. fclose(f);
  516. }
  517. register_extension(gisbase, bins, pkg_short_name, pkg_major, pkg_minor,
  518. pkg_revision);
  519. check_dependencies(package, gisbase, grass_version);
  520. /* starting with GRASS 6.1.cvs, d.m uses the same menu system as gis.m */
  521. if ((major == 6) && (minor < 1)) {
  522. register_entries_gisman(pkg_short_name, gisbase);
  523. }
  524. register_entries_gisman2(pkg_short_name, gisbase);
  525. register_html(pkg_short_name, gisbase, pkg_major, pkg_minor,
  526. pkg_revision);
  527. /* create a shell command for the make install process and installation of extension.db */
  528. /* we will use a local copy of the make command for this (extension author has to supply it). */
  529. if (VERBOSE) {
  530. fprintf(stdout, "Running '%s install':\n", MAKE_CMD);
  531. sprintf(install_cmd, "bin/%s -f Makefile install ; \
  532. cp -vf %s %s/etc/extensions.db ; chmod -v a+r %s/etc/extensions.db ;", MAKE_CMD, TMPDB, gisbase, gisbase);
  533. }
  534. else {
  535. sprintf(install_cmd, "bin/%s -f Makefile -s install &> %s ; \
  536. 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);
  537. }
  538. /* command to run post action script */
  539. if (VERBOSE) {
  540. sprintf(post_cmd, "sh ../post");
  541. }
  542. else {
  543. sprintf(post_cmd, "sh ../post &> %s", TMP_NULL);
  544. }
  545. /* make install */
  546. sprintf(tmp, "%s %s %s %s %s %s", install_cmd, UNINSTALL_CMD, GISMAN_CMD,
  547. GISMAN2_CMD, HTML_CMD, post_cmd);
  548. su(gisbase, tmp);
  549. print_done();
  550. }
  551. void test_install(char *package, char *gisbase, char *pkg_short_name,
  552. int pkg_major, int pkg_minor, int pkg_revision,
  553. char *grass_version)
  554. {
  555. char tmp[MAXSTR];
  556. char dir[MAXSTR];
  557. char sysstr[MAXSTR];
  558. int error;
  559. struct stat buf;
  560. FILE *f;
  561. char *verstr;
  562. char *grass_major;
  563. char *grass_minor;
  564. char *grass_revision;
  565. int major, minor, revision;
  566. /* check for valid install directory */
  567. error = stat(gisbase, &buf);
  568. if (error < 0) {
  569. print_error(ERR_INSTALL_EXT, "installation directory invalid: %s\n",
  570. strerror(errno));
  571. }
  572. /* export environment variables for GRASS 6 build system */
  573. /* target dir for installation */
  574. sprintf(GINSTALL_DST, "GINSTALL_DST=%s", gisbase);
  575. putenv(GINSTALL_DST);
  576. /*external include path */
  577. sprintf(tmp, "%s/include", gisbase);
  578. sprintf(GINSTALL_INC, "GINSTALL_INC=%s", tmp);
  579. putenv(GINSTALL_INC);
  580. /* external linker path */
  581. sprintf(tmp, "%s/lib", gisbase);
  582. sprintf(GINSTALL_LIB, "GINSTALL_LIB=%s", tmp);
  583. putenv(GINSTALL_LIB);
  584. /* path to install files */
  585. sprintf(GEM_GRASS_DIR, "GEM_GRASS_DIR=%s", gisbase);
  586. putenv(GEM_GRASS_DIR);
  587. /* extract GRASS major and minor version numbers */
  588. verstr = strdup(grass_version);
  589. grass_major = strtok(verstr, ".");
  590. grass_minor = strtok(NULL, ".");
  591. grass_revision = strtok(NULL, ".");
  592. major = strtol(grass_major, NULL, 10);
  593. minor = strtol(grass_minor, NULL, 10);
  594. revision = strtol(grass_revision, NULL, 10);
  595. free(verstr);
  596. /* now need to register an exit function that unsets these env vars on termination! */
  597. atexit(&exit_tmp);
  598. /* step into target directory and execute configure script */
  599. sprintf(dir, "%s/src", basename(package));
  600. error = chdir(dir);
  601. if (error < 0) {
  602. print_error(ERR_NO_ACCESS_EXT,
  603. "extension files in '%s' not accessible: %s\n", package,
  604. strerror(errno));
  605. }
  606. if (!SKIP_CFG) {
  607. if (VERBOSE) {
  608. fprintf(stdout, "Running configure script:\n");
  609. sprintf(sysstr, "sh %s %s", CONFIG_CMD, CONFIG_OPTS);
  610. error = system(sysstr);
  611. }
  612. else {
  613. fprintf(stdout, "Configuring...");
  614. sprintf(sysstr, "sh %s %s --quiet &> %s", CONFIG_CMD, CONFIG_OPTS,
  615. TMP_NULL);
  616. error = system(sysstr);
  617. }
  618. if (error == -1) {
  619. print_error(ERR_MISSING_CFG, "could not run configure script.\n");
  620. }
  621. if (error > 0) {
  622. print_error(ERR_CONFIGURE_EXT, "system configuration failed.\n");
  623. }
  624. print_done();
  625. print_cfg();
  626. }
  627. /* export environment variables for generation of HTML documentation directories */
  628. /* by include/Make/Rules.make */
  629. sprintf(GEM_EXT_NAME, "GEM_EXT_NAME=%s", pkg_short_name);
  630. putenv(GEM_EXT_NAME);
  631. sprintf(tmp, "%i.%i.%i", pkg_major, pkg_minor, pkg_revision);
  632. sprintf(GEM_EXT_VERSION, "GEM_EXT_VERSION=%s", tmp);
  633. putenv(GEM_EXT_VERSION);
  634. /* dump extension info text into two plain ASCII files for inclusion in HTML man page */
  635. dump_plain("../description", TMP_DESCR);
  636. dump_plain("../info", TMP_INFO);
  637. dump_plain("../depends", TMP_DEPS);
  638. dump_plain("../bugs", TMP_BUGS);
  639. dump_plain("../authors", TMP_AUTHORS);
  640. sprintf(GEM_EXT_DESCR, "GEM_EXT_DESCR=%s", TMP_DESCR);
  641. putenv(GEM_EXT_DESCR);
  642. sprintf(GEM_EXT_INFO, "GEM_EXT_INFO=%s", TMP_INFO);
  643. putenv(GEM_EXT_INFO);
  644. sprintf(GEM_EXT_DEPS, "GEM_EXT_DEPS=%s", TMP_DEPS);
  645. putenv(GEM_EXT_DEPS);
  646. sprintf(GEM_EXT_BUGS, "GEM_EXT_BUGS=%s", TMP_BUGS);
  647. putenv(GEM_EXT_BUGS);
  648. sprintf(GEM_EXT_AUTHORS, "GEM_EXT_AUTHORS=%s", TMP_AUTHORS);
  649. putenv(GEM_EXT_AUTHORS);
  650. /* now need to register an exit function that unsets these env vars on termination! */
  651. atexit(&exit_tmp);
  652. /* check dependencies before compiling everything ... */
  653. check_dependencies(package, gisbase, grass_version);
  654. /* now execute Makefile in top-level directory */
  655. if (VERBOSE) {
  656. fprintf(stdout, "Running '%s':\n", MAKE_CMD);
  657. sprintf(sysstr, "%s -f Makefile", MAKE_CMD);
  658. error = system(sysstr);
  659. }
  660. else {
  661. fprintf(stdout, "Compiling...");
  662. sprintf(sysstr, "%s -f Makefile &> %s", MAKE_CMD, TMP_NULL);
  663. error = system(sysstr);
  664. }
  665. if (error == -1) {
  666. if (!VERBOSE) {
  667. print_error(ERR_MISSING_CMD,
  668. "could not run '%s' do you have make tools installed?\n",
  669. MAKE_CMD);
  670. }
  671. }
  672. if (error > 0) {
  673. print_error(ERR_COMPILE_EXT, "source code could not be compiled.\n \
  674. Run again with option -v to see what is causing trouble.\n");
  675. }
  676. print_done();
  677. fprintf(stdout, "Installing...");
  678. /* check if an uninstall script exists */
  679. f = fopen("../uninstall", "r");
  680. if (f == NULL) {
  681. print_warning("error checking for uninstall script: %s\n \
  682. Uninstalling this extension may leave orphaned files on your system", strerror(errno));
  683. }
  684. else {
  685. fclose(f);
  686. }
  687. register_extension(gisbase, "src", pkg_short_name, pkg_major, pkg_minor,
  688. pkg_revision);
  689. check_dependencies(package, gisbase, grass_version);
  690. /* starting with GRASS 6.1.cvs, d.m uses the same menu system as gis.m */
  691. if ((major == 6) && (minor < 1)) {
  692. register_entries_gisman(pkg_short_name, gisbase);
  693. }
  694. register_entries_gisman2(pkg_short_name, gisbase);
  695. register_html(pkg_short_name, gisbase, pkg_major, pkg_minor,
  696. pkg_revision);
  697. fprintf(stdout, "(skipping '%s install')...", MAKE_CMD);
  698. print_done();
  699. }
  700. /*
  701. Run the uninstall script that was (hopefully) provided by the packager.
  702. Check for unsatisfied dependencies and warn/abort accordingly.
  703. */
  704. void uninstall(char *package, char *pkg_short_name, char *gisbase,
  705. char *grass_version)
  706. {
  707. char tmp[MAXSTR];
  708. char script[MAXSTR];
  709. int error;
  710. struct stat buf;
  711. int no_script;
  712. char *verstr;
  713. char *grass_major;
  714. char *grass_minor;
  715. char *grass_revision;
  716. int major, minor, revision;
  717. fprintf(stdout, "Un-installing...");
  718. /* export environment variables for uninstall script */
  719. sprintf(UNINSTALL_BASE, "UNINSTALL_BASE=%s", gisbase);
  720. putenv(UNINSTALL_BASE);
  721. /* extract GRASS major and minor version numbers */
  722. verstr = strdup(grass_version);
  723. grass_major = strtok(verstr, ".");
  724. grass_minor = strtok(NULL, ".");
  725. grass_revision = strtok(NULL, ".");
  726. major = strtol(grass_major, NULL, 10);
  727. minor = strtol(grass_minor, NULL, 10);
  728. revision = strtol(grass_revision, NULL, 10);
  729. free(verstr);
  730. /* now need to register an exit function that unsets these env vars on termination! */
  731. atexit(&exit_tmp);
  732. /* deregister extension */
  733. deregister_extension(package, pkg_short_name, gisbase);
  734. /* deregister menu entries in GIS Manager */
  735. /* starting with GRASS 6.1.cvs, d.m uses the same menu system as gis.m */
  736. if ((major == 6) && (minor < 1)) {
  737. error = deregister_entries_gisman(pkg_short_name, gisbase);
  738. if (error == -1) {
  739. print_warning("GIS Manager menu entries could not be removed.\n");
  740. strcpy(GISMAN_CMD, "");
  741. }
  742. if (error == 0) {
  743. print_warning("no entries found to remove from GIS Manager.\n");
  744. strcpy(GISMAN_CMD, "");
  745. }
  746. }
  747. /* deregister menu entries in GIS Manager 2 */
  748. deregister_entries_gisman2(pkg_short_name, gisbase);
  749. /* deregister HTML entries and delete man pages */
  750. deregister_html(pkg_short_name, gisbase);
  751. /* check if an uninstall script exists */
  752. sprintf(script, "%s/etc/uninstall.%s", gisbase, pkg_short_name);
  753. no_script = 0;
  754. error = stat(script, &buf);
  755. if (error < 0) {
  756. print_warning("no uninstall script available for this extension.\n \
  757. Unneeded files may have been left on your system.\n");
  758. no_script = 1;
  759. }
  760. if (no_script) {
  761. print_warning("error checking for uninstall script: %s\n \
  762. Uninstalling this extension may leave orphaned files on your system", strerror(errno));
  763. }
  764. else {
  765. /* it does: create a shell command to execute and then delete it upon de-installation */
  766. if (VERBOSE) {
  767. sprintf(tmp, "sh %s ; rm -vf %s ; \
  768. rm -vrf %s/docs/extensions/%s ; rm -vf %s/etc/dm/gem-entries/%s ; \
  769. 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);
  770. strcpy(UNINSTALL_CMD, tmp);
  771. }
  772. else {
  773. sprintf(tmp, "sh %s &> %s ; rm -vf %s &> %s ; \
  774. rm -vrf %s/docs/extensions/%s &> %s ; rm -vf %s/etc/dm/gem-entries/%s &> %s ; \
  775. 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);
  776. strcpy(UNINSTALL_CMD, tmp);
  777. }
  778. }
  779. /* do the uninstall! */
  780. sprintf(tmp, "%s %s %s", UNINSTALL_CMD, GISMAN_CMD, HTML_CMD);
  781. su(gisbase, tmp);
  782. print_done();
  783. }
  784. int source_clean(char *package)
  785. {
  786. char dir[MAXSTR];
  787. char sysstr[MAXSTR];
  788. int error;
  789. /* step into target directory */
  790. sprintf(dir, "%s/src", basename(package));
  791. error = chdir(dir);
  792. if (error < 0) {
  793. print_error(ERR_NO_ACCESS_EXT, "extension '%s' not accessible: ",
  794. package);
  795. }
  796. /* now execute Makefile and 'clean' from top-level directory */
  797. if (VERBOSE) {
  798. fprintf(stdout, "Running '%s clean':\n", MAKE_CMD);
  799. sprintf(sysstr, "%s -f Makefile clean", MAKE_CMD);
  800. error = system(sysstr);
  801. }
  802. else {
  803. fprintf(stdout, "Cleaning up...");
  804. sprintf(sysstr, "%s -f Makefile -s clean &> %s", MAKE_CMD, TMP_NULL);
  805. error = system(sysstr);
  806. }
  807. if (error == -1) {
  808. print_error(ERR_MISSING_CMD,
  809. "could not run '%s clean' do you have make tools installed?\n",
  810. MAKE_CMD);
  811. }
  812. else {
  813. print_done();
  814. }
  815. /* run post action script */
  816. system("sh ../post");
  817. return (0);
  818. }
  819. /*
  820. Restores HTML links and GIS Manager menus, e.g. after an update of GRASS
  821. */
  822. void restore(char *gisbase, char *grass_version)
  823. {
  824. int num_restored;
  825. char tmp[MAXSTR];
  826. char *verstr;
  827. char *grass_major;
  828. char *grass_minor;
  829. char *grass_revision;
  830. int major, minor, revision;
  831. /* extract GRASS major and minor version numbers */
  832. verstr = strdup(grass_version);
  833. grass_major = strtok(verstr, ".");
  834. grass_minor = strtok(NULL, ".");
  835. grass_revision = strtok(NULL, ".");
  836. major = strtol(grass_major, NULL, 10);
  837. minor = strtol(grass_minor, NULL, 10);
  838. revision = strtol(grass_revision, NULL, 10);
  839. free(verstr);
  840. fprintf(stdout, "Restoring...");
  841. /* starting with GRASS 6.1.cvs, d.m uses the same menu system as gis.m */
  842. if ((major == 6) && (minor < 1)) {
  843. num_restored = restore_entries_gisman(gisbase);
  844. if (VERBOSE) {
  845. fprintf(stdout, "\nRestored entries for GIS Manager: %i\n",
  846. num_restored);
  847. }
  848. }
  849. num_restored = restore_html(gisbase);
  850. if (VERBOSE) {
  851. fprintf(stdout, "\nRestored links in index.hml: %i\n", num_restored);
  852. }
  853. if (num_restored > 0) {
  854. /* copy restored files to GRASS install tree */
  855. if (VERBOSE) {
  856. sprintf(tmp,
  857. "cp -f %s %s/etc/dm/menu.tcl ; chmod a+r %s/etc/dm/menu.tcl ; \
  858. cp -f %s %s/docs/html/index.html ; chmod a+r %s/docs/html/index.html",
  859. TMP_GISMAN, gisbase, gisbase, TMP_HTML, gisbase, gisbase);
  860. }
  861. else {
  862. sprintf(tmp,
  863. "cp -f %s %s/etc/dm/menu.tcl ; chmod a+r %s/etc/dm/menu.tcl &> %s ; \
  864. cp -f %s %s/docs/html/index.html ; chmod a+r %s/docs/html/index.html",
  865. TMP_GISMAN, gisbase, gisbase, TMP_NULL, TMP_HTML, gisbase,
  866. gisbase);
  867. }
  868. su(gisbase, tmp);
  869. }
  870. if (num_restored == 0) {
  871. print_error(ERR_RESTORE, "could not find anything to restore.\n");
  872. }
  873. else {
  874. print_done();
  875. }
  876. }
  877. /*
  878. List all extensions installed on system with versions and dependencies
  879. */
  880. void list_extensions(char *gisbase)
  881. {
  882. char file[MAXSTR];
  883. FILE *f_in;
  884. fprintf(stdout, "\nExtensions in '%s' (name, version, type, depends):\n",
  885. gisbase);
  886. /* check, if extensions.db exists and is readable */
  887. sprintf(file, "%s/etc/extensions.db", gisbase);
  888. f_in = fopen(file, "r");
  889. if (f_in == NULL) {
  890. if (errno == ENOENT) {
  891. /* file does not yet exist */
  892. fprintf(stderr, "NONE.\n");
  893. fclose(f_in);
  894. exit(0);
  895. }
  896. else {
  897. /* sth. strange happened */
  898. fclose(f_in);
  899. print_error(ERR_LIST, "checking for file '%s': %s\n", file,
  900. strerror(errno));
  901. }
  902. }
  903. fclose(f_in);
  904. dump_ascii(file, "");
  905. }
  906. /*
  907. A bit of a misnomer: this does not actually run the post
  908. script but it exports all necessary env vars.
  909. */
  910. void run_post(char *package, int action, char *bins, char *gisbase)
  911. {
  912. char tmp[MAXSTR];
  913. char tmp2[MAXSTR];
  914. switch (action) {
  915. case INSTALL:
  916. sprintf(GEM_ACTION, "GEM_ACTION=INSTALL");
  917. break;
  918. case BIN_INSTALL:
  919. sprintf(GEM_ACTION, "GEM_ACTION=INSTALL");
  920. break;
  921. case QUERY:
  922. sprintf(GEM_ACTION, "GEM_ACTION=QUERY");
  923. break;
  924. case CLEAN:
  925. sprintf(GEM_ACTION, "GEM_ACTION=CLEAN");
  926. break;
  927. case LICENSE:
  928. sprintf(GEM_ACTION, "GEM_ACTION=LICENSE");
  929. break;
  930. case DETAILS:
  931. sprintf(GEM_ACTION, "GEM_ACTION=DETAILS");
  932. break;
  933. default:
  934. break;
  935. }
  936. putenv(GEM_ACTION);
  937. if (gisbase != NULL) {
  938. sprintf(INSTALL_BASE, "INSTALL_BASE=%s", gisbase);
  939. }
  940. else {
  941. sprintf(INSTALL_BASE, "INSTALL_BASE=UNDEFINED");
  942. }
  943. putenv(INSTALL_BASE);
  944. /* export absolute path to current working dir */
  945. getcwd(tmp, MAXSTR);
  946. sprintf(tmp2, "%s/%s/src", tmp, basename(package));
  947. sprintf(EXT_BASE, "EXT_BASE=%s", tmp2);
  948. putenv(EXT_BASE);
  949. if (bins == NULL) {
  950. sprintf(INSTALL_TYPE, "INSTALL_TYPE=src");
  951. }
  952. else {
  953. sprintf(INSTALL_TYPE, "INSTALL_TYPE=%s", bins);
  954. }
  955. putenv(INSTALL_TYPE);
  956. sprintf(tmp, "%i", FORCE);
  957. sprintf(GEM_FORCE, "GEM_FORCE=%s", tmp);
  958. putenv(GEM_FORCE);
  959. sprintf(tmp, "%i", VERBOSE);
  960. sprintf(GEM_VERBOSE, "GEM_VERBOSE=%s", tmp);
  961. putenv(GEM_VERBOSE);
  962. sprintf(GEM_GUI, "GEM_GUI=0");
  963. putenv(GEM_GUI);
  964. /* now need to register an exit function that unsets these env vars on termination! */
  965. atexit(&exit_tmp);
  966. }