00001
00015 #include <string.h>
00016 #include <stdlib.h>
00017 #include <unistd.h>
00018
00019 #ifdef __MINGW32__
00020 #include <windows.h>
00021 #include <process.h>
00022 #include <fcntl.h>
00023 #endif
00024
00025 #include <grass/dbmi.h>
00026
00027 #define READ 0
00028 #define WRITE 1
00029
00030
00042 dbDriver *db_start_driver(const char *name)
00043 {
00044 dbDriver *driver;
00045 dbDbmscap *list, *cur;
00046 const char *startup;
00047 int p1[2], p2[2];
00048 int pid;
00049 int stat;
00050 dbConnection connection;
00051 char ebuf[5];
00052
00053 #ifdef __MINGW32__
00054 int stdin_orig, stdout_orig;
00055 int have_stdin, have_stdout;
00056 int stdin_fd, stdout_fd;
00057 #endif
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067 if (G_get_gisrc_mode() == G_GISRC_MODE_MEMORY) {
00068 G_debug(3, "G_GISRC_MODE_MEMORY\n");
00069 sprintf(ebuf, "%d", G_GISRC_MODE_MEMORY);
00070 G_putenv("GRASS_DB_DRIVER_GISRC_MODE", ebuf);
00071
00072 if (G__getenv("DEBUG")) {
00073 G_putenv("DEBUG", G__getenv("DEBUG"));
00074 }
00075 else {
00076 G_putenv("DEBUG", "0");
00077 }
00078
00079 G_putenv("GISDBASE", G__getenv("GISDBASE"));
00080 G_putenv("LOCATION_NAME", G__getenv("LOCATION_NAME"));
00081 G_putenv("MAPSET", G__getenv("MAPSET"));
00082 }
00083 else {
00084
00085
00086 sprintf(ebuf, "%d", G_GISRC_MODE_FILE);
00087 G_putenv("GRASS_DB_DRIVER_GISRC_MODE", ebuf);
00088 }
00089
00090
00091 if (NULL == (list = db_read_dbmscap()))
00092 return (dbDriver *) NULL;
00093
00094
00095 if (name == '\0') {
00096 db_get_connection(&connection);
00097 if (NULL == (name = connection.driverName))
00098 return (dbDriver *) NULL;
00099 }
00100
00101
00102 for (cur = list; cur; cur = cur->next)
00103 if (strcmp(cur->driverName, name) == 0)
00104 break;
00105 if (cur == NULL) {
00106 char msg[256];
00107
00108 db_free_dbmscap(list);
00109 sprintf(msg, "%s: no such driver available", name);
00110 db_error(msg);
00111 return (dbDriver *) NULL;
00112 }
00113
00114
00115 driver = (dbDriver *) db_malloc(sizeof(dbDriver));
00116 if (driver == NULL) {
00117 db_free_dbmscap(list);
00118 return (dbDriver *) NULL;
00119 }
00120
00121
00122 db_copy_dbmscap_entry(&driver->dbmscap, cur);
00123 startup = driver->dbmscap.startup;
00124
00125
00126 db_free_dbmscap(list);
00127
00128
00129
00130 #ifdef __MINGW32__
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154 if (_pipe(p1, 250000, _O_BINARY) < 0 || _pipe(p2, 250000, _O_BINARY) < 0) {
00155 db_syserror("can't open any pipes");
00156 return (dbDriver *) NULL;
00157 }
00158
00159
00160 driver->send = fdopen(p1[WRITE], "wb");
00161 driver->recv = fdopen(p2[READ], "rb");
00162
00163 fflush(stdout);
00164 fflush(stderr);
00165
00166
00167
00168 have_stdin = have_stdout = 1;
00169
00170 if (_fileno(stdin) < 0) {
00171 have_stdin = 0;
00172 stdin_fd = 0;
00173 }
00174 else {
00175 stdin_fd = _fileno(stdin);
00176
00177 if ((stdin_orig = _dup(_fileno(stdin))) < 0) {
00178 db_syserror("can't duplicate stdin");
00179 return (dbDriver *) NULL;
00180 }
00181
00182 }
00183
00184 if (_dup2(p1[0], stdin_fd) != 0) {
00185 db_syserror("can't duplicate pipe");
00186 return (dbDriver *) NULL;
00187 }
00188
00189 if (_fileno(stdout) < 0) {
00190 have_stdout = 0;
00191 stdout_fd = 1;
00192 }
00193 else {
00194 stdout_fd = _fileno(stdout);
00195
00196 if ((stdout_orig = _dup(_fileno(stdout))) < 0) {
00197 db_syserror("can't duplicate stdout");
00198 return (dbDriver *) NULL;
00199 }
00200
00201 }
00202
00203 if (_dup2(p2[1], stdout_fd) != 0) {
00204 db_syserror("can't duplicate pipe");
00205 return (dbDriver *) NULL;
00206 }
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220 pid = _spawnl(_P_NOWAIT, startup, startup, NULL);
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242 if (have_stdin) {
00243 if (_dup2(stdin_orig, _fileno(stdin)) != 0) {
00244 db_syserror("can't reset stdin");
00245 return (dbDriver *) NULL;
00246 }
00247 close(stdin_orig);
00248 }
00249
00250
00251 if (have_stdout) {
00252 if (_dup2(stdout_orig, _fileno(stdout)) != 0) {
00253 db_syserror("can't reset stdout");
00254 return (dbDriver *) NULL;
00255 }
00256 close(stdout_orig);
00257 }
00258
00259 if (pid == -1) {
00260 db_syserror("can't _spawnl");
00261 return (dbDriver *) NULL;
00262 }
00263
00264
00265 driver->pid = pid;
00266
00267
00268
00269 #ifndef USE_BUFFERED_IO
00270 setbuf(driver->send, NULL);
00271 setbuf(driver->recv, NULL);
00272 #endif
00273
00274 db__set_protocol_fds(driver->send, driver->recv);
00275 if (db__recv_return_code(&stat) != DB_OK || stat != DB_OK)
00276 driver = NULL;
00277
00278 return driver;
00279
00280 #else
00281
00282
00283 if ((pipe(p1) < 0) || (pipe(p2) < 0)) {
00284 db_syserror("can't open any pipes");
00285 return (dbDriver *) NULL;
00286 }
00287
00288
00289 if ((pid = fork()) < 0) {
00290 db_syserror("can't create fork");
00291 return (dbDriver *) NULL;
00292 }
00293
00294 if (pid > 0) {
00295 close(p1[READ]);
00296 close(p2[WRITE]);
00297
00298
00299 driver->pid = pid;
00300
00301
00302 driver->send = fdopen(p1[WRITE], "wb");
00303 driver->recv = fdopen(p2[READ], "rb");
00304
00305
00306 #ifndef USE_BUFFERED_IO
00307 setbuf(driver->send, NULL);
00308 setbuf(driver->recv, NULL);
00309 #endif
00310
00311 db__set_protocol_fds(driver->send, driver->recv);
00312 if (db__recv_return_code(&stat) != DB_OK || stat != DB_OK)
00313 driver = NULL;
00314
00315 return driver;
00316 }
00317 else {
00318
00319 close(p1[WRITE]);
00320 close(p2[READ]);
00321
00322 close(0);
00323 close(1);
00324
00325 if (dup(p1[READ]) != 0) {
00326 db_syserror("dup r");
00327 _exit(EXIT_FAILURE);
00328 }
00329
00330 if (dup(p2[WRITE]) != 1) {
00331 db_syserror("dup w");
00332 _exit(EXIT_FAILURE);
00333 }
00334
00335 execl("/bin/sh", "sh", "-c", startup, NULL);
00336
00337 db_syserror("execl");
00338 return NULL;
00339 }
00340
00341 #endif
00342 }