start.c

Go to the documentation of this file.
00001 #include <string.h>
00002 #include <stdlib.h>
00003 #include <unistd.h>
00004 #include "dbmi.h"
00005 
00006 #define READ  0
00007 #define WRITE 1
00008 
00009 extern char *getenv();
00010 
00017 dbDriver *
00018 db_start_driver(name)
00019     char *name;
00020 {
00021     dbDriver *driver;
00022     dbDbmscap *list, *cur;
00023     char *startup;
00024     int p1[2], p2[2];
00025     int pid;
00026     int stat;
00027     dbConnection connection;
00028     char ebuf[5];
00029 
00030     /* Set some enviroment variables which are later read by driver.
00031      * This is necessary when application is running without GISRC file and all
00032      * gis variables are set by application. 
00033      * Even if GISRC is set, application may change some variables during runtime,
00034      * if for example reads data from different gdatabase, location or mapset*/
00035     
00036     /* setenv() is not portable, putenv() is POSIX, putenv() in glibc 2.0-2.1.1 doesn't conform to SUSv2,
00037      * G_putenv() as well, but that is what we want, makes a copy of string */
00038     if (  G_get_gisrc_mode() == G_GISRC_MODE_MEMORY ) 
00039     {
00040         sprintf ( ebuf, "%d", G_GISRC_MODE_MEMORY );
00041         G_putenv("GRASS_DB_DRIVER_GISRC_MODE", ebuf); /* to tell driver that it must read variables */
00042         
00043         if ( G__getenv ( "DEBUG" ) ) {
00044             G_putenv( "DEBUG", G__getenv ( "DEBUG" ) );
00045         } else {
00046             G_putenv("DEBUG", "0");
00047         }
00048 
00049         G_putenv( "GISDBASE", G__getenv("GISDBASE") );
00050         G_putenv( "LOCATION_NAME", G__getenv("LOCATION_NAME") );
00051         G_putenv( "MAPSET", G__getenv("MAPSET") );
00052     } 
00053     else 
00054     {
00055         /* Warning: GISRC_MODE_MEMORY _must_ be set to G_GISRC_MODE_FILE, because the module can be 
00056          *          run from an application which previously set enviroment variable to G_GISRC_MODE_MEMORY */
00057         sprintf ( ebuf, "%d", G_GISRC_MODE_FILE );
00058         G_putenv("GRASS_DB_DRIVER_GISRC_MODE", ebuf);
00059     }
00060     
00061 /* read the dbmscap file */
00062     if(NULL == (list = db_read_dbmscap()))
00063         return (dbDriver *) NULL;
00064 
00065 /* if name is empty use connection.driverName, added by RB 4/2000 */
00066     if( name == '\0' )
00067     {
00068         db_get_connection( &connection );
00069         if(NULL == (name = connection.driverName) )
00070            return (dbDriver *) NULL;
00071     }
00072 
00073 /* find this system name */
00074     for (cur = list; cur; cur = cur->next)
00075         if (strcmp (cur->driverName, name) == 0)
00076             break;
00077     if (cur == NULL)
00078     {
00079         char msg[256];
00080 
00081         db_free_dbmscap (list);
00082         sprintf (msg, "%s: no such driver available", name );
00083         db_error (msg);
00084         return (dbDriver *) NULL;
00085     }
00086 
00087 /* allocate a driver structure */
00088     driver = (dbDriver *) db_malloc (sizeof(dbDriver));
00089     if (driver == NULL)
00090     {
00091         db_free_dbmscap (list);
00092         return (dbDriver *) NULL;
00093     }
00094     
00095 /* copy the relevant info from the dbmscap entry into the driver structure */
00096     db_copy_dbmscap_entry (&driver->dbmscap, cur);
00097     startup = driver->dbmscap.startup;
00098 
00099 /* free the dbmscap list */
00100     db_free_dbmscap (list);
00101 
00102 /* run the driver as a child process and create pipes to its stdin, stdout */
00103 
00104 /* open the pipes */
00105     if ((pipe(p1) < 0 ) || (pipe(p2) < 0 ))
00106     {
00107         db_syserror ("can't open any pipes");
00108         return (dbDriver *) NULL;
00109     }
00110 
00111 /* create a child */
00112     if ((pid = fork()) < 0)
00113     {
00114         db_syserror ("can't create fork");
00115         return (dbDriver *) NULL;
00116     }
00117 
00118     if (pid > 0)        /* parent */
00119     {
00120         close(p1[READ]);
00121         close(p2[WRITE]);
00122 
00123 /* record driver process id in driver struct */
00124         driver->pid = pid;
00125 
00126 /* convert pipes to FILE* */
00127         driver->send = fdopen (p1[WRITE], "w");
00128         driver->recv = fdopen (p2[READ],  "r");
00129 
00130 /* most systems will have to use unbuffered io to get the send/recv to work */
00131 #ifndef USE_BUFFERED_IO
00132         setbuf (driver->send, NULL);
00133         setbuf (driver->recv, NULL);
00134 #endif
00135 
00136         db__set_protocol_fds (driver->send, driver->recv);
00137         if(db__recv_return_code(&stat) !=DB_OK || stat != DB_OK)
00138             driver =  NULL;
00139         return driver;
00140     }
00141     else        /* child process */
00142     {
00143         close(p1[WRITE]);
00144         close(p2[READ]);
00145 
00146         close (0);
00147         close (1);
00148 
00149         if (dup(p1[READ]) != 0)
00150         {
00151             db_syserror("dup r");
00152             _exit(127) ;
00153         }
00154 
00155         if (dup(p2[WRITE]) != 1)
00156         {
00157             db_syserror("dup w");
00158             _exit(127) ;
00159         }
00160 
00161         execl ("/bin/sh", "sh", "-c", startup, 0);
00162 
00163         db_syserror ("execl");
00164         return NULL; /* to keep lint, et. al. happy */
00165     }
00166 }

Generated on Sat Jul 22 22:05:40 2006 for GRASS by  doxygen 1.4.7