int commandhandler(BIO *cbio, int cl) { BIO *bbody = NULL, *bbase64 = NULL, *bcrypt = NULL; int ret = -1; char buf[100 * 1024]; json_object *config = NULL; unsigned char iv[16]; BIO *bmem = NULL; char *bptr = NULL, *c = NULL; long blen = 0; char *command = NULL; logme(LOGMSG_DEBUG, "commandhandler (cl=%d)", cl); do { if(!(bmem = BIO_new(BIO_s_mem()))) break; if(!(bbody = BIO_new(BIO_s_mem()))) break; if(!(bbase64 = BIO_new(BIO_f_base64()))) break; BIO_set_flags(bbase64, BIO_FLAGS_BASE64_NO_NL); if(!(bcrypt = BIO_new(BIO_f_cipher()))) break; memset(iv, 0x00, sizeof(iv)); BIO_set_cipher(bcrypt, EVP_get_cipherbyname("aes-128-cbc"), (unsigned char *)conf.key, iv, 0); BIO_push(bbase64, bbody); BIO_push(bcrypt, bmem); while(blen < cl) { if((ret = BIO_read(cbio, buf, ((cl - blen) > sizeof(buf)) ? sizeof(buf) : (cl - blen))) <= 0) break; blen += ret; while((c = memchr(buf, '\n', ret)) || (c = memchr(buf, '\r', ret))) memmove(c, c + 1, --ret - (c - buf)); if(BIO_write(bbody, buf, ret) != ret) { logme(LOGMSG_DEBUG, "BIO_write error"); break; } } do { blen = BIO_read(bbase64, buf, sizeof(buf)); if(blen > 0) { BIO_write(bcrypt, buf, blen); } } while(blen > 0); (void)BIO_flush(bcrypt); blen = BIO_get_mem_data(bmem, &bptr); if(!(config = json_tokener_parse(bptr))) break; if(!(command = (char *)json_object_get_string(json_object_object_get(config, "command")))) break; logme(LOGMSG_DEBUG, "command: %s", command); if(!strcasecmp(command, "FORWARD")) { ret = command_forward(config, cbio); } else if(!strcasecmp(command, "CONFIG")) { ret = command_config(config, cbio); } else if(!strcasecmp(command, "UPGRADE")) { ret = command_upgrade(config, cbio); } else if(!strcasecmp(command, "CHECK")) { ret = command_check(config, cbio); } } while(0); if(bbody) BIO_free(bbody); if(bbase64) BIO_free(bbase64); if(bcrypt) BIO_free(bcrypt); if(bmem) BIO_free(bmem); if(config) json_object_put(config); return ret; }
int main (int argc, const char** argv) { int status = 0; // Create a vector of args. std::vector <std::string> args; for (int i = 1; i < argc; ++i) args.push_back (argv[i]); Config config; config.set ("verbose", "1"); // Some options are hard-coded. if (args.size ()) { if (args[0] == "-h" || closeEnough ("--help", args[0], 3)) command_help (args); else if (args[0] == "-v" || closeEnough ("--version", args[0], 3)) { Color bold ("bold"); std::cout << "\n" << bold.colorize (PACKAGE_STRING) #ifdef HAVE_COMMIT << " " << COMMIT #endif << " built for " #if defined (DARWIN) << "darwin" #elif defined (SOLARIS) << "solaris" #elif defined (CYGWIN) << "cygwin" #elif defined (HAIKU) << "haiku" #elif defined (OPENBSD) << "openbsd" #elif defined (FREEBSD) << "freebsd" #elif defined (NETBSD) << "netbsd" #elif defined (LINUX) << "linux" #elif defined (KFREEBSD) << "GNU/kFreeBSD" #elif defined (GNUHURD) << "GNU/Hurd" #else << "unknown" #endif << "\n" << "Copyright (C) 2010 - 2015 Göteborg Bit Factory." << "\n" << "\n" << "Taskd may be copied only under the terms of the MIT license, " << "which may be found in the taskd source kit." << "\n" << "Documentation for taskd can be found using 'man taskd' or at " << "http://taskwarrior.org" << "\n" << "\n"; } else { try { // Some defaults come from the environment. char* root_env = getenv ("TASKDDATA"); if (root_env) config.set ("root", root_env); // Process all the options. std::vector <std::string> positionals; std::vector <std::string>::iterator arg; for (arg = args.begin (); arg != args.end (); ++arg) { if (closeEnough ("--data", *arg, 3)) { ++arg; if (arg == args.end () || (*arg)[0] == '-') throw std::string (STRING_TASKD_DATA); config.set ("root", *arg); } else if (closeEnough ("--quiet", *arg, 3)) config.set ("verbose", 0); else if (closeEnough ("--debug", *arg, 3)) config.set ("debug", 1); else if (closeEnough ("--force", *arg, 3)) config.set ("confirmation", 0); else if (closeEnough ("--daemon", *arg, 3)) config.set ("daemon", 1); else if (taskd_applyOverride (config, *arg)) ; else positionals.push_back (*arg); } // A database object interfaces to the data. Database db (&config); // The highest-level commands are hard-coded: if (closeEnough ("init", args[0], 3)) command_init (db, positionals); else if (closeEnough ("config", args[0], 3)) command_config (db, positionals); else if (closeEnough ("status", args[0], 3)) command_status (db, positionals); else if (closeEnough ("help", args[0], 3)) command_help ( positionals); else if (closeEnough ("diagnostics", args[0], 3)) command_diag (db, positionals); else if (closeEnough ("server", args[0], 3)) command_server (db, positionals); else if (closeEnough ("add", args[0], 3)) command_add (db, positionals); else if (closeEnough ("remove", args[0], 3)) command_remove (db, positionals); else if (closeEnough ("suspend", args[0], 3)) command_suspend (db, positionals); else if (closeEnough ("resume", args[0], 3)) command_resume (db, positionals); else if (closeEnough ("client", args[0], 3)) command_client (db, positionals); else if (closeEnough ("validate", args[0], 3)) command_validate (db, positionals); else throw format (STRING_TASKD_BAD_COMMAND, args[0]); } catch (std::string& error) { if (error == "usage") { std::vector <std::string> no_args; command_help (no_args); } else std::cout << error << "\n"; status = -1; } catch (std::bad_alloc& error) { std::cerr << "Error: Memory allocation failed: " << error.what () << "\n"; status = -3; } catch (...) { std::cerr << STRING_ERROR_UNKNOWN << "\n"; status = -2; } } } else command_help (args); return status; }