#define _POSIX_C_SOURCE 200809L #include #include #include #include #include #include #include struct fcgi_env { FCGX_Stream *in; FCGX_Stream *out; FCGX_Stream *err; FCGX_ParamArray *envp; }; static sqlite3 *db = NULL; static void cleanup(void) { if (db) { sqlite3_close(db); } } static int cb(void *dat, int count, char **data, char **columns) { struct fcgi_env *env = dat; if (count != 4) { FCGX_FPrintF(env->out, "Status: 500 Internal Server Error\r\n" "Content-type: text/plain\r\n" "\r\n" "The database returned %d columns.\n", count); return 1; } FCGX_FPrintF(env->out, "Content-type: application/json\r\n" "\r\n" "{\"title\":\"%s\",\"title_zh\":\"%s\",\"text\":\"%s\",\"text_zh\":\"%s\"}\n", data[0], data[1] == NULL ? "" : data[1], data[2], data[3]); return 0; } int main(int argc, char **argv) { if (argc != 2) { fprintf(stderr, "Usage: %s /path/to/data.db\n", argv[0]); return 64; } atexit(cleanup); int r; if ((r = sqlite3_open_v2(argv[1], &db, SQLITE_OPEN_READONLY, NULL)) != SQLITE_OK) { fprintf(stderr, "Cannot open database: %s\n", sqlite3_errstr(r)); return r; } FCGX_Stream *in, *out, *err; FCGX_ParamArray envp; struct fcgi_env env; char *errmsg; while(FCGX_Accept(&in, &out, &err, &envp) >= 0) { env.in = in; env.out = out; env.err = err; env.envp = &envp; if ((r = sqlite3_exec(db, "SELECT title,title_zh,text,text_zh FROM v_random_quote", cb, &env, &errmsg))) { FCGX_FPrintF(out, "Status: 500 Internal Server Error\r\n" "Content-type: text/plain\r\n" "\r\n" "%s\n", errmsg); sqlite3_free(errmsg); } } }