int main(int argc, char **argv) { int debug = 0, conftest = 0, nodaemon = 0; int i = 0; unsigned int clilen; struct sockaddr_in cliaddr; struct timeval start, end; char *cnfg = DEF_CNFG; char localhost[MAXNAMLEN + 1], path[MAXNAMLEN + 1]; FILE *pidfp; octet_t oct; ruleset_t *rs; /* * Who am I running as ? */ uname(&myname); /* * spocp_err = 0 ; */ memset(&srv, 0, sizeof(srv_t)); pthread_mutex_init(&(srv.mutex), NULL); pthread_mutex_init(&(srv.mlock), NULL); gethostname(localhost, MAXNAMLEN); #ifdef HAVE_GETDOMAINNAME getdomainname(path, MAXNAMLEN); #else { char *pos; if(pos = strstr(localhost, ".")) strncpy(path, pos+1, MAXNAMLEN); else strcpy(path, ""); } #endif if (0) printf("Domain: %s\n", path); srv.hostname = Strdup(localhost); /* * truncating input strings to reasonable length */ for (i = 0; i < argc; i++) if (strlen(argv[i]) > 512) argv[i][512] = '\0'; while ((i = getopt(argc, argv, "Dhrtf:d:")) != EOF) { switch (i) { case 'D': nodaemon = 1; break; case 'f': cnfg = Strdup(optarg); break; case 'd': debug = atoi(optarg); if (debug < 0) debug = 0; break; case 't': conftest = 1; break; case 'r': srv.readonly = 1; case 'h': default: fprintf(stderr, "Usage: %s [-t] ", argv[0]); fprintf(stderr, "[-f configfile] "); fprintf(stderr, "[-D] [-d debuglevel]\n"); exit(0); } } srv.root = ruleset_new(0); if (srv_init(&srv, cnfg) < 0) exit(1); if (srv.port && srv.uds) { fprintf(stderr, "Sorry are not allowed to listen on both a unix domain socket and a port\n"); exit(1); } if (srv.logfile) spocp_open_log(srv.logfile, debug); else if (debug) spocp_open_log(0, debug); if (srv.name){ localcontext = (char *) Calloc(strlen(srv.name) + strlen("//") + 1, sizeof(char)); /* Flawfinder: ignore */ sprintf(localcontext, "//%s", srv.name); } else { localcontext = (char *) Calloc(strlen(localhost) + strlen("//") + 1, sizeof(char)); /* Flawfinder: ignore */ sprintf(localcontext, "//%s", localhost); } /* * where I put the access rules for access to this server and its * rules */ snprintf(path, MAXNAMLEN, "%s/server", localcontext); oct_assign(&oct, path); if ((rs = ruleset_create(&oct, srv.root)) == 0) exit(1); rs->db = db_new(); /* * access rules for operations */ snprintf(path, MAXNAMLEN, "%s/operation", localcontext); oct_assign(&oct, path); if ((rs = ruleset_create(&oct, srv.root)) == 0) exit(1); rs->db = db_new(); LOG(SPOCP_INFO) { traceLog(LOG_INFO, "Local context: \"%s\"", localcontext); traceLog(LOG_INFO, "initializing backends"); if (srv.root->db) plugin_display(srv.plugin); } if (srv.plugin) { run_plugin_init(&srv); } if ( get_rules( &srv ) != SPOCP_SUCCESS ) exit(1); /*ruleset_tree( srv.root, 0);*/ /* If only testing configuration and rulefile this is as far as I go */ if (conftest) { traceLog(LOG_INFO,"Configuration was OK"); exit(0); } gettimeofday(&start, NULL); if (srv.port || srv.uds) { /* * stdin and stdout will not be used from here on, close to * save file descriptors */ fclose(stdin); fclose(stdout); #ifdef HAVE_SSL /* * ---------------------------------------------------------- */ /* * build our SSL context, whether it will ever be used or not */ /* * mutex'es for openSSL to use */ THREAD_setup(); if (srv.certificateFile && srv.privateKey && srv.caList) { traceLog(LOG_INFO,"Initializing the TLS/SSL environment"); if (!(srv.ctx = tls_init(&srv))) { return FALSE; } } /* * ---------------------------------------------------------- */ #endif #ifdef HAVE_SASL { int r = sasl_server_init(sasl_cb, "spocp"); if (r != SASL_OK) { traceLog( LOG_ERR, "Unable to initialized SASL library: %s", sasl_errstring(r, NULL, NULL)); return FALSE; } } #endif saci_init(); if( nodaemon == 0 ) { #ifdef HAVE_DAEMON if (daemon(1, 1) < 0) { fprintf(stderr, "couldn't go daemon\n"); exit(1); } #else daemon_init("spocp", 0); #endif } if (srv.pidfile) { /* * Write the PID file. */ pidfp = fopen(srv.pidfile, "w"); if (pidfp == (FILE *) 0) { fprintf(stderr, "Couldn't open pidfile \"%s\"\n", srv.pidfile); exit(1); } fprintf(pidfp, "%d\n", (int) getpid()); fclose(pidfp); } if (srv.port) { LOG(SPOCP_INFO) traceLog( LOG_INFO, "Asked to listen on port %d", srv.port); if ((srv.listen_fd = spocp_stream_socket(srv.port)) < 0) exit(1); srv.id = (char *) Malloc(16); sprintf(srv.id, "spocp-%d", srv.port); srv.type = AF_INET; } else { LOG(SPOCP_INFO) traceLog(LOG_INFO,"Asked to listen on unix domain socket"); if ((srv.listen_fd = spocp_unix_domain_socket(srv.uds)) < 0) exit(1); srv.id = (char *) Malloc(7 + strlen(srv.uds)); /* Flawfinder: ignore */ sprintf(srv.id, "spocp-%s", srv.uds); srv.type = AF_UNIX; } xsignal(SIGCHLD, sig_chld); xsignal(SIGPIPE, sig_pipe); xsignal(SIGINT, sig_int); xsignal(SIGTERM, sig_term); xsignal(SIGUSR1, sig_usr1); clilen = sizeof(cliaddr); DEBUG(SPOCP_DSRV) traceLog(LOG_DEBUG,"Creating threads"); /* * returns the pool the threads are picking work from */ srv.work = tpool_init(srv.threads, 64, 1); spocp_srv_run(&srv); } else { conn_t *conn; saci_init(); DEBUG(SPOCP_DSRV) traceLog(LOG_DEBUG,"---->"); LOG(SPOCP_INFO) traceLog(LOG_INFO,"Reading STDIN"); /* * If I want to use this I have to do init_server() first * conn = spocp_open_connection( STDIN_FILENO, &srv ) ; */ /* * this is much simpler */ conn = conn_new(); conn_setup(conn, &srv, STDIN_FILENO, "localhost", "127.0.0.1"); LOG(SPOCP_INFO) traceLog(LOG_INFO,"Running server"); spocp_server((void *) conn); gettimeofday(&end, NULL); print_elapsed("query time:", start, end); conn_free( conn ); } srv_free( &srv ); if (cnfg != DEF_CNFG) Free( cnfg ); exit(0); }
solitaire* solitaire_theidiot(mem_context *context, visual_settings *settings) { visual_pile *deck, *pile1, *pile2, *pile3, *pile4, *done; rule *rule1, *rule2; condition *pile1_4_cond; /* The one solitaire instance we have.*/ solitaire* s = mem_alloc(context, sizeof(solitaire)); /* This is the internal data representation of this * solitaire. This is a local struct hidden from other * members. */ internal* i = mem_alloc(context, sizeof(internal)); s->data = i; s->visual = visual_create(context, settings); i->deck = pile_create(context, 52); deck = visual_pile_create(context, i->deck); deck->origin[0] = 0 - (settings->card_width / 2 + settings->card_spacing / 2 + settings->card_width * 2 + settings->card_spacing * 2 + settings->card_width / 2); deck->origin[1] = 40.0f; deck->rotation = 45.0f; deck->action = action_deal(context, s, i); visual_add_pile(context, s->visual, deck); i->pile1 = pile_create(context, 13); pile1 = visual_pile_create(context, i->pile1); pile1->origin[0] = 0 - (settings->card_width / 2 + settings->card_spacing / 2 + settings->card_width + settings->card_spacing); pile1->origin[1] = 70.0f; pile1->translateY = 0 - settings->card_height / 5; visual_add_pile(context, s->visual, pile1); i->pile2 = pile_create(context, 13); pile2 = visual_pile_create(context, i->pile2); pile2->origin[0] = 0 - (settings->card_width / 2 + settings->card_spacing / 2); pile2->origin[1] = 70.0f; pile2->translateY = 0 - settings->card_height / 5; visual_add_pile(context, s->visual, pile2); i->pile3 = pile_create(context, 13); pile3 = visual_pile_create(context, i->pile3); pile3->origin[0] = settings->card_width / 2 + settings->card_spacing / 2; pile3->origin[1] = 70.0f; pile3->translateY = 0 - settings->card_height / 5; visual_add_pile(context, s->visual, pile3); i->pile4 = pile_create(context, 13); pile4 = visual_pile_create(context, i->pile4); pile4->origin[0] = settings->card_width / 2 + settings->card_spacing / 2 + settings->card_width + settings->card_spacing; pile4->origin[1] = 70.0f; pile4->translateY = 0 - settings->card_height / 5; visual_add_pile(context, s->visual, pile4); i->done = pile_create(context, 48); done = visual_pile_create(context, i->done); done->origin[0] = settings->card_width / 2 + settings->card_spacing / 2 + settings->card_width * 2 + settings->card_spacing * 2 + settings->card_width / 2; done->origin[1] = 40.0f; done->rotation = -45.0f; visual_add_pile(context, s->visual, done); card_create_deck(context, i->deck, 14); card_shuffle(i->deck); visual_sync(s->visual); s->ruleset = ruleset_create(context); /* Shared condition between several rules. */ pile1_4_cond = condition_source_array( context, 4, i->pile1, i->pile2, i->pile3, i->pile4); /* Move card to done pile if source is pile1-pile4 and there is a higher card in same suit in those piles. */ rule1 = rule_create(context); rule_add_condition(context, rule1, pile1_4_cond); rule_add_condition(context, rule1, condition_destination(context, i->done)); rule_add_condition( context, rule1, condition_or_array( context, 4, condition_top_card_compare(context, i->pile1, e_dest_higher_value | e_follow_suit), condition_top_card_compare(context, i->pile2, e_dest_higher_value | e_follow_suit), condition_top_card_compare(context, i->pile3, e_dest_higher_value | e_follow_suit), condition_top_card_compare(context, i->pile4, e_dest_higher_value | e_follow_suit))); rule_add_condition(context, rule1, condition_top_card(context)); ruleset_add_rule(context, s->ruleset, rule1); /* Allow move to a top card to an empty pile. */ rule2 = rule_create(context); rule_add_condition(context, rule2, pile1_4_cond); rule_add_condition(context, rule2, condition_top_card(context)); rule_add_condition(context, rule2, condition_destination_empty(context)); rule_add_condition( context, rule2, condition_destination_array( context, 4, i->pile1, i->pile2, i->pile3, i->pile4)); ruleset_add_rule(context, s->ruleset, rule2); /* Solved rule */ s->ruleset->solved = rule_create(context); rule_add_condition( context, s->ruleset->solved, condition_source_card_equal( context, e_suit_none, 14, e_equal_value, i->pile1)); rule_add_condition( context, s->ruleset->solved, condition_source_card_equal( context, e_suit_none, 14, e_equal_value, i->pile2)); rule_add_condition( context, s->ruleset->solved, condition_source_card_equal( context, e_suit_none, 14, e_equal_value, i->pile3)); rule_add_condition( context, s->ruleset->solved, condition_source_card_equal( context, e_suit_none, 14, e_equal_value, i->pile4)); rule_add_condition( context, s->ruleset->solved, condition_card_count_array( context, 1, 4, i->pile1, i->pile2, i->pile3, i->pile4)); return s; }
static void setup_rules(mem_context *context, solitaire *s, internal *i) { condition *ace1_4_cond; rule *rule1, *rule2, *rule3, *rule4, *rule5; s->ruleset = ruleset_create(context); /* Shared condition for the aces. */ ace1_4_cond = condition_destination_array( context, 4, i->ace[0], i->ace[1], i->ace[2], i->ace[3]); /* Allow move of ace to an empty pile among the ace piles. */ rule1 = rule_create(context); rule_add_condition(context, rule1, ace1_4_cond); rule_add_condition(context, rule1, condition_destination_empty(context)); rule_add_condition(context, rule1, condition_top_card(context)); rule_add_condition( context, rule1, condition_source_card_equal(context, e_suit_none, 1, e_equal_value, 0)); rule_add_action(context, rule1, action_reveal_source_top_card(context)); ruleset_add_rule(context, s->ruleset, rule1); /* Allow card to be placed on top of the ace piles following suit and ascending order. */ rule2 = rule_create(context); rule_add_condition(context, rule2, ace1_4_cond); rule_add_condition(context, rule2, condition_top_card(context)); rule_add_condition(context, rule2, condition_top_card_compare( context, 0, e_dest_1lower_value|e_follow_suit)); rule_add_action(context, rule2, action_reveal_source_top_card(context)); ruleset_add_rule(context, s->ruleset, rule2); /* Allow moving several cards to a top card of the opposite suit. */ rule3 = rule_create(context); rule_add_condition( context, rule3, condition_top_card_compare( context, 0, e_dest_1higher_value|e_suit_opposite)); rule_add_condition(context, rule3, condition_source_array( context, 8, i->build[0], i->build[1], i->build[2], i->build[3], i->build[4], i->build[5], i->build[6], i->build[7])); rule_add_condition(context, rule3, condition_destination_array( context, 8, i->build[0], i->build[1], i->build[2], i->build[3], i->build[4], i->build[5], i->build[6], i->build[7])); rule_add_condition(context, rule3, condition_source_card_revealed(context)); rule_add_condition(context, rule3, condition_rest_of_pile(context)); rule_add_condition( context, rule3, condition_source_not_equal_destination(context)); rule_add_action(context, rule3, action_reveal_source_top_card(context)); ruleset_add_rule(context, s->ruleset, rule3); /* Allow moving of kings to an empty pile. */ rule4 = rule_create(context); rule_add_condition(context, rule4, condition_destination_array( context, 8, i->build[0], i->build[1], i->build[2], i->build[3], i->build[4], i->build[5], i->build[6], i->build[7])); rule_add_condition(context, rule4, condition_destination_empty(context)); rule_add_condition(context, rule4, condition_source_card_equal( context, e_suit_none, 13, e_equal_value, 0)); rule_add_condition(context, rule4, condition_rest_of_pile(context)); rule_add_action(context, rule4, action_reveal_source_top_card(context)); ruleset_add_rule(context, s->ruleset, rule4); /* Allow moving a single card to the build piles from the ace piles. */ rule5 = rule_create(context); rule_add_condition(context, rule5, condition_top_card(context)); rule_add_condition( context, rule5, condition_source_array(context, 4, i->ace[0], i->ace[1], i->ace[2], i->ace[3])); rule_add_condition(context, rule5, condition_destination_array( context, 8, i->build[0], i->build[1], i->build[2], i->build[3], i->build[4], i->build[5], i->build[6], i->build[7])); rule_add_condition( context, rule5, condition_top_card_compare( context, 0, e_dest_1higher_value|e_suit_opposite)); ruleset_add_rule(context, s->ruleset, rule5); /* Solved rule */ s->ruleset->solved = rule_create(context); rule_add_condition( context, s->ruleset->solved, condition_card_count_array( context, 13, 4, i->ace[0], i->ace[1], i->ace[2], i->ace[3])); }
SymbolRef pattern_to_grammar(PatternNode *node) { GrammarRuleSet *ruleset; switch (node->type) { case PN_WORD: { int nwords = (int)AR_size(&ar_words); const char **words = AR_data(&ar_words); /* Try to find an existing equal terminal symbol */ SymbolRef res = { SYM_TERMINAL, 0 }; for (res.index = 0; res.index < nwords; ++res.index) if (strcmp(words[res.index], node->text) == 0) break; /* Add a new terminal symbol if none existed. */ if (res.index == nwords) { char *str = strdup(node->text); AR_push(&ar_words, &str); } return res; } case PN_SEQ: { ruleset = ruleset_create(1); assert(ruleset != NULL); ruleset->rules[0] = symrefs_create(2); assert(ruleset->rules[0] != NULL); ruleset->rules[0]->refs[0] = pattern_to_grammar(node->left); ruleset->rules[0]->refs[1] = pattern_to_grammar(node->right); } break; case PN_ALT: { ruleset = ruleset_create(2); assert(ruleset != NULL); ruleset->rules[0] = symrefs_create(1); assert(ruleset->rules[0] != NULL); ruleset->rules[1] = symrefs_create(1); assert(ruleset->rules[1] != NULL); ruleset->rules[0]->refs[0] = pattern_to_grammar(node->left); ruleset->rules[1]->refs[0] = pattern_to_grammar(node->right); } break; case PN_OPT: { ruleset = ruleset_create(2); assert(ruleset != NULL); ruleset->rules[0] = symrefs_create(0); assert(ruleset->rules[0] != NULL); ruleset->rules[1] = symrefs_create(1); assert(ruleset->rules[1] != NULL); ruleset->rules[1]->refs[0] = pattern_to_grammar(node->left); } break; default: assert(false); } ruleset_sort(ruleset); /* See if the rule set matches an existing symbol's rule set */ GrammarRuleSet **rulesets = AR_data(&ar_grammar); size_t nruleset = AR_size(&ar_grammar), n; for (n = 0; n < nruleset; ++n) if (ruleset_cmp(rulesets[n], ruleset) == 0) break; if (n < nruleset) ruleset_destroy(ruleset); else AR_push(&ar_grammar, &ruleset); SymbolRef res = { SYM_NONTERMINAL, (int)n }; return res; }
int read_rules(srv_t * srv, char *file, dbcmd_t * dbc) { FILE *fp; char *sp, *tmp; int n = 0, f = 0, r; octet_t *op; octarr_t *oa = 0; ruleset_t *rs = 0, *trs, *prs; spocp_result_t rc = SPOCP_SUCCESS; spocp_charbuf_t *buf; spocp_chunk_t *chunk = 0, *ck; spocp_chunkwrap_t *cw; spocp_ruledef_t rdef; struct stat statbuf; if ((fp = fopen(file, "r")) == 0) { LOG(SPOCP_EMERG) traceLog(LOG_ERR,"couldn't open rule file \"%s\"", file); op = oct_new( 256, NULL); sp = getcwd(op->val, op->size); traceLog(LOG_ERR,"I'm in \"%s\"", sp); oct_free(op); return -1; } stat( file, &statbuf); srv->mtime = statbuf.st_mtime; /* * The default ruleset should already be set */ if (srv->root == 0) { srv->root = rs = ruleset_new(0); } else rs = srv->root; if (rs->db == 0) rs->db = db_new(); buf = charbuf_new( fp, BUFSIZ ); if (get_more(buf) == 0) return 0; /* * have to escape CR since fgets stops reading when it hits a newline * NUL also has to be escaped since I have problem otherwise finding * the length of the 'string'. '\' hex hex is probably going to be the * choice */ while (rc == SPOCP_SUCCESS ) { cw = get_object( buf, 0 ); if (cw->status == 0) { Free(cw); break; } else if (cw->status == -1) { rc = SPOCP_LOCAL_ERROR; Free(cw); break; } else { chunk = cw->chunk; Free(cw); } if (oct2strcmp(chunk->val, ";include ") == 0) { /* include * file */ ck = chunk->next; tmp = oct2strdup( ck->val, 0 ) ; LOG(SPOCP_DEBUG) traceLog(LOG_DEBUG,"include directive \"%s\"", tmp); if ((rc = read_rules(srv, tmp, dbc)) < 0) { traceLog(LOG_ERR,"Include problem"); } } else if (*chunk->val->val == '/' || *chunk->val->val == '(') { trs = rs; if (*chunk->val->val == '/') { #ifdef AVLUS oct_print(LOG_INFO,"ruleset", chunk->val); #endif if ((trs = ruleset_find( chunk->val, rs)) == NULL) { octet_t oct; octln( &oct, chunk->val); rs = ruleset_create(chunk->val, rs); trs = ruleset_find(&oct, rs); trs->db = db_new(); } ck = chunk->next; } else { ck = chunk; } ruledef_return( &rdef, ck ) ; if( rdef.rule ) { op = chunk2sexp( rdef.rule ) ; oa = octarr_add(oa, op) ; LOG(SPOCP_DEBUG) { traceLog(LOG_DEBUG,"We've got a rule"); } } if( rdef.bcond) { op = chunk2sexp( rdef.bcond ) ; oa = octarr_add(oa, op) ; LOG(SPOCP_DEBUG) { traceLog(LOG_DEBUG,"We've got a boundary condition"); } }