/* main.c */ #define VERSION_STRING "2" /* Parses the format username[:password]@server[:port] * user:password@server:port = userNULpasswordNULserverNUL (port N/A) */ DECL int parse_url(char * url) { size_t len = strlen(url); size_t sep = 0, ls = 0, rs; while (++sep < len && url[sep] != '@'); while (++ls < len && url[ls] != ':') { if (ls >= sep) { ls = 0; break; } } rs = sep; while (++rs < len && url[rs] != ':'); if (rs == len) { rs = 0; } creds.username = url; url[ls ? ls : sep] = '\0'; if (ls) { creds.password = url + ls + 1; url[sep] = '\0'; } creds.server = url + sep + 1; if (rs) { url[rs] = '\0'; creds.port = atoi(url + rs + 1); } return 0; } DECL void rope(void) { if (session) { irc_destroy_session(session); } api_rope(); } /* All possible failures / successes wipe the password from memory. */ DECL int init(void) { int ret = 0; srand(time(NULL)); memset(&callbacks, 0, sizeof(callbacks)); callbacks.event_connect = event_connect; callbacks.event_channel = event_channel; if(!api_init()) { session = irc_create_session(&callbacks); if (!session) { ERRMSG("Error creating IRC session"); ret = 1; } else { atexit(rope); if (creds.username == NULL || creds.server == NULL) { ERRMSG("Server and Username required. Stopping now"); exit(1); } if (irc_connect(session, creds.server, creds.port, creds.password, creds.username, creds.username, creds.username)) { fprintf(stderr, "IRC ERROR: %s\n", irc_strerror(irc_errno(session))); ret = 1; } } } else { ERRMSG("Error initializing database."); ret = 1; } if (creds.password) { memset(creds.password, '\0', strlen(creds.password)); } return ret; } DECL int loop(void) { /* We should figure out how the failure happens so we can tell the user that. */ if (irc_run(session) != 0) { ERR(1, "Error running IRC session\nPossible issue: bad URL," " no network connection, bad port, refused connection."); } return 0; } DECL void help(void) { ERRMSG(PROGN ": usage\n" "-channel CHANNEL - Sets the target channel\n" "-url URL - Sets the target URL\n" "-db DBFILE - Sets the database file (default: probotic_data.sqlite)\n" "-identify PASSWORD - Identifies against NickServ\n" "-version - Prints version information\n" "-help - Prints this information\n" "\nUse format username[:password]@server[:port], port defaults to 6667.\n"); } DECL void version(void) { ERRMSG(PROGN ": " VERSION_STRING); } int main (int argc, char ** argv) { #ifdef NO_LOGGING freopen(stdout, "/dev/null"); freopen(stderr, "/dev/null"); #endif if (argc > 1) { char * arg; while (++argv, --argc) { arg = *argv; if (*arg == '-') { ++arg; if (strcmp(arg, "version") == 0) { version(); return 1; } else if (strcmp(arg, "help") == 0) { goto help; } if (argc < 2) { goto help; } if (strcmp(arg, "db") == 0) { db = argv[1]; } else if (strcmp(arg, "url") == 0) { parse_url(argv[1]); } else if (strcmp(arg, "channel") == 0) { creds.channel = argv[1]; } else if (strcmp(arg, "identify") == 0) { ident_password = argv[1]; } else { ERR(1,"Unknown command provided"); } ++argv; --argc; } else { goto help; } } } fprintf(stderr, "Connecting to %s:%s@%s:%d\nChannel: %s\n", creds.username, creds.password, creds.server, creds.port, creds.channel); if (init()) { return 1; } return loop(); help: help(); return 1; }