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