GRASS Programmer's Manual 6.4.1(2011)
start.c
Go to the documentation of this file.
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/spawn.h>
00026 #include <grass/dbmi.h>
00027 
00028 #define READ  0
00029 #define WRITE 1
00030 
00031 
00043 dbDriver *db_start_driver(const char *name)
00044 {
00045     dbDriver *driver;
00046     dbDbmscap *list, *cur;
00047     const char *startup;
00048     int p1[2], p2[2];
00049     int pid;
00050     int stat;
00051     dbConnection connection;
00052     char ebuf[5];
00053 
00054     /* Set some environment variables which are later read by driver.
00055      * This is necessary when application is running without GISRC file and all
00056      * gis variables are set by application. 
00057      * Even if GISRC is set, application may change some variables during runtime,
00058      * if for example reads data from different gdatabase, location or mapset*/
00059 
00060     /* setenv() is not portable, putenv() is POSIX, putenv() in glibc 2.0-2.1.1 doesn't conform to SUSv2,
00061      * G_putenv() as well, but that is what we want, makes a copy of string */
00062     if (G_get_gisrc_mode() == G_GISRC_MODE_MEMORY) {
00063         G_debug(3, "G_GISRC_MODE_MEMORY\n");
00064         sprintf(ebuf, "%d", G_GISRC_MODE_MEMORY);
00065         G_putenv("GRASS_DB_DRIVER_GISRC_MODE", ebuf);   /* to tell driver that it must read variables */
00066 
00067         if (G__getenv("DEBUG")) {
00068             G_putenv("DEBUG", G__getenv("DEBUG"));
00069         }
00070         else {
00071             G_putenv("DEBUG", "0");
00072         }
00073 
00074         G_putenv("GISDBASE", G__getenv("GISDBASE"));
00075         G_putenv("LOCATION_NAME", G__getenv("LOCATION_NAME"));
00076         G_putenv("MAPSET", G__getenv("MAPSET"));
00077     }
00078     else {
00079         /* Warning: GISRC_MODE_MEMORY _must_ be set to G_GISRC_MODE_FILE, because the module can be 
00080          *          run from an application which previously set environment variable to G_GISRC_MODE_MEMORY */
00081         sprintf(ebuf, "%d", G_GISRC_MODE_FILE);
00082         G_putenv("GRASS_DB_DRIVER_GISRC_MODE", ebuf);
00083     }
00084 
00085     /* read the dbmscap file */
00086     if (NULL == (list = db_read_dbmscap()))
00087         return (dbDriver *) NULL;
00088 
00089     /* if name is empty use connection.driverName, added by RB 4/2000 */
00090     if (name == '\0') {
00091         db_get_connection(&connection);
00092         if (NULL == (name = connection.driverName))
00093             return (dbDriver *) NULL;
00094     }
00095 
00096     /* find this system name */
00097     for (cur = list; cur; cur = cur->next)
00098         if (strcmp(cur->driverName, name) == 0)
00099             break;
00100     if (cur == NULL) {
00101         char msg[256];
00102 
00103         db_free_dbmscap(list);
00104         sprintf(msg, "%s: no such driver available", name);
00105         db_error(msg);
00106         return (dbDriver *) NULL;
00107     }
00108 
00109     /* allocate a driver structure */
00110     driver = (dbDriver *) db_malloc(sizeof(dbDriver));
00111     if (driver == NULL) {
00112         db_free_dbmscap(list);
00113         return (dbDriver *) NULL;
00114     }
00115 
00116     /* copy the relevant info from the dbmscap entry into the driver structure */
00117     db_copy_dbmscap_entry(&driver->dbmscap, cur);
00118     startup = driver->dbmscap.startup;
00119 
00120     /* free the dbmscap list */
00121     db_free_dbmscap(list);
00122 
00123     /* run the driver as a child process and create pipes to its stdin, stdout */
00124 
00125 #ifdef __MINGW32__
00126 #define pipe(fds) _pipe(fds, 250000, _O_BINARY)
00127 #endif
00128 
00129     /* open the pipes */
00130     if ((pipe(p1) < 0) || (pipe(p2) < 0)) {
00131         db_syserror("can't open any pipes");
00132         return (dbDriver *) NULL;
00133     }
00134 
00135     pid = G_spawn_ex(startup,
00136                      SF_BACKGROUND,
00137                      SF_REDIRECT_DESCRIPTOR, 0, p1[READ],
00138                      SF_CLOSE_DESCRIPTOR, p1[WRITE],
00139                      SF_REDIRECT_DESCRIPTOR, 1, p2[WRITE],
00140                      SF_CLOSE_DESCRIPTOR, p2[READ],
00141                      startup, NULL);
00142 
00143     /* create a child */
00144     if (pid < 0) {
00145         db_syserror("can't create fork");
00146         return (dbDriver *) NULL;
00147     }
00148 
00149     close(p1[READ]);
00150     close(p2[WRITE]);
00151 
00152     /* record driver process id in driver struct */
00153     driver->pid = pid;
00154 
00155     /* convert pipes to FILE* */
00156     driver->send = fdopen(p1[WRITE], "wb");
00157     driver->recv = fdopen(p2[READ], "rb");
00158 
00159     /* most systems will have to use unbuffered io to get the send/recv to work */
00160 #ifndef USE_BUFFERED_IO
00161     setbuf(driver->send, NULL);
00162     setbuf(driver->recv, NULL);
00163 #endif
00164 
00165     db__set_protocol_fds(driver->send, driver->recv);
00166     if (db__recv_return_code(&stat) != DB_OK || stat != DB_OK)
00167         driver = NULL;
00168 
00169     return driver;
00170 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines