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 G_debug(2, "dbmi_client/start startup: [%s]", startup);
00221 pid = _spawnl(_P_NOWAIT, startup, startup, NULL);
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243 if (have_stdin) {
00244 if (_dup2(stdin_orig, _fileno(stdin)) != 0) {
00245 db_syserror("can't reset stdin");
00246 return (dbDriver *) NULL;
00247 }
00248 close(stdin_orig);
00249 }
00250
00251
00252 if (have_stdout) {
00253 if (_dup2(stdout_orig, _fileno(stdout)) != 0) {
00254 db_syserror("can't reset stdout");
00255 return (dbDriver *) NULL;
00256 }
00257 close(stdout_orig);
00258 }
00259
00260 if (pid == -1) {
00261 db_syserror("can't _spawnl");
00262 return (dbDriver *) NULL;
00263 }
00264
00265
00266 driver->pid = pid;
00267
00268
00269
00270 #ifndef USE_BUFFERED_IO
00271 setbuf(driver->send, NULL);
00272 setbuf(driver->recv, NULL);
00273 #endif
00274
00275 db__set_protocol_fds(driver->send, driver->recv);
00276 if (db__recv_return_code(&stat) != DB_OK || stat != DB_OK)
00277 driver = NULL;
00278
00279 return driver;
00280
00281 #else
00282
00283
00284 if ((pipe(p1) < 0) || (pipe(p2) < 0)) {
00285 db_syserror("can't open any pipes");
00286 return (dbDriver *) NULL;
00287 }
00288
00289
00290 if ((pid = fork()) < 0) {
00291 db_syserror("can't create fork");
00292 return (dbDriver *) NULL;
00293 }
00294
00295 if (pid > 0) {
00296 close(p1[READ]);
00297 close(p2[WRITE]);
00298
00299
00300 driver->pid = pid;
00301
00302
00303 driver->send = fdopen(p1[WRITE], "wb");
00304 driver->recv = fdopen(p2[READ], "rb");
00305
00306
00307 #ifndef USE_BUFFERED_IO
00308 setbuf(driver->send, NULL);
00309 setbuf(driver->recv, NULL);
00310 #endif
00311
00312 db__set_protocol_fds(driver->send, driver->recv);
00313 if (db__recv_return_code(&stat) != DB_OK || stat != DB_OK)
00314 driver = NULL;
00315
00316 return driver;
00317 }
00318 else {
00319
00320 close(p1[WRITE]);
00321 close(p2[READ]);
00322
00323 close(0);
00324 close(1);
00325
00326 if (dup(p1[READ]) != 0) {
00327 db_syserror("dup r");
00328 _exit(EXIT_FAILURE);
00329 }
00330
00331 if (dup(p2[WRITE]) != 1) {
00332 db_syserror("dup w");
00333 _exit(EXIT_FAILURE);
00334 }
00335
00336 execl(startup, startup, NULL);
00337
00338 db_syserror("execl");
00339 return NULL;
00340 }
00341
00342 #endif
00343 }