/** * Initialises the CQP program (or cqpserver or cqpcl). * * This function: * - initialises the global variables; * - initialises the built-in random number generator; * - initialises the macro database; * - parses the program options; * - reads the initialisation file; * - reads the macro initialisation file; * - and loads the default corpus, if any. * * @param argc The argc from main() * @param argv The argv from main() * @return Always 1. */ int initialize_cqp(int argc, char **argv) { char *home = NULL; char *homedrive = NULL; char *homepath = NULL; char init_file_fullname[CL_MAX_FILENAME_LENGTH]; /* file handle for initialisation files, if any */ FILE *cqprc; extern int yydebug; /* initialize global variables */ exit_cqp = 0; cqp_file_p = 0; corpuslist = NULL; eep = -1; /* intialise built-in random number generator */ cl_randomize(); /* initialise macro database */ init_macros(); /* parse program options */ parse_options(argc, argv); /* let's always run stdout unbuffered */ /* if (batchmode || rangeoutput || insecure || !isatty(fileno(stdout))) */ if (setvbuf(stdout, NULL, _IONBF, 0) != 0) perror("unbuffer stdout"); yydebug = parser_debug; /* before we start looking for files, let's get the home directory, if we can, * so we don't have to detect it in more than one place. */ #ifndef __MINGW__ home = (char *)getenv("HOME"); #else /* under Windows it is %HOMEDRIVE%%HOMEPATH% */ if ((homepath = (char *)getenv("HOMEPATH")) != NULL && (homedrive = (char *)getenv("HOMEDRIVE")) != NULL ) { home = (char *)cl_malloc(256); sprintf(home, "%s%s", homedrive, homepath); } #endif /* note that either way above, home is NULL if the needed env var(s) were not found. */ /* read initialization file if specified via -I, or if we are in interactive mode */ if (cqp_init_file || (!child_process && (!batchmode || batchfd == NULL) && which_app != cqpserver) ) { /* * Read init file specified with -I <file> * if no init file was specified, and we're not in batchmode, child mode, or cqpserver, * looks for ~/.cqprc * Same with macro init file (-M <file> or ~/.cqpmacros), but ONLY if macros are enabled. */ /* * allow interactive commands during processing of initialization file ??? * (I don't think this is the case!!) */ init_file_fullname[0] = '\0'; /* read init file specified with -I , otherwise look for $HOME/.cqprc */ if (cqp_init_file) sprintf(init_file_fullname, "%s", cqp_init_file); else if (home) sprintf(init_file_fullname, "%s%c%s", home, SUBDIR_SEPARATOR, CQPRC_NAME); if (init_file_fullname[0] != '\0') { if ((cqprc = fopen(init_file_fullname, "r")) != NULL) { reading_cqprc = 1; /* not good for very much, really */ if (!cqp_parse_file(cqprc, 1)) { fprintf(stderr, "Parse errors while reading %s, exiting.\n", init_file_fullname); exit(1); } reading_cqprc = 0; /* fclose(cqprc); was already closed by cqp_parse_file!! */ } else if (cqp_init_file) { fprintf(stderr, "Can't read initialization file %s\n", init_file_fullname); exit(1); } } } if (!enable_macros && macro_init_file) cqpmessage(Warning, "Macros not enabled. Ignoring macro init file %s.", macro_init_file); if (enable_macros && (macro_init_file || (!child_process && (!batchmode || (batchfd == NULL)) && !(which_app == cqpserver)) ) ) { init_file_fullname[0] = '\0'; /* read macro init file specified with -M , otherwise look for ~/.cqpmacros */ if (macro_init_file) sprintf(init_file_fullname, "%s", macro_init_file); else if (home) sprintf(init_file_fullname, "%s%c%s", home, SUBDIR_SEPARATOR, CQPMACRORC_NAME); if (init_file_fullname[0] != '\0') { if ((cqprc = fopen(init_file_fullname, "r")) != NULL) { reading_cqprc = 1; /* not good for very much, really */ if (!cqp_parse_file(cqprc, 1)) { fprintf(stderr, "Parse errors while reading %s, exiting.\n", init_file_fullname); exit(1); } reading_cqprc = 0; /* fclose(cqprc); was already closed by cqp_parse_file!! */ } else if (macro_init_file) { fprintf(stderr, "Can't read macro initialization file %s\n", init_file_fullname); exit(1); } } } /* ends if (!child_process || (batchmode ... ) ... ) */ check_available_corpora(UNDEF); /* load the default corpus. */ if ((default_corpus) && !set_current_corpus_name(default_corpus, 0)) { fprintf(stderr, "Can't set current corpus to default corpus %s, exiting.\n", default_corpus); exit(1); } #ifndef __MINGW__ if (signal(SIGPIPE, SIG_IGN) == SIG_IGN) { /* fprintf(stderr, "Couldn't install SIG_IGN for SIGPIPE signal\n"); */ /* -- be silent about not being able to ignore the SIGPIPE signal, which often happens in slave mode */ /* note that SIGPIPE does not seem to exist in signal.h under MinGW */ signal(SIGPIPE, SIG_DFL); } #endif #ifdef __MINGW__ /* due to how the home path was calculated, home contains a malloc'ed string */ cl_free(home); #endif return 1; }
/** * Main function for the cqpserver app. */ int main(int argc, char *argv[]) { int cmd; which_app = cqpserver; /* TODO: shouldn't these come AFTER initialize_cqp(), as that function may overwrite these values with defaults? * or maybe I've missed some subtlety here....*/ silent = 1; paging = autoshow = auto_save = 0; if (!initialize_cqp(argc, argv)) { Rprintf( "CQPserver: ERROR Couldn't initialise CQP engine.\n"); rcqp_receive_error(1); } cqiserver_welcome(); if (localhost) { add_host_to_list("127.0.0.1"); /* in -L mode, connections from localhost are automatically accepted */ } if (0 < accept_connection(server_port)) { if (server_log) Rprintf("CQPserver: Connected. Waiting for CONNECT request.\n"); } else { Rprintf( "CQPserver: ERROR Connection failed.\n"); rcqp_receive_error(1); } /* establish CQi connection: wait for CONNECT request */ cmd = cqi_read_command(); if (cmd != CQI_CTRL_CONNECT) { if (server_log) Rprintf("CQPserver: Connection refused.\n"); cqiserver_wrong_command_error(cmd); } user = cqi_read_string(); passwd = cqi_read_string(); if (server_log) Rprintf("CQPserver: CONNECT user = '******' passwd = '%s' pid = %d\n", user, passwd, (int)getpid()); /* check password here (always required !!) */ if (!authenticate_user(user, passwd)) { Rprintf("CQPserver: Wrong username or password. Connection refused.\n"); /* TODO shouldn't this be to stderr as it is not conditional on server_log? */ cqi_command(CQI_ERROR_CONNECT_REFUSED); } else { cqi_command(CQI_STATUS_CONNECT_OK); /* re-randomize for query lock key generation */ cl_randomize(); /* check which corpora the user is granted access to */ { CorpusList *cl = FirstCorpusFromList(); while (cl != NULL) { if (!check_grant(user, cl->name)) dropcorpus(cl); cl = NextCorpusFromList(cl); } } /* start command interpreter loop */ interpreter(); if (server_log) Rprintf("CQPserver: User '%s' has logged off.\n", user); } /* connection terminated; clean up and exit */ Rprintf("CQPserver: Exit. (pid = %d)\n", (int)getpid()); /* TODO should we check cqp_error_status as in the main cqp app? */ return 0; }