| 1 |
|
|---|
| 2 | /****************************************************************
|
|---|
| 3 | *
|
|---|
| 4 | * MODULE: g.mapset
|
|---|
| 5 | *
|
|---|
| 6 | * AUTHOR(S): Radim Blazek
|
|---|
| 7 | * Joel Pitt, joel.pitt@gmail.com
|
|---|
| 8 | *
|
|---|
| 9 | * PURPOSE: Change current mapset, optionally adding it
|
|---|
| 10 | * if the mapset does not exist.
|
|---|
| 11 | *
|
|---|
| 12 | * COPYRIGHT: (C) 2004, 2010-2011 by the GRASS Development Team
|
|---|
| 13 | *
|
|---|
| 14 | * This program is free software under the
|
|---|
| 15 | * GNU General Public License (>=v2).
|
|---|
| 16 | * Read the file COPYING that comes with GRASS
|
|---|
| 17 | * for details.
|
|---|
| 18 | *
|
|---|
| 19 | **************************************************************/
|
|---|
| 20 | #include <stdlib.h>
|
|---|
| 21 | #include <stdio.h>
|
|---|
| 22 | #include <string.h>
|
|---|
| 23 | #include <unistd.h>
|
|---|
| 24 | #include <grass/gis.h>
|
|---|
| 25 | #include <grass/glocale.h>
|
|---|
| 26 | #include <grass/spawn.h>
|
|---|
| 27 |
|
|---|
| 28 | int main(int argc, char *argv[])
|
|---|
| 29 | {
|
|---|
| 30 | int ret;
|
|---|
| 31 | struct GModule *module;
|
|---|
| 32 | struct {
|
|---|
| 33 | struct Option *gisdbase, *location, *mapset;
|
|---|
| 34 | } opt;
|
|---|
| 35 | struct {
|
|---|
| 36 | struct Flag *add, *list, *curr;
|
|---|
| 37 | } flag;
|
|---|
| 38 | const char *gisdbase_old, *location_old, *mapset_old;
|
|---|
| 39 | const char *gisdbase_new, *location_new, *mapset_new;
|
|---|
| 40 | const char *gis_lock;
|
|---|
| 41 | char *mapset_old_path, *mapset_new_path;
|
|---|
| 42 | char *lock_prog;
|
|---|
| 43 | const char *shell;
|
|---|
| 44 | char path[GPATH_MAX];
|
|---|
| 45 |
|
|---|
| 46 | G_gisinit(argv[0]);
|
|---|
| 47 |
|
|---|
| 48 | module = G_define_module();
|
|---|
| 49 | G_add_keyword(_("general"));
|
|---|
| 50 | G_add_keyword(_("settings"));
|
|---|
| 51 | module->label = _("Changes/reports current mapset.");
|
|---|
| 52 | module->description = _("Optionally create new mapset or list available mapsets in given location.");
|
|---|
| 53 |
|
|---|
| 54 | opt.mapset = G_define_standard_option(G_OPT_M_MAPSET);
|
|---|
| 55 | opt.mapset->required = YES;
|
|---|
| 56 | opt.mapset->description = _("Name of mapset where to switch");
|
|---|
| 57 | opt.mapset->guisection = _("Mapset");
|
|---|
| 58 | opt.mapset->gisprompt = "new,mapset,mapset";
|
|---|
| 59 |
|
|---|
| 60 | opt.location = G_define_standard_option(G_OPT_M_LOCATION);
|
|---|
| 61 | opt.location->guisection = _("Mapset");
|
|---|
| 62 |
|
|---|
| 63 | opt.gisdbase = G_define_standard_option(G_OPT_M_DBASE);
|
|---|
| 64 | opt.gisdbase->guisection = _("Mapset");
|
|---|
| 65 |
|
|---|
| 66 | flag.add = G_define_flag();
|
|---|
| 67 | flag.add->key = 'c';
|
|---|
| 68 | flag.add->description = _("Create mapset if it doesn't exist");
|
|---|
| 69 | flag.add->answer = FALSE;
|
|---|
| 70 | flag.add->guisection = _("Create");
|
|---|
| 71 |
|
|---|
| 72 | flag.list = G_define_flag();
|
|---|
| 73 | flag.list->key = 'l';
|
|---|
| 74 | flag.list->suppress_required = YES;
|
|---|
| 75 | flag.list->description = _("List available mapsets and exit");
|
|---|
| 76 | flag.list->guisection = _("Print");
|
|---|
| 77 |
|
|---|
| 78 | flag.curr = G_define_flag();
|
|---|
| 79 | flag.curr->key = 'p';
|
|---|
| 80 | flag.curr->suppress_required = YES;
|
|---|
| 81 | flag.curr->description = _("Print current mapset and exit");
|
|---|
| 82 | flag.curr->guisection = _("Print");
|
|---|
| 83 |
|
|---|
| 84 | if (G_parser(argc, argv))
|
|---|
| 85 | exit(EXIT_FAILURE);
|
|---|
| 86 |
|
|---|
| 87 | /* Store original values */
|
|---|
| 88 | gisdbase_old = G_getenv_nofatal("GISDBASE");
|
|---|
| 89 | location_old = G_getenv_nofatal("LOCATION_NAME");
|
|---|
| 90 | mapset_old = G_getenv_nofatal("MAPSET");
|
|---|
| 91 |
|
|---|
| 92 | if (flag.curr->answer) {
|
|---|
| 93 | fprintf(stdout, "%s\n", mapset_old);
|
|---|
| 94 | exit(EXIT_SUCCESS);
|
|---|
| 95 | }
|
|---|
| 96 |
|
|---|
| 97 | G_asprintf(&mapset_old_path, "%s/%s/%s", gisdbase_old, location_old,
|
|---|
| 98 | mapset_old);
|
|---|
| 99 |
|
|---|
| 100 | /* New values */
|
|---|
| 101 | if (opt.gisdbase->answer)
|
|---|
| 102 | gisdbase_new = opt.gisdbase->answer;
|
|---|
| 103 | else
|
|---|
| 104 | gisdbase_new = gisdbase_old;
|
|---|
| 105 |
|
|---|
| 106 | if (opt.location->answer)
|
|---|
| 107 | location_new = opt.location->answer;
|
|---|
| 108 | else
|
|---|
| 109 | location_new = location_old;
|
|---|
| 110 |
|
|---|
| 111 | if (flag.list->answer) {
|
|---|
| 112 | char **ms;
|
|---|
| 113 | int nmapsets;
|
|---|
| 114 |
|
|---|
| 115 | G_setenv_nogisrc("LOCATION_NAME", location_new);
|
|---|
| 116 | G_setenv_nogisrc("GISDBASE", gisdbase_new);
|
|---|
| 117 |
|
|---|
| 118 | ms = G_get_available_mapsets();
|
|---|
| 119 |
|
|---|
| 120 | for (nmapsets = 0; ms[nmapsets]; nmapsets++) {
|
|---|
| 121 | if (G_mapset_permissions(ms[nmapsets]) > 0) {
|
|---|
| 122 | fprintf(stdout, "%s ", ms[nmapsets]);
|
|---|
| 123 | }
|
|---|
| 124 | }
|
|---|
| 125 | fprintf(stdout, "\n");
|
|---|
| 126 |
|
|---|
| 127 | exit(EXIT_SUCCESS);
|
|---|
| 128 | }
|
|---|
| 129 |
|
|---|
| 130 | mapset_new = opt.mapset->answer;
|
|---|
| 131 | G_asprintf(&mapset_new_path, "%s/%s/%s", gisdbase_new, location_new,
|
|---|
| 132 | mapset_new);
|
|---|
| 133 |
|
|---|
| 134 | /* TODO: this should be checked better (repeated '/' etc.) */
|
|---|
| 135 | if (strcmp(mapset_old_path, mapset_new_path) == 0) {
|
|---|
| 136 | G_warning(_("<%s> is already the current mapset"), mapset_new);
|
|---|
| 137 | exit(EXIT_SUCCESS);
|
|---|
| 138 | }
|
|---|
| 139 | /* Check if the mapset exists and user is owner */
|
|---|
| 140 | G_debug(2, "check : %s", mapset_new_path);
|
|---|
| 141 |
|
|---|
| 142 | ret = G_mapset_permissions2(gisdbase_new, location_new, mapset_new);
|
|---|
| 143 | switch (ret) {
|
|---|
| 144 | case 0:
|
|---|
| 145 | G_fatal_error(_("You don't have permission to use the mapset <%s>"),
|
|---|
| 146 | mapset_new);
|
|---|
| 147 | break;
|
|---|
| 148 | case -1:
|
|---|
| 149 | if (flag.add->answer == TRUE) {
|
|---|
| 150 | G_debug(2, "Mapset <%s> doesn't exist, attempting to create it",
|
|---|
| 151 | mapset_new);
|
|---|
| 152 | if (G_make_mapset(gisdbase_new, location_new, mapset_new) != 0)
|
|---|
| 153 | G_fatal_error(_("Unable to create new mapset <%s>"), mapset_new);
|
|---|
| 154 | }
|
|---|
| 155 | else
|
|---|
| 156 | G_fatal_error(_("Mapset <%s> does not exist. Use -c flag to create it."),
|
|---|
| 157 | mapset_new);
|
|---|
| 158 | break;
|
|---|
| 159 | default:
|
|---|
| 160 | break;
|
|---|
| 161 | }
|
|---|
| 162 |
|
|---|
| 163 | /* Check if the mapset is in use */
|
|---|
| 164 | gis_lock = getenv("GIS_LOCK");
|
|---|
| 165 | if (!gis_lock)
|
|---|
| 166 | G_fatal_error(_("Unable to read GIS_LOCK environment variable"));
|
|---|
| 167 |
|
|---|
| 168 | G_asprintf(&lock_prog, "%s/etc/lock", G_gisbase());
|
|---|
| 169 |
|
|---|
| 170 | sprintf(path, "%s/.gislock", mapset_new_path);
|
|---|
| 171 | G_debug(2, "%s", path);
|
|---|
| 172 |
|
|---|
| 173 | ret = G_spawn(lock_prog, lock_prog, path, gis_lock, NULL);
|
|---|
| 174 | G_debug(2, "lock result = %d", ret);
|
|---|
| 175 | G_free(lock_prog);
|
|---|
| 176 |
|
|---|
| 177 | /* Warning: the value returned by system() is not that returned by exit() in executed program
|
|---|
| 178 | * e.g. exit(1) -> 256 (multiplied by 256) */
|
|---|
| 179 | if (ret != 0) {
|
|---|
| 180 | /* .gislock does not exist */
|
|---|
| 181 | if (access(path, F_OK) != 0)
|
|---|
| 182 | G_fatal_error(_("Lock file of mapset <%s> cannot be checked"),
|
|---|
| 183 | mapset_new);
|
|---|
| 184 | else
|
|---|
| 185 | G_fatal_error(_("There appears to be an active GRASS session in selected mapset <%s>"),
|
|---|
| 186 | mapset_new);
|
|---|
| 187 | }
|
|---|
| 188 |
|
|---|
| 189 | /* Clean temporary directory */
|
|---|
| 190 | sprintf(path, "%s/etc/clean_temp", G_gisbase());
|
|---|
| 191 | G_verbose_message(_("Cleaning up temporary files..."));
|
|---|
| 192 | G_spawn(path, "clean_temp", NULL);
|
|---|
| 193 |
|
|---|
| 194 | /* Reset variables */
|
|---|
| 195 | G_setenv("GISDBASE", gisdbase_new);
|
|---|
| 196 | G_setenv("LOCATION_NAME", location_new);
|
|---|
| 197 | G_setenv("MAPSET", mapset_new);
|
|---|
| 198 |
|
|---|
| 199 | /* Remove old lock */
|
|---|
| 200 | sprintf(path, "%s/.gislock", mapset_old_path);
|
|---|
| 201 | remove(path);
|
|---|
| 202 |
|
|---|
| 203 | G_free(mapset_old_path);
|
|---|
| 204 |
|
|---|
| 205 | G_important_message(_("Mapset switched. Your shell continues to use the history "
|
|---|
| 206 | "for the old mapset"));
|
|---|
| 207 |
|
|---|
| 208 | if ((shell = getenv("SHELL"))) {
|
|---|
| 209 | if (strstr(shell, "bash")) {
|
|---|
| 210 | G_important_message(_("You can switch the history by commands:\n"
|
|---|
| 211 | "history -w; history -r %s/.bash_history; HISTFILE=%s/.bash_history"),
|
|---|
| 212 | mapset_new_path, mapset_new_path);
|
|---|
| 213 | }
|
|---|
| 214 | else if (strstr(shell, "tcsh")) {
|
|---|
| 215 | G_important_message(_("You can switch the history by commands:\n"
|
|---|
| 216 | "history -S; history -L %s/.history; setenv histfile=%s/.history"),
|
|---|
| 217 | mapset_new_path, mapset_new_path);
|
|---|
| 218 | }
|
|---|
| 219 | }
|
|---|
| 220 |
|
|---|
| 221 | G_verbose_message(_("Your current mapset is <%s>"), mapset_new);
|
|---|
| 222 |
|
|---|
| 223 | G_free(mapset_new_path);
|
|---|
| 224 |
|
|---|
| 225 | return (EXIT_SUCCESS);
|
|---|
| 226 | }
|
|---|