/** * \brief Saves the InfoServ database to disk */ void saveInfoData(void) { SomeNews *news = NULL; int index = 0; db.is = fopen(IS_DB, "w"); if (db.is == NULL) { sSend(":%s GOPER :ERROR: Unable to save Info Article database fopen failed: %s", myname, strerror(errno)); logDump(corelog, "Unable to save Info Article database: fopen: %s", strerror(errno)); return; } /*! \bug Huh? Why check for NULL -twice- ? */ if (is_listhead != NULL) { /* In case list is empty, thanks to Echostar for pointing this cack-handed error out... */ for (news = is_listhead, index = 0; news; news = news->next, index++) { fprintf(db.is, "article %i %s %li %s\n", news->importance, news->from, news->timestamp, news->header); dbWriteString(db.is, news->content); } } fprintf(db.is, "done\n"); fclose(db.is); sSend(":%s PRIVMSG " LOGCHAN " :Completed save(%i articles)", InfoServ, index); }
/*! * \fn void handler(int signal) * \brief Signal handler * \param signal A signal number (such as SIGTERM) * This is the function used by services to handle signals. */ void handler(int sig) { switch (sig) { case SIGTERM: sSend("WALLOPS " ":Received some signal thats telling me to shutdown"); timed_akill_queue(NULL); sshutdown(0); break; case SIGSEGV: timed_akill_queue(NULL); logDump(corelog, "Core dumped ---\n\"%s\"", coreBuffer); sSend("WALLOPS :Segmentation Violation, shutdown NOW"); sSend("GOPER :Buffer is -> %s", coreBuffer); dlogDump(corelog); sshutdown(1); break; case SIGPIPE: timed_akill_queue(NULL); signal(SIGPIPE, SIG_IGN); /*! \bug XXXMLG probably not QUITE right */ /* sshutdown(0);*/ break; default: sSend("GNOTICE :Recieved unidentified signal %i", sig); return; } }
/** * Add a new user, be that ChanServ or a nick in holding. * in the 'mode' variable you can specify +iogsw or any other ircd * compatible modes. * \par Used at services startup */ void addUser(char *nick, char *user, char *host, char *name, char *mode) { if (!nick || !*nick) { return; } sSend("NICK %s 1 0 %s %s %s :%s", nick, user, host, myname, name); sSend(":%s MODE %s :%s", nick, nick, mode); }
/** * \brief Saves the Clone rule database to disk */ void saveTriggerData(void) { int totrules = 0; CloneRule *rule; extern CloneRule *first_crule; db.trigger = fopen(TRG_DB, "w"); if (!db.trigger) { logDump(corelog, "Unable to open trigger database for read access: %s", strerror(errno)); sSend (":%s GLOBOPS :Unable to open trigger database for read access: %s", NickServ, strerror(errno)); return; } for (rule = first_crule; rule; rule = rule->next, ++totrules) { if (fprintf (db.trigger, "Trigger %s %d %d %ld\n", rule->mask, rule->trigger, rule->utrigger, rule->flags) < 0) { logDump(corelog, "Error in writing rule to trigger database: %s", strerror(errno)); break; } if (rule->kill_msg) { if ((fprintf(db.trigger, "Killmsg %s\n", rule->kill_msg)) < 0) { logDump(corelog, "Error in writing trigger rule (killmsg) to trigger database: %s", strerror(errno)); break; } } if (rule->warn_msg) { if ((fprintf(db.trigger, "Warnmsg %s\n", rule->warn_msg)) < 0) { logDump(corelog, "Error in writing trigger rule (warnlmsg) to trigger database: %s", strerror(errno)); break; } } } fprintf(db.trigger, "done\n"); if (fclose(db.trigger) < 0) { logDump(corelog, "Error closing trigger database: %s", strerror(errno)); return; } sSend(":%s PRIVMSG " LOGCHAN " :Completed trigger save (%u rules)", OperServ, totrules); }
/** * Respond to an /INFO message * \param nick Pointer to online user item */ void sendInfoReply(UserList * nick) { char *from = nick->nick; extern char *services_info[]; int i = 0; sSend(":%s 373 %s :Server INFO", myname, from); for (i = 0; services_info[i]; i++) sSend(":%s 371 %s :%s", myname, from, services_info[i]); sSend(":%s 374 %s :End of /INFO list.", myname, from); return; }
/** * \brief Saves the URLS of channels to urls.txt */ void saveChanUrls(RegChanList * first) { return; RegChanList *cl = first; const char *tmpFounderNick; FILE *fpOut; char cstr[258]; fpOut = fopen(CS_DIR "urls.txt.new", "w"); if (!fpOut) return; while (cl) { if (!cl->name || !*cl->name || (cl->restrictlevel > 0)) { cl = cl->next; continue; } if (cl->mlock & (PM_S | PM_P | PM_I | PM_K)) { cl = cl->next; continue; } tmpFounderNick = cl->founderId.getNick(); if (tmpFounderNick == NULL) tmpFounderNick = "-"; sprintf(cstr, ":%.255s", md5_printable(md5_password((u_char *)cl->password))); fprintf(fpOut, "C %s %s %ld %ld %s\n", cl->name, tmpFounderNick, cl->mlock, cl->flags, md5_printable(md5_password((u_char *)cstr))); memset(cstr, 0, 255); if (cl->topic) fprintf(fpOut, "topic %s %s %lu :%s\n", cl->name, *cl->tsetby ? cl->tsetby : "-", cl->ttimestamp, cl->topic); if (cl->url) fprintf(fpOut, "url %s :%s\n", cl->name, cl->url); fflush(fpOut); cl = cl->next; } if (fclose(fpOut) < 0) { sSend("GLOBOPS :Fatal error in writing out urls.txt.new."); return; } if (rename("chanserv/urls.txt.new", "chanserv/urls.txt") < 0) { sSend("GLOBOPS :Error renaming urls.txt.new."); return; } }
int send_from_fifo(int fd) { int len; if( !session_isValid(fd) ) return -1; if( session[fd]->wdata_size == 0 ) return 0; // nothing to send len = sSend(fd, (const char *) session[fd]->wdata, (int)session[fd]->wdata_size, 0); if( len == SOCKET_ERROR ) {//An exception has occured if( sErrno != S_EWOULDBLOCK ) { //ShowDebug("send_from_fifo: error %d, ending connection #%d\n", sErrno, fd); session[fd]->wdata_size = 0; //Clear the send queue as we can't send anymore. [Skotlex] set_eof(fd); } return 0; } if( len > 0 ) { // some data could not be transferred? // shift unsent data to the beginning of the queue if( (size_t)len < session[fd]->wdata_size ) memmove(session[fd]->wdata, session[fd]->wdata + len, session[fd]->wdata_size - len); session[fd]->wdata_size -= len; } return 0; }
/** * @brief Make a fake mass client */ char * make_clone() { static char rand_nick[NICKLEN + 1]; char rand_user[USERLEN + 1]; char host[HOSTLEN + 1], blip1[6], blip2[5]; char rand_ircname[50]; int fails = 0; (void)ranstring(rand_nick, NICKLEN - 1, 0); (void)ranstring(rand_user, USERLEN - 1, 2); (void)ranstring(rand_ircname, sizeof(rand_ircname) - 1, 1); (void)ranstring(blip1, sizeof(blip1) - 1, 0); (void)ranstring(blip2, sizeof(blip2) - 1, 1); snprintf(host, sizeof(host), "services-%lx.%s-sorcery-massdetect.net", (time(0)/30)%1000, blip1); if (getNickData(rand_nick) || getRegNickData(rand_nick)) { while ((getNickData(rand_nick) || getRegNickData(rand_nick)) && fails < 50) { (void)ranstring(rand_nick, NICKLEN - 1, 0); if (fails++ > 20) return NULL; else if (fails > 1 && fails < 3) sSend("GLOBOPS :[***] make_clone(MassServ): nick %s already exists", rand_nick); } } addUser(rand_nick, rand_user, host, rand_ircname, "+m"); return rand_nick; }
/*! * \fn void sshutdown(int type) * \brief Shuts down services * \param type specifies type of shutdown (fatal error, normal exit, etc) * * \bug XXXMLG This needs to be done better... I suggest #defines for the * various things we want this function to do (save data, send message, * etc) and then use something like: * sshutdown(SHUTDOWN_SAVE | SHUTDOWN_MSG, "This is the message"); */ void sshutdown(int type) { if (type != (-1) && type != 2) { writeServicesTotals(); saveakills(); saveNickData(); syncChanData(1); saveMemoData(); saveInfoData(); } timed_akill_queue(NULL); unlink("services.pid"); if (1 /*type == 0 || type == -1 || type > 2 */ ) { #ifdef USE_SQL if (dbConn != NULL) PQfinish(dbConn); dbConn = NULL; #endif } if (type == 1) { sSend("SQUIT %s :Services %s fall down go BOOM!", hostname, VERSION_NUM); close(server); abort(); /* dump a core file */ } else if (type == 2) { /* No connection to server established */ fprintf(stderr, "Error connecting to server, check above message\n"); exit(-1); } else if (type == 0) { sSend("SQUIT %s :Services %s shutdown", hostname, VERSION_NUM); if (server != -1) { close(server); } exit(66); } else { sSend("SQUIT %s :Services %s shutdown", hostname, VERSION_NUM); close(server); exit(1); } }
/** * @param source Sender nickname * @param buf Message text * @param which Value indicating which client received the message * @brief handle an incoming message to a MassServ fake client */ void detect_mass(UserList *nl_from, char *buf, int which) { aMassAd *booya; aMassAd *f1, *f2, *f1o, *f2o; expire_ads(); if (nl_from != 0) { f1o = f1 = find_ad(nl_from, 0); f2o = f2 = find_ad(nl_from, 1); } else return; if (nl_from && ((!f1 && which == 0) || (!f2 && which == 1))) { booya = (aMassAd *) oalloc(sizeof(aMassAd)); booya->sender = nl_from; booya->utc = time(NULL); booya->rcvd_by = which; insert_ad(booya); if (!booya->sender) logDump(corelog, "[***] bug: booya->sender is NULL in detect_mass()"); } if (f1 == NULL) f1 = find_ad(nl_from, 0); if (f2 == NULL) f2 = find_ad(nl_from, 1); if (f1 != NULL && f2 != NULL) { sSend(":%s GLOBOPS :\2Mass Ad:\2 (%s) %s", MassServ, nl_from->nick, buf); flush_ad(nl_from); // sSend(":%s SVSKILL %s :killed ([services] (Mass msg'ing))", source); } else if (!f1o && !f2o) sSend(":%s GLOBOPS :(Debug) \2Possible Mass Ad:\2 (%s) %s", MassServ, nl_from->nick, buf); return; }
/** * @brief Maintain the advert detection bots' presence and expire old * advert information periodically */ void adCloneMaintenance() { char *y; int k; if (massAdClones[0] == 0 && massAdClones[1] == 0) { if ((y = make_clone())) { massAdClones[0] = strdup(y); if ((y = make_clone())) massAdClones[1] = strdup(y); } massAdClones[2] = massAdClones[3] = massAdClones[4] = NULL; } else { if (massAdClones[0]) { sSend(":%s QUIT :%s", massAdClones[0], massAdClones[0]); massAdClones[2] = massAdClones[0]; if ((y = make_clone())) massAdClones[0] = strdup(y); } if (massAdClones[1]) { sSend(":%s QUIT :%s", massAdClones[1], massAdClones[1]); massAdClones[3] = massAdClones[1]; if ((y = make_clone())) massAdClones[1] = strdup(y); } for(k = 2; k < 4; k++) { if (massAdClones[k]) { FREE(massAdClones[k]); massAdClones[k] = 0; } } } }
void checkTusers(char *) { #ifdef PLUSLCHAN static u_int last_mostusers = 0; if (last_mostusers < mostusers) { sSend(":%s MODE %s +l %lu", OperServ, PLUSLCHAN, mostusers + 5); last_mostusers = mostusers; } timer(60, checkTusers, NULL); #endif }
int send_from_fifo(int fd) { ssize_t len; if( !sockt->session_isValid(fd) ) return -1; if( session[fd]->wdata_size == 0 ) return 0; // nothing to send len = sSend(fd, (const char *) session[fd]->wdata, (int)session[fd]->wdata_size, MSG_NOSIGNAL); if( len == SOCKET_ERROR ) {//An exception has occured if( sErrno != S_EWOULDBLOCK ) { //ShowDebug("send_from_fifo: %s, ending connection #%d\n", error_msg(), fd); #ifdef SHOW_SERVER_STATS socket_data_qo -= session[fd]->wdata_size; #endif session[fd]->wdata_size = 0; //Clear the send queue as we can't send anymore. [Skotlex] set_eof(fd); } return 0; } if( len > 0 ) { // some data could not be transferred? // shift unsent data to the beginning of the queue if( (size_t)len < session[fd]->wdata_size ) memmove(session[fd]->wdata, session[fd]->wdata + len, session[fd]->wdata_size - len); session[fd]->wdata_size -= len; #ifdef SHOW_SERVER_STATS socket_data_o += len; socket_data_qo -= len; if (!session[fd]->flag.server) { socket_data_co += len; } #endif } return 0; }
void readRegData(void) { char tmp2[10 + HOSTLEN], tmp[10]; int lineread = 1, i; db.nsreg = fopen("nickserv/nickregs.db", "r"); if(!db.nsreg) return; while(sfgets(tmp, 10, db.nsreg)) { if(tmp[0] != '-') { sSend("GOPER :!ERROR! NickServ databases are corrupted (line %i)", lineread); sshutdown(1); } sfgets(tmp2, 10 + HOSTLEN, db.nsreg); addNReg(tmp2); sfgets(tmp, 10, db.nsreg); i = atoi(tmp); for(i--;i;i--) addNReg(tmp2); } fclose(db.nsreg); }
void MainWindow::setSingnals() { connect(fileMenuNew, SIGNAL(triggered()), this, SLOT( sNew() )); connect(fileMenuOpen, SIGNAL(triggered()), this, SLOT( sOpen() )); connect(fileMenuSave, SIGNAL(triggered()), this, SLOT( sSave() )); connect(fileMenuQuit, SIGNAL(triggered()), qApp, SLOT(quit() )); connect(fileMenuSaveAs, SIGNAL(triggered()), this, SLOT( sSaveAs() )); connect(this->ui->send_button, SIGNAL(clicked()), this, SLOT(sSend())); //connect(przyklad, SIGNAL(triggered()), this, SLOT( sEg((QString)"przyklad") )); connect(Run, SIGNAL(triggered()), this, SLOT( sRun() )); connect(Debug, SIGNAL(triggered()), this, SLOT( sDebug() )); connect(Stop, SIGNAL(triggered()), this, SLOT( sStop() )); connect(Undo, SIGNAL(triggered()), this, SLOT( sUndo() )); connect(Redo, SIGNAL(triggered()), this, SLOT( sRedo() )); connect(Copy, SIGNAL(triggered()), this, SLOT(sCopy())); connect(Cut, SIGNAL(triggered()), this, SLOT(sCut())); connect(Paste, SIGNAL(triggered()), this, SLOT(sPaste())); connect(toC, SIGNAL(triggered()), this, SLOT(sToC())); connect(toJava, SIGNAL(triggered()), this, SLOT(sToJava())); }
/** * \brief Loads the clone rule database from disk */ void readTriggerData(void) { CloneRule *rule = NULL; char *command, *text; int done = 0; unsigned long linenum = 0; db.trigger = fopen(TRG_DB, "r"); if (db.trigger == NULL) { logDump(corelog, "Unable to open trigger database for read access: %s", strerror(errno)); return; } while (!done) { if (!(sfgets(dbLine, 2048, db.trigger))) { if (!done) { unexpected_eof(TRG_DB); } done = 1; fclose(db.trigger); return; } linenum++; if (parse_init(&state, dbLine) != 0) { /*! \bug XXX be nicer here... */ abort(); } command = parse_getarg(&state); if (strcmp(command, "Trigger") == 0) { rule = NewCrule(); rule->kill_msg = NULL; rule->warn_msg = NULL; strncpyzt(rule->mask, parse_getarg(&state), sizeof(rule->mask)); rule->mask[sizeof(rule->mask) - 1] = '\0'; rule->trigger = atoi(parse_getarg(&state)); rule->utrigger = atoi(parse_getarg(&state)); rule->flags = atol(parse_getarg(&state)); AddCrule(rule, -2); /* -2 is magic for append to end */ } else if (strcmp(command, "Killmsg") == 0) { text = parse_getallargs(&state); if (text && rule) rule->kill_msg = strdup(text); } else if (strcmp(command, "Warnmsg") == 0) { text = parse_getallargs(&state); if (text && rule) rule->warn_msg = strdup(text); } else if (strcmp(command, "done") == 0) { done = 1; } else { fprintf(stderr, "Error in reading trigger data (%s) %lu\n", dbLine, linenum); parse_cleanup(&state); return; } #ifdef DBDEBUG sSend(":%s PRIVMSG " DEBUGCHAN " :Read trigger data (%s)", OperServ, dbLine); #endif parse_cleanup(&state); } fclose(db.trigger); }
/** * \brief Loads the memo database from disk */ void readMemoData(void) { RegNickList *nick = NULL; RegNickList *from, *rnlb; MemoList *newmemo; char *command; char *topic; int done = 0; unsigned long linenum = 0; db.ms = fopen(MS_DB, "r"); if (db.ms == NULL) return; while (!done) { if (!(sfgets(dbLine, 2048, db.ms))) { if (!done) { unexpected_eof(MS_DB); } done = 1; fclose(db.ms); return; } linenum++; if (parse_init(&state, dbLine) != 0) { /*! \bug XXX be nicer here... */ abort(); } command = parse_getarg(&state); if (strcmp(command, "data") == 0) { nick = getRegNickData(parse_getarg(&state)); /*! \bug Increment the arguments.. we REALLY need to fix the dbs */ (void)parse_getarg(&state); (void)parse_getarg(&state); if (nick) { nick->memos->flags = atoi(parse_getarg(&state)); nick->memos->max = atoi(parse_getarg(&state)); if (nick->memos->max <= 0) nick->memos->max = MS_DEF_RCV_MAX; } } else if (strcmp(command, "mblock") == 0) { MemoBlock *mbitem; if (nick && nick->memos) { char *nickToBlock; if ((nickToBlock = parse_getarg(&state)) && (rnlb = getRegNickData(nickToBlock))) { mbitem = (MemoBlock *) oalloc(sizeof(MemoBlock)); mbitem->blockId = rnlb->regnum; mbitem->next = nick->memos->firstMblock; nick->memos->firstMblock = mbitem; } } } else if (strcmp(command, "redirect") == 0) { nick = getRegNickData(parse_getarg(&state)); if (nick != NULL) nick->memos->forward = getRegNickData(parse_getarg(&state)); } else if (strcmp(command, "memo") == 0) { char *cn; cn = parse_getarg(&state); nick = getRegNickData(cn); if (nick == NULL) { printf("memo: %s not valid\n", cn); continue; } newmemo = (MemoList *) oalloc(sizeof(MemoList)); newmemo->realto = nick; /*! \bug Increment the argument 1, we need to fix the db */ (void)parse_getarg(&state); newmemo->flags = atoi(parse_getarg(&state)); newmemo->sent = (time_t) atol(parse_getarg(&state)); /* Memo expiration code */ if ((time(NULL) - newmemo->sent) >= NICKDROPTIME && !(newmemo->flags & MEMO_SAVE)) { FREE(newmemo); continue; } strncpyzt(newmemo->from, parse_getarg(&state), NICKLEN); from = getRegNickData(newmemo->from); strncpyzt(newmemo->to, parse_getarg(&state), CHANLEN); /* Read the memo, skipping the leading : */ topic = parse_getallargs(&state); if (topic == NULL) { FREE(newmemo); continue; } newmemo->memotxt = strdup(topic); /* Add the memo to the users memobox */ LIST_ENTRY_INIT(newmemo, ml_lst); LIST_INSERT_HEAD(&nick->memos->mb_memos, newmemo, ml_lst); if (from && newmemo->flags & MEMO_UNREAD) LIST_INSERT_HEAD(&from->memos->mb_sent, newmemo, ml_sent); nick->memos->memocnt++; } else if (strcmp(command, "done") == 0) { done = 1; } else { fprintf(stderr, "Error in reading memo data (%s) %lu\n", dbLine, linenum); sshutdown(-1); } #ifdef DBDEBUG sSend(":%s PRIVMSG " DEBUGCHAN " :Read memo data (%s)", MemoServ, dbLine); #endif parse_cleanup(&state); } fclose(db.ms); }
/** * \brief Saves the Memo database to disk */ void saveMemoData(void) { RegNickList *nl; MemoBox *tmp; MemoList *memo; MemoBlock *mbitem; const char *tmpNickName; int bucket; int totmemos; int totboxes; db.ms = fopen(MS_DB, "w"); totmemos = 0; totboxes = 0; for (bucket = 0; bucket < NICKHASHSIZE; bucket++) { nl = LIST_FIRST(&RegNickHash[bucket]); while (nl != NULL) { tmp = nl->memos; if (tmp != NULL) { totboxes++; fprintf(db.ms, "data %s %i %i %i %i\n", nl->nick, tmp->memocnt, tmp->flags, tmp->flags, tmp->max); if (tmp->forward) fprintf(db.ms, "redirect %s %s\n", nl->nick, tmp->forward->nick); for (mbitem = tmp->firstMblock; mbitem; mbitem = mbitem->next ) { if ((tmpNickName = mbitem->blockId.getNick())) fprintf(db.ms, "mblock %s\n", tmpNickName); } for (memo = LIST_FIRST(&tmp->mb_memos); memo; memo = LIST_NEXT(memo, ml_lst)) { if (ShouldMemoExpire(memo, 0)) { memo = LIST_NEXT(memo, ml_lst); if (memo == NULL) break; continue; } fprintf(db.ms, "memo %s %i %i %lu %s %s :%s\n", nl->nick, 0, memo->flags, (long)memo->sent, memo->from, memo->to, memo->memotxt); totmemos++; } } nl = LIST_NEXT(nl, rn_lst); } } fprintf(db.ms, "done\n"); fclose(db.ms); sSend(":%s PRIVMSG " LOGCHAN " :Completed save(%u boxes, %u memos)", MemoServ, totboxes, totmemos); }
/** * \brief Loads the ChanServ database from disk */ void readChanData() { RegChanList *rcl; RegNickList *rnl; char *command; int done = 0, db_version = 1; int line_num = 0; char *pass; char *topic; rcl = NULL; rnl = NULL; db.cs = fopen(CS_DIR "chanserv.db", "r"); if (db.cs == NULL) return; while (!done) { if ((sfgets(dbLine, 2048, db.cs)) == 0) { if (!done) { unexpected_eof(CS_DB); } done = 1; fclose(db.cs); return; } line_num++; if (parse_init(&state, dbLine) != 0) { fprintf(stderr, CS_DIR "chanserv.db:%d: " " Fatal error during read " " (Null line?) \n", line_num); abort(); } command = parse_getarg(&state); if (!strcmp(command, "version")) { db_version = atoi(parse_getarg(&state)); } else if (!strcmp(command, "channel")) { char *sChannelName, *sFounderNick; rcl = (RegChanList *) oalloc(sizeof(RegChanList)); sChannelName = parse_getarg(&state); sFounderNick = parse_getarg(&state); initRegChanData(rcl); if (strlen(sChannelName) >= CHANLEN) { fprintf(stderr, CS_DIR "chanserv.db:%d: " " Channel name '%.80s' exceeds " " CHANLEN.\n", line_num, sChannelName); sshutdown(-1); } else if (strlen(sFounderNick) >= NICKLEN) { fprintf(stderr, CS_DIR "chanserv.db:%d: " " Founder nick name '%.80s' " " (%.80s)" " exceeds NICKLEN.\n", line_num, sFounderNick, sChannelName); sshutdown(-1); } if (!sChannelName || !sFounderNick) { fprintf(stderr, CS_DIR "chanserv.db:%d: " " Parse error. (%p, %p)", line_num, sChannelName, sFounderNick); sshutdown(-1); } rnl = getRegNickData(sFounderNick); strcpy(rcl->name, sChannelName); if (rnl) { rcl->founderId = rnl->regnum; rnl->chans++; } else rcl->founderId = RegId(0, 0); rcl->mlock = atol(parse_getarg(&state)); rcl->flags = atol(parse_getarg(&state)); pass = parse_getarg(&state); /*! \bug XXX verify this works */ if (!pass) { fprintf(stderr, CS_DIR "chanserv.db:%d: " " Null password?!", line_num); sshutdown(-1); } if ((db_version < 2) || *pass == '@') { if (db_version < 2) strcpy((char *)rcl->password, pass); else strcpy((char *)rcl->password, pass + 1); if (strlen(pass) > (u_int)((db_version < 2) ? PASSLEN : PASSLEN+1)) { fprintf(stderr, CS_DIR "chanserv.db:%d: " " password > PASSLEN", line_num); sshutdown(-1); } xorit((char *)rcl->password); rcl->flags &= ~CENCRYPT; } else { u_char *tmpup = fromBase64(pass+1, NULL); int q; if (!tmpup) abort(); for(q = 0; q < 16; q++) rcl->password[q] = tmpup[q]; FREE(tmpup); rcl->flags |= CENCRYPT; } rcl->timereg = (time_t) atol(parse_getarg(&state)); rcl->timestamp = (time_t) atol(parse_getarg(&state)); strncpyzt(rcl->key, parse_getarg(&state), KEYLEN); rcl->limit = atol(parse_getarg(&state)); rcl->memolevel = atoi(parse_getarg(&state)); rcl->tlocklevel = atoi(parse_getarg(&state)); rcl->restrictlevel = atoi(parse_getarg(&state)); /* The rest of the line - skipping the leading : */ topic = parse_getallargs(&state); if (topic == NULL) rcl->desc[0] = '\0'; else strncpyzt(rcl->desc, topic, CHANDESCBUF); addRegChan(rcl); mostchans++; } else if (!strcmp(command, "topic")) { rcl = getRegChanData(parse_getarg(&state)); if (rcl == NULL) continue; strncpyzt(rcl->tsetby, parse_getarg(&state), NICKLEN); rcl->ttimestamp = (time_t) atol(parse_getarg(&state)); /* The rest of the topic, skipping the : in it */ topic = parse_getallargs(&state); if (topic == NULL) rcl->topic = NULL; else rcl->topic = strdup(topic); } else if (!strcmp(command, "url")) { rcl = getRegChanData(parse_getarg(&state)); if (rcl == NULL) continue; topic = parse_getallargs(&state); if (topic == NULL) rcl->url = NULL; else rcl->url = strdup(topic); } else if (!strcmp(command, "autogreet")) { rcl = getRegChanData(parse_getarg(&state)); if (rcl == NULL) continue; topic = parse_getallargs(&state); if (topic == NULL) rcl->autogreet = NULL; else rcl->autogreet = strdup(topic); } else if (!strcmp(command, "markby")) { rcl = getRegChanData(parse_getarg(&state)); if (rcl == NULL) continue; topic = parse_getarg(&state); if (topic == NULL) rcl->markby = NULL; else rcl->markby = strdup(topic); } else if (strcmp(command, "chkey") == 0) { char *tmpp = parse_getarg(&state); if (rcl && tmpp) rcl->chpw_key = strtoul(tmpp, (char **)0, 16); } else if (!strcmp(command, "op")) { cAccessList *lame; char *tmpName; rcl = getRegChanData(parse_getarg(&state)); if (rcl == NULL) continue; tmpName = parse_getarg(&state); if ((rnl = getRegNickData(tmpName)) != NULL) { lame = (cAccessList *) oalloc(sizeof(cAccessList)); lame->nickId = rnl->regnum; lame->uflags = atoi(parse_getarg(&state)); addChanOp(rcl, lame); } } else if (!strcmp(command, "akick")) { cAkickList *lame; lame = (cAkickList *) oalloc(sizeof(cAkickList)); rcl = getRegChanData(parse_getarg(&state)); if (rcl == NULL) continue; strncpyzt(lame->mask, parse_getarg(&state), 70); lame->added = (time_t) atol(parse_getarg(&state)); /* The rest of the string... */ topic = parse_getallargs(&state); if (topic == NULL) lame->reason[0] = '\0'; else { strncpyzt(lame->reason, topic, NICKLEN + 50); } addChanAkick(rcl, lame); } else if (!strcmp(command, "done")) done = 1; else { fprintf(stderr, "GLOBOPS :Read chan data (%s)", dbLine); sshutdown(-1); } #ifdef DBDEBUG sSend(":%s PRIVMSG " DEBGUGCHAN " :Read chan data (%s)", ChanServ, dbLine); #endif parse_cleanup(&state); } fclose(db.cs); }
/** * \brief Saves the ChanServ database to disk */ void saveChanData(RegChanList * first) { RegChanList *cl = first; cAccessList *accitem; cAkickList *akitem; const char *tmpFounderNick; int x = 0; saveChanUrls(first); db.cs = NULL; db.cs = fopen(CS_DIR "chanserv.db", "w"); if (db.cs == NULL) { sSend(":%s GOPER :ERROR: Unable to save Channel database fopen failed: %s", myname, strerror(errno)); logDump(corelog, "Unable to save Channel database: fopen: %s", strerror(errno)); return; } fprintf(db.cs, "version 2\n"); while (cl) { tmpFounderNick = cl->founderId.getNick(); if (tmpFounderNick == NULL) tmpFounderNick = "-"; /* New chan insertion point */ fprintf(db.cs, "channel "); fprintf(db.cs, "%s %s ", cl->name, tmpFounderNick); fprintf(db.cs, "%lu %lu ", cl->mlock, cl->flags); if (!(cl->flags & CENCRYPT)) { strcpy(cryptstr, (char *)cl->password); xorit(cryptstr); fprintf(db.cs, "@%s ", cryptstr); } else { u_char *tmpup = toBase64(cl->password, 16); if (!tmpup) abort(); fprintf(db.cs, "$%s ", tmpup); FREE(tmpup); } fprintf(db.cs, "%lu ", (unsigned long)cl->timereg); fprintf(db.cs, "%lu ", (unsigned long)cl->timestamp); fprintf(db.cs, "%s %lu %i ", cl->key, cl->limit, cl->memolevel); fprintf(db.cs, "%i %i :%s\n", cl->tlocklevel, cl->restrictlevel, cl->desc); if (cl->topic) fprintf(db.cs, "topic %s %s %lu :%s\n", cl->name, cl->tsetby, cl->ttimestamp, cl->topic); if (cl->url) fprintf(db.cs, "url %s :%s\n", cl->name, cl->url); if (cl->autogreet != NULL) fprintf(db.cs, "autogreet %s :%s\n", cl->name, cl->autogreet); if ((cl->flags & CMARK) && cl->markby) fprintf(db.cs, "markby %s %s\n", cl->name, cl->markby); if (cl->chpw_key) fprintf(db.cs, "chkey %X\n", cl->chpw_key); if (cl->firstOp) { const char *tmpName; for (accitem = cl->firstOp; accitem; accitem = accitem->next) { tmpName = (accitem->nickId).getNick(); if (tmpName == NULL) continue; fprintf(db.cs, "op %s %s ", cl->name, tmpName); fprintf(db.cs, "%i\n", accitem->uflags); } } if (cl->firstAkick) { for (akitem = cl->firstAkick; akitem; akitem = akitem->next) { fprintf(db.cs, "akick %s %s ", cl->name, akitem->mask); fprintf(db.cs, "%lu :%s\n", (u_long) akitem->added, akitem->reason); } } x++; fflush(db.cs); #ifdef DBDEBUG sSend(":%s PRIVMSG " DEBUGCHAN " :Saved chan data (%s)", ChanServ, cl->name); #endif cl = cl->next; } fprintf(db.cs, "done\n"); fflush(db.cs); fclose(db.cs); #ifdef GLOBOPS_TIMED_MSGS sSend(":%s GLOBOPS :Completed save(%i)", ChanServ, x); #else sSend(":%s PRIVMSG " LOGCHAN " :Completed save(%i)", ChanServ, x); #endif }
/** * \brief Loads the NickServ database from disk */ void readNickData() { RegNickList *rnl = NULL; char *command, *tmpp; unsigned char *tmpup; int done = 0, db_version = 1; int line_num = 0, do_enc = 0; #ifdef REQ_EMAIL readRegData(); #endif db.ns = fopen(NS_DB, "r"); if (db.ns == NULL) { logDump(corelog, "Unable to open " NS_DB ": %s", strerror(errno)); return; } while (!done) { if (!(sfgets(dbLine, 1024, db.ns))) { if (!done) { unexpected_eof(NS_DB); } done = 1; fclose(db.ns); return; } line_num++; if (parse_init(&state, dbLine) != 0) { /*! \bug XXX make a nicer error here! */ abort(); } command = parse_getarg(&state); if (strcmp(command, "version") == 0) { tmpp = parse_getarg(&state); assert(tmpp); if (tmpp) db_version = atoi(tmpp); } else if (strcmp(command, "nick") == 0) { rnl = (RegNickList *) oalloc(sizeof(RegNickList)); char *sNick, *sUser, *sHost, *sPass; sNick = parse_getarg(&state); sUser = parse_getarg(&state); sHost = parse_getarg(&state); sPass = parse_getarg(&state); if (strlen(sNick) >= NICKLEN) { fprintf(stderr, NS_DB ":%d: " " Nickname '%.80s' exceeds " " NICKLEN.\n", line_num, sNick); sshutdown(-1); } strcpy(rnl->nick, sNick); strncpyzt(rnl->user, sUser, USERLEN); SetDynBuffer(&rnl->host, sHost); if (db_version < 2) { if (strlen(sPass) > PASSLEN) { fprintf(stderr, NS_DB ":%d: " " Password for nick '%s' " " exceeds PASSLEN.\n", line_num, sNick); sshutdown(-1); } strcpy((char *)rnl->password, xorit(sPass)); } else { char encType = *sPass; if (encType == '@') { if (strlen(sPass+1) > PASSLEN) { fprintf(stderr, NS_DB ":%d: " " Password for nick '%s' " " exceeds PASSLEN.\n", line_num, sNick); sshutdown(-1); } strcpy((char *)rnl->password, xorit(sPass + 1)); do_enc = 0; } else if (encType == '$') { int q, len; tmpup = fromBase64(sPass + 1, &len); assert(tmpup); for(q = 0; q < 16; q++) rnl->password[q] = tmpup[q]; do_enc = 1; FREE(tmpup); } else rnl->password[0] = '\0'; } rnl->timestamp = (time_t) atol(parse_getarg(&state)); rnl->timereg = (time_t) atol(parse_getarg(&state)); rnl->flags = atoi(parse_getarg(&state)); if (db_version >= 3) { const char *idString = parse_getarg(&state); int av, bv; sscanf(idString, "%X*%X", &av, &bv); rnl->regnum.SetDirect(top_regnick_idnum, av, bv); } else { rnl->regnum.SetNext(top_regnick_idnum); } if (do_enc) rnl->flags |= NENCRYPT; else rnl->flags &= ~NENCRYPT; rnl->opflags = 0; rnl->idtime = DEF_NDELAY; ADD_MEMO_BOX(rnl); addRegNick(rnl); } else if (strcmp(command, "is") == 0) { char *data = parse_getarg(&state); if (rnl && data) rnl->is_readtime = atol(data); } else if (strcmp(command, "oper") == 0) { char *opflags_s; if (rnl && (rnl == getRegNickData(parse_getarg(&state)))) { if ((opflags_s = parse_getarg(&state))) rnl->opflags |= (strtoul(opflags_s, (char **)0, 10) & ~(OROOT | OSERVOP)); if (rnl->opflags) addOpData(rnl); } } else if (strcmp(command, "url") == 0) { if (rnl && (rnl == getRegNickData(parse_getarg(&state)))) { rnl->url = strdup(parse_getarg(&state)); if (strlen(rnl->url) > (URLLEN - 1)) rnl->url[URLLEN - 1] = '\0'; } } else if (strcmp(command, "gecos") == 0) { #ifdef TRACK_GECOS char *gecos = parse_getallargs(&state); if (gecos != NULL) rnl->gecos = strdup(gecos); #endif } else if (strcmp(command, "akey") == 0) { #ifdef REQ_EMAIL if (rnl) rnl->email_key = atoi(parse_getarg(&state)); #endif } else if (strcmp(command, "chkey") == 0) { char *tmpp = parse_getarg(&state); if (rnl && tmpp) rnl->chpw_key = strtoul(tmpp, (char **)0, 16); } else if (strcmp(command, "markby") == 0) { char *mby; rnl = getRegNickData(parse_getarg(&state)); if (!rnl || !(mby = parse_getarg(&state))) continue; rnl->markby = strdup(mby); } else if (strcmp(command, "access") == 0) { rnl = getRegNickData(parse_getarg(&state)); addAccItem(rnl, parse_getarg(&state)); } else if (!strcmp(command, "email")) { rnl = getRegNickData(parse_getarg(&state)); strncpyzt(rnl->email, parse_getarg(&state), EMAILLEN); if (!strcmp(rnl->email, "(none)")) strcat(rnl->email, " "); } else if (!strcmp(command, "idtime")) { rnl = getRegNickData(parse_getarg(&state)); rnl->idtime = atoi(parse_getarg(&state)); } else if (!strcmp(command, "done")) done = 1; else { fprintf(stderr, NS_DB ":%d: Error reading nick data (%s)", line_num, dbLine); sshutdown(-1); } #ifdef DBDEBUG sSend(":%s PRIVMSG " DEBUGCHAN " :Read nick data (%s)", NICKSERV, dbLine); #endif parse_cleanup(&state); } fclose(db.ns); readMemoData(); }
/** * \brief Saves the NickServ database to disk */ void saveNickData(void) { RegNickList *nl; nAccessList *accitem; int x = 0, bucket; db.ns = fopen(NS_DB, "w"); if (db.ns == NULL) { sSend(":%s GOPER :ERROR: Unable to save NickServ database fopen failed: %s", myname, strerror(errno)); logDump(corelog, "Unable to save NickServ database: fopen: %s", strerror(errno)); return; } fprintf(db.ns, "version 3\n"); for (bucket = 0; bucket < NICKHASHSIZE; bucket++) { nl = LIST_FIRST(&RegNickHash[bucket]); while (nl != NULL) { /* New nick insertion point */ fprintf(db.ns, "nick "); if (nl->user[0] == '\0') fprintf(db.ns, "%s . %s ", nl->nick, nl->host); else fprintf(db.ns, "%s %s %s ", nl->nick, nl->user, nl->host); if (!(nl->flags & NENCRYPT)) { strcpy(cryptstr, (char *)nl->password); xorit(cryptstr); fprintf(db.ns, "@%s ", cryptstr); } else { unsigned char *p; // XXX Put note that PASSLEN must be at least 15 p = toBase64(nl->password, 16); fprintf(db.ns, "$%s ", p); FREE(p); } fprintf(db.ns, "%lu ", (unsigned long)nl->timestamp); fprintf(db.ns, "%lu ", (unsigned long)nl->timereg); fprintf(db.ns, "%i %X*%X\n", nl->flags, nl->regnum.a, nl->regnum.b); /* Infoserv data */ fprintf(db.ns, "is %ld\n", nl->is_readtime); #ifdef REQ_EMAIL if (!(nl->flags & NACTIVE) || (nl->flags & NDEACC)) fprintf(db.ns, "akey %lu\n", nl->email_key); #endif if (nl->chpw_key) fprintf(db.ns, "chkey %X\n", nl->chpw_key); if (nl->url != NULL) fprintf(db.ns, "url %s %s\n", nl->nick, nl->url); #ifdef TRACK_GECOS if (nl->gecos != NULL) fprintf(db.ns, "gecos :%s\n", nl->gecos); #endif if (nl->email[0] && strcmp(nl->email, "(none)")) fprintf(db.ns, "email %s %s\n", nl->nick, nl->email); if ((nl->opflags & ~(OROOT | OSERVOP))) fprintf(db.ns, "oper %s %lu 0 0\n", nl->nick, nl->opflags); if ((nl->flags & NMARK) && nl->markby) fprintf(db.ns, "markby %s %s\n", nl->nick, nl->markby); if (nl->idtime != DEF_NDELAY) fprintf(db.ns, "idtime %s %i\n", nl->nick, nl->idtime); for (accitem = LIST_FIRST(&nl->acl); accitem; accitem = LIST_NEXT(accitem, al_lst)) fprintf(db.ns, "access %s %s\n", nl->nick, accitem->mask); x++; fflush(db.ns); #ifdef DBDEBUG sSend(":%s PRIVMSG " DEBUGCHAN " :Saved nick data (%s)", NickServ, nl->nick); #endif nl = LIST_NEXT(nl, rn_lst); } } fprintf(db.ns, "done\n"); fflush(db.ns); fclose(db.ns); #ifdef GLOBOPS_TIMED_MSGS sSend(":%s GLOBOPS :Completed save(%i)", NickServ, x); #else sSend(":%s PRIVMSG " LOGCHAN " :Completed save(%i)", NickServ, x); #endif }
/* * WARNING WARNING WARNING * * This function is very ugly in terms of args handling, and it is * very easy to inadvertently break something if you make small tweaks * to it. * * args and numargs do NOT always map together in this function, * for example numargs = 3, means that args really has 3+3=6 elements * in some points: numargs should be numargs2. * * Basically, the bottom two elements of args[] are dropped * in this function when * it goes to args2 to call the particular handlers -Mysid */ void parseLine(char *line) { int i = 0, a = 0, x = 0, prefixed = 0; char *args2[MAX_IRC_LINE_LEN + 5]; char *args[MAX_IRC_LINE_LEN + 5]; char realargs[151][151]; u_int16_t numargs = 0; /* * Seems Ok to me ^^^ * sizes may be off(?) */ /* Yes, your sizes were off.. -Mysid */ strncpyzt(coreBuffer, line, MAX_IRC_LINE_LEN); #ifdef DEBUG printf("Read: %s\n", coreBuffer); #endif CTime = time(NULL); while (*line && x < 150) { while (*line != ' ' && *line && a < 150) { realargs[x][a] = *line; a++; line++; } realargs[x][a] = 0; args[x] = realargs[x]; x++; numargs++; while (*line == ' ') line++; a = 0; } /* ensure the next item is null so we can check it later */ realargs[x][0] = 0; args[x] = realargs[x]; if (args[0][0] == ':') { prefixed = 1; /** \bug old lame bugfix, what would be better is to use a 'from' value and args++'ing it, if there's no prefix then have from set to the uplink -Mysid */ args[0]++; } else prefixed = 0; if (!strcmp(args[0], "PING") && !prefixed) { sSend("PONG :%s", myname); return; } else if (!strcmp(args[0], "ERROR") && !strcmp(args[1], ":Closing")) sshutdown(0); else if (!strcmp(args[0], "NICK") && !prefixed) { if (strchr(args[4], '*') || strchr(args[4], '?') || strchr(args[4], '!') || strchr(args[4], '@')) { char nick[NICKLEN]; strncpyzt(nick, args[1], NICKLEN); sSend (":%s KILL %s :%s!%s (Your ident reply contains either a *, !, @, or ?. Please remove this before returning.)", services[1].name, nick, services[1].host, services[1].name); addGhost(nick); timer(15, delTimedGhost, strdup(nick)); return; } addNewUser(args, numargs); /* nickserv.c, add new user. */ return; } if (!strcmp(args[1], "PRIVMSG")) { UserList *tmp = getNickData(args[0]); if (strchr(args[2], '#') || strchr(args[2], '$')) return; if (!strcasecmp(args[0], NickServ) || !strcasecmp(args[0], GameServ) || !strcasecmp(args[0], OperServ) || !strcasecmp(args[0], ChanServ) || !strcasecmp(args[0], MemoServ) || !strcasecmp(args[0], InfoServ)) return; if (tmp && tmp->reg && tmp->reg->flags & NBANISH) { sSend(":%s NOTICE %s :This nickname is banished." " You cannot use services until you change" " nicknames.", NickServ, args[0]); return; } if (!tmp) { nDesynch(args[0], "PRIVMSG"); return; } if (addFlood(tmp, 1)) return; if (getBanInfo(tmp->nick, tmp->user, tmp->host, A_IGNORE) != NULL) { if (tmp->floodlevel.GetLev() < 2) sSend (":%s NOTICE %s :You are on services ignore, you may not use any Service", NickServ, tmp->nick); if (!isOper(tmp) || tmp->caccess < ACC_RECOGNIZED || !tmp->reg || !(tmp->reg->opflags & OROOT)) return; } args[3]++; while (*args[3] == ' ') args[3]++; for (i = 3; i < numargs; i++) args2[i - 3] = args[i]; numargs -= 3; /* Handle pings before even going to the services */ if (!strcasecmp(args2[0], "\001PING")) { if (addFlood(tmp, 3)) return; if (numargs < 3) sSend(":%s NOTICE %s :\001PING %s", args[2], args[0], args2[1]); else sSend(":%s NOTICE %s :\001PING %s %s", args[2], args[0], args2[1], args2[2]); return; } /* NOTE: numargs maps to args2 not args at this point */ if (!strncasecmp(args[2], OperServ, strlen(OperServ))) sendToOperServ(tmp, args2, numargs); else if (!strncasecmp(args[2], NickServ, strlen(NickServ))) sendToNickServ(tmp, args2, numargs); else if (!strncasecmp(args[2], ChanServ, strlen(ChanServ))) sendToChanServ(tmp, args2, numargs); else if (!strncasecmp(args[2], MemoServ, strlen(MemoServ))) sendToMemoServ(tmp, args2, numargs); else if (!strncasecmp(args[2], InfoServ, strlen(InfoServ))) sendToInfoServ(tmp, args2, numargs); else if (!strncasecmp(args[2], GameServ, strlen(GameServ))) sendToGameServ(tmp, args2, numargs); else if (isGhost(args[2])) { sSend (":%s NOTICE %s :This is a NickServ registered nick enforcer, and not a real user.", args[2], args[0]); } /* Note, the below should be correct. */ else if ((numargs >= 1) && adCheck(tmp, args[2], args2, numargs)) return; return; } else if (!strcmp(args[1], "QUIT")) { remUser(args[0], 0); return; } else if (!strcmp(args[1], "NICK")) { UserList *tmp = getNickData(args[0]); if (addFlood(tmp, 5)) return; changeNick(args[0], args[2], args[3]); return; } else if (!strcmp(args[1], "MODE") && !strcmp(args[0], args[2])) { setMode(args[0], args[3]); return; } else if (!strcmp(args[1], "MODE")) { setChanMode(args, numargs); return; } else if (!strcmp(args[1], "TOPIC")) { setChanTopic(args, numargs); return; } else if (!strcmp(args[1], "AWAY")) { if (numargs < 3) { setFlags(args[0], NISAWAY, '-'); checkMemos(getNickData(args[0])); } else setFlags(args[0], NISAWAY, '+'); return; } else if (!strcmp(args[1], "JOIN")) { addUserToChan(getNickData(args[0]), args[2]); return; } else if (!strcmp(args[1], "PART")) { remUserFromChan(getNickData(args[0]), args[2]); return; } else if (!strcmp(args[1], "KICK")) { remUserFromChan(getNickData(args[3]), args[2]); return; } else if (!strcmp(args[1], "KILL")) { int i; for (i = 0; i < NUMSERVS; i++) { if (!strcasecmp(args[2], services[i].name)) { addUser(services[i].name, services[i].uname, services[i].host, services[i].rname, services[i].mode); sSend(":%s KILL %s :%s!%s (services kill protection)", services[i].name, args[0], services[i].host, services[i].name); sSend(":%s GLOBOPS :%s just killed me!", services[i].name, args[0]); remUser(args[0], 0); return; } } if (isGhost(args[2])) { delGhost(args[2]); return; } else remUser(args[2], 1); return; } else if (!strcmp(args[1], "MOTD")) { UserList *tmp = getNickData(args[0]); if (addFlood(tmp, 1)) return; motd(args[0]); return; } else if (!strcmp(args[1], "INFO")) { UserList *tmp = getNickData(args[0]); if (!tmp || addFlood(tmp, 3)) return; sendInfoReply(tmp); return; } else if (!strcmp(args[1], "VERSION")) { UserList *tmp = getNickData(args[0]); if (addFlood(tmp, 1)) return; sSend(":%s 351 %s %s %s :%s", myname, args[0], VERSION_STRING, myname, VERSION_QUOTE); return; } else if ((!strcmp(args[1], "GNOTICE") || !strcmp(args[1], "GLOBOPS")) && !strcmp(args[2], ":Link") && !strcmp(args[3], "with") && !strncmp(args[4], myname, strlen(myname))) { sSend(":%s GNOTICE :Link with %s[services@%s] established.", myname, args[0], hostname); strncpyzt(hostname, args[0], sizeof(hostname)); expireNicks(NULL); expireChans(NULL); sync_cfg("1"); checkTusers(NULL); flushLogs(NULL); nextNsync = (SYNCTIME + CTime); nextCsync = ((SYNCTIME * 2) + CTime); nextMsync = ((SYNCTIME * 3) + CTime); loadakills(); return; } #ifdef IRCD_HURTSET else if (!strcmp(args[1], "HURTSET") && (numargs >= 4)) { UserList *hurtwho; if ((hurtwho = getNickData(args[2]))) { if (args[3] && *args[3] == '-') hurtwho->oflags &= ~(NISAHURT); else if (args[3] && atoi(args[3]) == 4) { hurtwho->oflags |= (NISAHURT); } else if (args[3] && isdigit(*args[3]) && (getBanInfo(hurtwho->nick, hurtwho->user, hurtwho->host, A_AHURT) != NULL)) hurtwho->oflags |= (NISAHURT); } } #endif else if (!strcmp(args[1], "SQUIT")) { time_t jupe; jupe = time(NULL); if (strchr(args[2], '.')) return; sSend(":%s WALLOPS :%s Un-jupitered by %s at %s", myname, args[2], args[0], ctime(&(jupe))); return; } else if (!strcmp(args[1], "STATS") && numargs > 3) { const char* from = args[0]; if (args[2] && !strcasecmp(args[2], "OPTS")) { sSend(":%s NOTICE %s :Network name: %s", InfoServ, from, NETWORK); #ifdef AKILLMAILTO sSend(":%s NOTICE %s :Akill log address: %s", InfoServ, from, AKILLMAILTO); #endif #ifdef ENABLE_GRPOPS sSend(":%s NOTICE %s :GRPops enabled.", InfoServ, from); #endif #ifdef MD5_AUTH sSend(":%s NOTICE %s :MD5 authentication available.", InfoServ, from); #endif } else if (args[2] && !strcasecmp(args[2], "V$")) { sSend(":%s NOTICE %s :Based on sn services1.4.", InfoServ, from); } } /* "No N-line" error */ else if (!strcmp(args[0], "ERROR") && !strcmp(args[1], ":No")) { fprintf(stderr, "Error connecting to server: No N-line\n"); sshutdown(2); } }
/** * Break up a string of data into seperate pieces and parse those. * (parseLine()) * \bug "I'm not sure but this function could be done better(?) if someone * wants to improve it..." */ void breakLine(char *tmpbuffer) { int usedbuf, terminated; char sendBuffer[MAX_IRC_LINE_LEN + 1]; memset(sendBuffer, 0, MAX_IRC_LINE_LEN + 1); usedbuf = 0; /* Just in case the impossible happens, and our old data is >= 512 chars, * which means we won't be able to add anything from the data stream, and * therefore can't get the terminating \r\n */ if (strlen(oldData) >= MAX_IRC_LINE_LEN) { sSend(":%s GLOBOPS :Infinate loop encounted in breakLine(). " "Mail this line to [email protected]", OperServ); sSend(":%s GLOBOPS :Services terminating", OperServ); sshutdown(1); } /* If we have some leftover unterminated data from the stream... */ if (oldData[0] != '\0') { strncpyzt(sendBuffer, oldData, MAX_IRC_LINE_LEN); bzero(oldData, MAX_IRC_LINE_LEN); usedbuf = strlen(sendBuffer); } while (*tmpbuffer) { terminated = FALSE; /* While each of the following are true: * @ We've not found a terminator * @ We're not at the end of the buffer * @ We're not at the end of the buffer we can copy to */ while (*tmpbuffer != '\n' && *tmpbuffer != '\r' && *tmpbuffer != '\0' && usedbuf < MAX_IRC_LINE_LEN) { sendBuffer[usedbuf] = *tmpbuffer; usedbuf++; tmpbuffer++; } sendBuffer[usedbuf] = 0; usedbuf = 0; /* Clear trailing terminator */ while (*tmpbuffer == '\r' || *tmpbuffer == '\n') { tmpbuffer++; terminated = TRUE; } if (terminated == FALSE) { /* If we didn't find the terminators */ /* * Copy our current unfinished line to a tmp buffer, we'll look * at it again in the next call to breakLine(), when we recieve * more data. Had to be done due to recv() taking unteminated * data. */ strncpyzt(oldData, sendBuffer, MAX_IRC_LINE_LEN); } else { /* If we've got all our data, and it's terminated, we can parse it */ parseLine(sendBuffer); } } }