Пример #1
0
/*!
  \brief Get driver (?)

  \param argc, argv arguments

  \return 0 on success
  \return 1 on failure
 */
int db_driver(int argc, char *argv[])
{
    int stat;
    int procnum;
    int i;
    int rfd, wfd;
    FILE *send, *recv;
    char *modestr;

    /* Read and set environment variables, see dbmi_client/start.c */
    if ((modestr = getenv("GRASS_DB_DRIVER_GISRC_MODE"))) {
	int mode;

	mode = atoi(modestr);

	if (mode == G_GISRC_MODE_MEMORY) {
	    G_set_gisrc_mode(G_GISRC_MODE_MEMORY);
	    G__setenv("DEBUG", getenv("DEBUG"));
	    G__setenv("GISDBASE", getenv("GISDBASE"));
	    G__setenv("LOCATION_NAME", getenv("LOCATION_NAME"));
	    G__setenv("MAPSET", getenv("MAPSET"));
	    G_debug(3, "Driver GISDBASE set to '%s'", G_getenv("GISDBASE"));
	}
    }

#ifdef __MINGW32__
    /* TODO: */
    /* We should close everything except stdin, stdout but _fcloseall()
     * closes open streams not file descriptors. _getmaxstdio too big number.
     * 
     * Because the pipes were created just before this driver was started 
     * the file descriptors should not be above a closed descriptor
     * until it was run from a multithread application and some descriptors 
     * were closed in the mean time. 
     * Also Windows documentation does not say that new file descriptor is 
     * the lowest available.
     */

    {
	int err_count = 0;
	int cfd = 3;

	while (1) {
	    if (close(cfd) == -1)
		err_count++;

	    /* no good reason for 10 */
	    if (err_count > 10)
		break;

	    cfd++;
	}
    }
#endif

    send = stdout;
    recv = stdin;

    /* THIS CODE IS FOR DEBUGGING WITH CODECENTER */

/**********************************************/
    if (argc == 3) {
	rfd = wfd = -1;
	sscanf(argv[1], "%d", &rfd);
	sscanf(argv[2], "%d", &wfd);
	send = fdopen(wfd, "w");
	if (send == NULL) {
	    db_syserror(argv[1]);
	    exit(1);
	}
	recv = fdopen(rfd, "r");
	if (recv == NULL) {
	    db_syserror(argv[2]);
	    exit(1);
	}
    }

/**********************************************/

    db_clear_error();
    db_auto_print_errors(0);
    db_auto_print_protocol_errors(1);
    db__init_driver_state();

#ifndef USE_BUFFERED_IO
    setbuf(recv, NULL);
    setbuf(send, NULL);
#endif
    db__set_protocol_fds(send, recv);

    if (db_driver_init(argc, argv) == DB_OK)
	db__send_success();
    else {
	db__send_failure();
	exit(1);
    }

    stat = DB_OK;
    /* get the procedure number */
    while (db__recv_procnum(&procnum) == DB_OK) {
#ifdef __MINGW32__
	if (procnum == DB_PROC_SHUTDOWN_DRIVER) {
	    db__send_procedure_ok(procnum);
	    break;
	}
#endif
	db_clear_error();

	/* find this procedure */
	for (i = 0; procedure[i].routine; i++)
	    if (procedure[i].procnum == procnum)
		break;

	/* if found, call it */
	if (procedure[i].routine) {
	    if ((stat = db__send_procedure_ok(procnum)) != DB_OK)
		break;		/* while loop */
	    if ((stat = (*procedure[i].routine) ()) != DB_OK)
		break;
	}
	else if ((stat =
		  db__send_procedure_not_implemented(procnum)) != DB_OK)
	    break;
    }

    db_driver_finish();

    exit(stat == DB_OK ? 0 : 1);
}
Пример #2
0
/*!
  \brief Read dbmscap
  
  dbmscap file was used in grass5.0 but it is not used in
  grass5.7 until we find it necessary. All code for dbmscap
  file is commented here. 
  
  Instead of in dbmscap file db_read_dbmscap() searches 
  for available dbmi drivers in $(GISBASE)/driver/db/

  \return pointer to dbDbmscap
*/
dbDbmscap *db_read_dbmscap(void)
{
    /*  
       FILE *fd;
       char *file;
       char name[1024];
       char startup[1024];
       char comment[1024];
       int  line;
     */
    char *dirpath;
    DIR *dir;
    struct dirent *ent;

    dbDbmscap *list = NULL;

    /* START OF OLD CODE FOR dbmscap FILE - NOT USED, BUT KEEP IT FOR FUTURE */
#if 0
    /* get the full name of the dbmscap file */

    file = db_dbmscap_filename();
    if (file == NULL)
	return (dbDbmscap *) NULL;


    /* open the dbmscap file */

    fd = fopen(file, "r");
    if (fd == NULL) {
	db_syserror(file);
	return (dbDbmscap *) NULL;
    }


    /* find all valid entries
     * blank lines and lines with # as first non blank char are ignored
     * format is:
     *   driver name:startup command:comment
     */

    for (line = 1; fgets(buf, sizeof buf, fd); line++) {
	if (sscanf(buf, "%1s", comment) != 1 || *comment == '#')
	    continue;
	if (sscanf(buf, "%[^:]:%[^:]:%[^:\n]", name, startup, comment) == 3)
	    add_entry(&list, name, startup, comment);
	else if (sscanf(buf, "%[^:]:%[^:\n]", name, startup) == 2)
	    add_entry(&list, name, startup, "");
	else {
	    fprintf(stderr, "%s: line %d: invalid entry\n", file, line);
	    fprintf(stderr, "%d:%s\n", line, buf);
	}
	if (list == NULL)
	    break;
    }
    fclose(fd);
#endif
    /* END OF OLD CODE FOR dbmscap FILE */

    /* START OF NEW CODE FOR SEARCH IN $(GISBASE)/driver/db/ */

    /* opend db drivers directory */
#ifdef __MINGW32__
    dirpath = G_malloc(strlen("\\driver\\db\\") + strlen(G_gisbase()) + 1);
    sprintf(dirpath, "%s\\driver\\db\\", G_gisbase());
    G_convert_dirseps_to_host(dirpath);
#else
    G_asprintf(&dirpath, "%s/driver/db/", G_gisbase());
#endif

    G_debug(2, "dbDbmscap(): opendir [%s]", dirpath);
    dir = opendir(dirpath);
    if (dir == NULL) {
	db_syserror("Cannot open drivers directory");
	return (dbDbmscap *) NULL;
    }
    G_free(dirpath);

    /* read all drivers */
    while ((ent = readdir(dir))) {
	char *name;

	if ((strcmp(ent->d_name, ".") == 0)
	    || (strcmp(ent->d_name, "..") == 0))
	    continue;

	/* Remove '.exe' from name (windows extension) */
	name = G_str_replace(ent->d_name, ".exe", "");

#ifdef __MINGW32__
	dirpath = G_malloc(strlen("\\driver\\db\\")
			   + strlen(G_gisbase()) + strlen(ent->d_name) + 1);
	sprintf(dirpath, "%s\\driver\\db\\%s", G_gisbase(), ent->d_name);
	G_convert_dirseps_to_host(dirpath);
#else
	G_asprintf(&dirpath, "%s/driver/db/%s", G_gisbase(), ent->d_name);
#endif
	add_entry(&list, name, dirpath, "");
	G_free(name);
	G_free(dirpath);
    }

    closedir(dir);

    return list;
}
Пример #3
0
/*!
  \brief Initialize a new dbDriver for db transaction.
 
  If <i>name</i> is NULL, the db name will be assigned 
  connection.driverName.
  
  \param name driver name
  
  \return pointer to dbDriver structure
  \return NULL on error
*/
dbDriver *db_start_driver(const char *name)
{
    dbDriver *driver;
    dbDbmscap *list, *cur;
    const char *startup;
    int p1[2], p2[2];
    int pid;
    int stat;
    dbConnection connection;
    char ebuf[5];

    /* Set some environment variables which are later read by driver.
     * This is necessary when application is running without GISRC file and all
     * gis variables are set by application. 
     * Even if GISRC is set, application may change some variables during runtime,
     * if for example reads data from different gdatabase, location or mapset*/

    /* setenv() is not portable, putenv() is POSIX, putenv() in glibc 2.0-2.1.1 doesn't conform to SUSv2,
     * G_putenv() as well, but that is what we want, makes a copy of string */
    if (G_get_gisrc_mode() == G_GISRC_MODE_MEMORY) {
	G_debug(3, "G_GISRC_MODE_MEMORY\n");
	sprintf(ebuf, "%d", G_GISRC_MODE_MEMORY);
	G_putenv("GRASS_DB_DRIVER_GISRC_MODE", ebuf);	/* to tell driver that it must read variables */

	if (G_getenv_nofatal("DEBUG")) {
	    G_putenv("DEBUG", G_getenv_nofatal("DEBUG"));
	}
	else {
	    G_putenv("DEBUG", "0");
	}

	G_putenv("GISDBASE", G_getenv_nofatal("GISDBASE"));
	G_putenv("LOCATION_NAME", G_getenv_nofatal("LOCATION_NAME"));
	G_putenv("MAPSET", G_getenv_nofatal("MAPSET"));
    }
    else {
	/* Warning: GISRC_MODE_MEMORY _must_ be set to G_GISRC_MODE_FILE, because the module can be 
	 *          run from an application which previously set environment variable to G_GISRC_MODE_MEMORY */
	sprintf(ebuf, "%d", G_GISRC_MODE_FILE);
	G_putenv("GRASS_DB_DRIVER_GISRC_MODE", ebuf);
    }

    /* read the dbmscap file */
    if (NULL == (list = db_read_dbmscap()))
	return (dbDriver *) NULL;

    /* if name is empty use connection.driverName, added by RB 4/2000 */
    if (name == '\0') {
	db_get_connection(&connection);
	if (NULL == (name = connection.driverName))
	    return (dbDriver *) NULL;
    }

    /* find this system name */
    for (cur = list; cur; cur = cur->next)
	if (strcmp(cur->driverName, name) == 0)
	    break;
    if (cur == NULL) {
	char msg[256];

	db_free_dbmscap(list);
	sprintf(msg, "%s: no such driver available", name);
	db_error(msg);
	return (dbDriver *) NULL;
    }

    /* allocate a driver structure */
    driver = (dbDriver *) db_malloc(sizeof(dbDriver));
    if (driver == NULL) {
	db_free_dbmscap(list);
	return (dbDriver *) NULL;
    }

    /* copy the relevant info from the dbmscap entry into the driver structure */
    db_copy_dbmscap_entry(&driver->dbmscap, cur);
    startup = driver->dbmscap.startup;

    /* free the dbmscap list */
    db_free_dbmscap(list);

    /* run the driver as a child process and create pipes to its stdin, stdout */

#ifdef __MINGW32__
#define pipe(fds) _pipe(fds, 250000, _O_BINARY | _O_NOINHERIT)
#endif

    /* open the pipes */
    if ((pipe(p1) < 0) || (pipe(p2) < 0)) {
	db_syserror("can't open any pipes");
	return (dbDriver *) NULL;
    }

    close_on_exec(p1[READ]);
    close_on_exec(p1[WRITE]);
    close_on_exec(p2[READ]);
    close_on_exec(p2[WRITE]);

    pid = G_spawn_ex(startup,
		     SF_BACKGROUND,
		     SF_REDIRECT_DESCRIPTOR, 0, p1[READ],
		     SF_CLOSE_DESCRIPTOR, p1[WRITE],
		     SF_REDIRECT_DESCRIPTOR, 1, p2[WRITE],
		     SF_CLOSE_DESCRIPTOR, p2[READ],
		     startup, NULL);

    /* create a child */
    if (pid < 0) {
	db_syserror("can't create fork");
	return (dbDriver *) NULL;
    }

    close(p1[READ]);
    close(p2[WRITE]);

    /* record driver process id in driver struct */
    driver->pid = pid;

    /* convert pipes to FILE* */
    driver->send = fdopen(p1[WRITE], "wb");
    driver->recv = fdopen(p2[READ], "rb");

    /* most systems will have to use unbuffered io to get the send/recv to work */
#ifndef USE_BUFFERED_IO
    setbuf(driver->send, NULL);
    setbuf(driver->recv, NULL);
#endif

    db__set_protocol_fds(driver->send, driver->recv);
    if (db__recv_return_code(&stat) != DB_OK || stat != DB_OK)
	driver = NULL;

    return driver;
}