/** * Automaticaly re-set the DefCon level if the time limit has expired. **/ void resetDefCon(int level) { char strLevel[5]; snprintf(strLevel, 4, "%d", level); if (DefConLevel != level) { if ((DefContimer) && (time(NULL) - DefContimer >= dotime(DefConTimeOut))) { DefConLevel = level; send_event(EVENT_DEFCON_LEVEL, 1, strLevel); alog("Defcon level timeout, returning to lvl %d", level); xanadu_cmd_global(s_OperServ, getstring2(NULL, OPER_DEFCON_WALL), s_OperServ, level); if (GlobalOnDefcon) { if (DefConOffMessage) { oper_global(NULL, "%s", DefConOffMessage); } else { oper_global(NULL, getstring(NULL, DEFCON_GLOBAL), DefConLevel); } } if (GlobalOnDefconMore && !DefConOffMessage) { oper_global(NULL, "%s", DefconMessage); } runDefCon(); } } }
/* c_irq_handler - custom irq handler called by assembly irq handler after state has been saved/restored appropriately. Parameters: None */ void c_irq_handler(){ unsigned stamp; mmio_t oscr = (mmio_t)OSCR; mmio_t ossr = (mmio_t)OSSR; mmio_t osmr0 = (mmio_t)OSMR_0; if(*ossr & OSSR_M0){ //keep global time by checking if oscr has overlapped start_time if(lastoscr<start_time && *oscr>=start_time){ rollovercount++; } lastoscr = *oscr; dotime(&stamp); //set next interrupt for 10ms later *osmr0 = *oscr + OSTMR_FREQ/100; //unset interrupts *ossr |= OSSR_M0; //update devices and switch to highest prio task dev_update((unsigned long)stamp); dispatch_save(); } if(*ossr & OSSR_M1) *ossr |= OSSR_M1; if(*ossr & OSSR_M2) *ossr |= OSSR_M2; if(*ossr & OSSR_M3) *ossr |= OSSR_M3; }
int main(object me) { float value; mapping r; if (time() - me->query_temp("scan_time") < 10 && ! wizardp(me)) return notify_fail("等等,系统喘气中……\n"); r = rusage(); value = SCALE * (r["utime"] + r["stime"]) / uptime(); write(NOR + WHT "\n\t\t .__________ 系 统 资 讯 __________.\n"); write(NOR + WHT "\t\t ─────────────────────────\n"); write(NOR + WHT "\t\t 游戏的识别名称: " + MUD_NAME + "\n"); write(NOR + WHT "\t\t 界面系统的版本: " + __VERSION__ + "\n"); write(NOR + WHT "\t\t 系统函数库版本: Nitan Mudlib Version 2.1\n"); printf(NOR + WHT "\t\t CPU 使用百分比: %f %% 被这个游戏使用中\n", value ); write(NOR + WHT "\t\t CPU 的负担状况: " + query_load_average() + "\n"); printf(NOR + WHT "\t\t 共使用的记忆体: %s bytes\n", memory_expression(memory_info()) ); write(NOR + WHT "\t\t 线上使用者总数: " + sizeof( users() ) + " 个人在线上\n"); write(NOR + WHT "\t\t 注册使用者总数: " + count_ppls() + " 个人在本游戏注册\n"); write(NOR + WHT "\t\t 载入的物件总数: " + sizeof( objects() ) + " 个物件\n"); write(NOR + WHT "\t\t 心跳总数的资讯: " + sizeof(heart_beats()) + " 个\n"); write(NOR + WHT "\t\t 延迟呼叫数资讯: " + sizeof(call_out_info()) + " 个\n"); write(NOR + WHT "\t\t 系统负载的资讯: " + query_load_average() + "\n"); write(NOR + WHT "\t\t 讯息传输的资讯: " + query_rusage_message() + "\n"); write(NOR + WHT "\t\t 连续执行的时间: " + dotime() + "\n"); write(NOR + WHT "\t\t 游戏现在的状态: " + STATUS + "\n" NOR); write(NOR + WHT "\t\t 游戏对 PK 限制: 每天不超过 8 人,每人不超过 2 次\n\n" NOR); me->set_temp("scan_time", time()); return 1; }
int do_ignoreuser(User * u, Channel *c, char *cmd, char *nick, char *time) { ChannelInfo *ci = c->ci; int t; if (!cmd) { notice_lang(ci->bi->nick, u, OPER_IGNORE_SYNTAX); return MOD_CONT; } if (!stricmp(cmd, "ADD")) { if (!nick) { notice_lang(ci->bi->nick, u, OPER_IGNORE_SYNTAX); return MOD_CONT; } else if (!time) { notice_lang(ci->bi->nick, u, OPER_IGNORE_SYNTAX); return MOD_CONT; } else { t = dotime(time); if (t <= -1) { notice_lang(ci->bi->nick, u, OPER_IGNORE_VALID_TIME); return MOD_CONT; } else if (t == 0) { t = 157248000; /* if 0 is given, we set time to 157248000 seconds == 5 years (let's hope the next restart will be before that time ;-)) */ add_ignore(nick, t); notice_lang(ci->bi->nick, u, OPER_IGNORE_PERM_DONE, nick); alog("[bs_fantasy_ext] %s added %s permanently to the ignore list.", u->nick, nick); } else { add_ignore(nick, t); notice_lang(ci->bi->nick, u, OPER_IGNORE_TIME_DONE, nick, time); alog("[bs_fantasy_ext] %s added %s to the ignore list for %d seconds.", u->nick, nick, t); } } } else if (!stricmp(cmd, "LIST")) { do_ignorelist(u, ci); alog("[bs_fantasy_ext] %s requested the ignore list.", u->nick); } else if (!stricmp(cmd, "DEL")) { if (!nick) { notice_lang(ci->bi->nick, u, OPER_IGNORE_SYNTAX); } else { if (delete_ignore(nick)) { notice_lang(ci->bi->nick, u, OPER_IGNORE_DEL_DONE, nick); alog("[bs_fantasy_ext] %s deleted %s from the ignore list.", u->nick, nick); return MOD_CONT; } else notice_lang(ci->bi->nick, u, OPER_IGNORE_LIST_NOMATCH, nick); } } else if (!stricmp(cmd, "CLEAR")) { clear_ignores(); notice_lang(ci->bi->nick, u, OPER_IGNORE_LIST_CLEARED); alog("[bs_fantasy_ext] %s cleared the ignore list.", u->nick); return MOD_CONT; } else notice_lang(ci->bi->nick, u, OPER_IGNORE_SYNTAX); return MOD_CONT; }
/* dosleep implements the sleep system call. Busy wait solution that waits for system time to be equal to start time plus the number of miliseconds passed as a parameter. Parameters: args - args[0] is the number of miliseconds to sleep. Returns: nothing Note: This implementation of sleep handles the edge case when (current_time+sleep_time) overflows a 32 bit value. */ void dosleep(unsigned* args){ //wait for time to elapse unsigned start = 0; unsigned now = 0; if(args[0]){ dotime(&start); now = start; if(start+args[0] > start){ while(now < (start + args[0])) dotime(&now); } else { while((now/10) > 0) //make sure loop exits in case 0 isn't sampled dotime(&now); while(now < (start + args[0])) dotime(&now); } } }
static int do_tban(User * u) { char mask[BUFSIZE]; Channel *c; User *u2 = NULL; char *buffer = moduleGetLastBuffer(); char *chan; char *nick; char *time; chan = myStrGetToken(buffer, ' ', 0); nick = myStrGetToken(buffer, ' ', 1); time = myStrGetToken(buffer, ' ', 2); if (time && chan && nick) { if (!(c = findchan(chan))) { notice_lang(s_ChanServ, u, CHAN_X_NOT_IN_USE, chan); } else if (!(u2 = finduser(nick))) { notice_lang(s_ChanServ, u, NICK_X_NOT_IN_USE, nick); } else { if (canBanUser(c, u, u2)) { get_idealban(c->ci, u2, mask, sizeof(mask)); addBan(c, dotime(time), mask); mySendResponse(u, chan, mask, time); } } } else { myFullHelpSyntax(u); } if (time) free(time); if (nick) free(nick); if (chan) free(chan); return MOD_CONT; }
int AnopeInit(int argc, char **argv) /* This will be executed when the module is loaded */ { Command *c; /* Pointer to a Command */ int status = 0; /* the status of our new command */ c = createCommand("moo", hs_moo_show, NULL, -1, -1, -1, -1, -1); /* Create a new command "moo" pointing to hs_moo */ moduleAddHelp(c,myHostServMooHelp); /* add help for all users to this command */ moduleAddRegHelp(c,myHostServMooRegHelp); /* add extra regular-user only help to this command */ moduleAddOperHelp(c,myHostServMooOperHelp); /* add extra oper only help to this command */ moduleAddAdminHelp(c,myHostServMooAdminHelp); /* add extra admin only help to this command */ moduleAddRootHelp(c,myHostServMooRootHelp); /* add extra root only help to this command */ moduleSetHostHelp(myHostServHelp); /* add us to the .hs help list */ status = moduleAddCommand(HOSTSERV, c, MOD_HEAD); /* Add the command to the HOSTSERV cmd table */ /* Check if we have any argv's */ if(argc>0) { /* we do, the first will be the nick of the person modload'ing us */ /* or NULL if we were auto-loaded */ if(argv[0]) { alog("hs_moo was modloaded by: [%s]",argv[0]); } else { alog("hs_moo was automatically loaded by anope"); } } alog("hs_moo.so: Add Command 'moo' Status: %d",status); /* Log the command being added */ moduleAddCallback("test",time(NULL)+dotime("15s"),test,0,NULL); /* set a call-back function to exec in 3 mins time */ moduleDelCallback("test"); moduleAddAuthor(AUTHOR); /* tell Anope about the author */ moduleAddVersion(VERSION); /* Tell Anope about the verison */ if(status!=MOD_ERR_OK) { return MOD_STOP; } return MOD_CONT; }
/* * Main program */ int main(int argc, char **argv) { CONF_SECTION *maincs, *cs; FILE *fp; struct radutmp rt; char othername[256]; char nasname[1024]; char session_id[sizeof(rt.session_id)+1]; int hideshell = 0; int showsid = 0; int rawoutput = 0; int radiusoutput = 0; /* Radius attributes */ char const *portind; int c; unsigned int portno; char buffer[2048]; char const *user = NULL; int user_cmp = 0; time_t now = 0; uint32_t nas_port = ~0; uint32_t nas_ip_address = INADDR_NONE; int zap = 0; raddb_dir = RADIUS_DIR; #ifndef NDEBUG if (fr_fault_setup(getenv("PANIC_ACTION"), argv[0]) < 0) { fr_perror("radwho"); exit(EXIT_FAILURE); } #endif talloc_set_log_stderr(); while((c = getopt(argc, argv, "d:fF:nN:sSipP:crRu:U:Z")) != EOF) switch(c) { case 'd': raddb_dir = optarg; break; case 'F': radutmp_file = optarg; break; case 'h': usage(0); break; case 'S': hideshell = 1; break; case 'n': showname = 0; break; case 'N': if (inet_pton(AF_INET, optarg, &nas_ip_address) < 0) { usage(1); } break; case 's': showname = 1; break; case 'i': showsid = 1; break; case 'p': showptype = 1; break; case 'P': nas_port = atoi(optarg); break; case 'c': showcid = 1; showname = 1; break; case 'r': rawoutput = 1; break; case 'R': radiusoutput = 1; now = time(NULL); break; case 'u': user = optarg; user_cmp = 0; break; case 'U': user = optarg; user_cmp = 1; break; case 'Z': zap = 1; break; default: usage(1); break; } /* * Mismatch between the binary and the libraries it depends on */ if (fr_check_lib_magic(RADIUSD_MAGIC_NUMBER) < 0) { fr_perror("radwho"); return 1; } /* * Be safe. */ if (zap && !radiusoutput) zap = 0; /* * zap EVERYONE, but only on this nas */ if (zap && !user && (~nas_port == 0)) { /* * We need to know which NAS to zap users in. */ if (nas_ip_address == INADDR_NONE) usage(1); printf("Acct-Status-Type = Accounting-Off\n"); printf("NAS-IP-Address = %s\n", hostname(buffer, sizeof(buffer), nas_ip_address)); printf("Acct-Delay-Time = 0\n"); exit(0); /* don't bother printing anything else */ } if (radutmp_file) goto have_radutmp; /* * Initialize main_config */ memset(&main_config, 0, sizeof(main_config)); /* Read radiusd.conf */ snprintf(buffer, sizeof(buffer), "%.200s/radiusd.conf", raddb_dir); maincs = cf_file_read(buffer); if (!maincs) { fprintf(stderr, "%s: Error reading or parsing radiusd.conf\n", argv[0]); exit(1); } cs = cf_section_sub_find(maincs, "modules"); if (!cs) { fprintf(stderr, "%s: No modules section found in radiusd.conf\n", argv[0]); exit(1); } /* Read the radutmp section of radiusd.conf */ cs = cf_section_sub_find_name2(cs, "radutmp", NULL); if (!cs) { fprintf(stderr, "%s: No configuration information in radutmp section of radiusd.conf\n", argv[0]); exit(1); } cf_section_parse(cs, NULL, module_config); /* Assign the correct path for the radutmp file */ radutmp_file = radutmpconfig.radutmp_fn; have_radutmp: if (showname < 0) showname = 1; /* * Show the users logged in on the terminal server(s). */ if ((fp = fopen(radutmp_file, "r")) == NULL) { fprintf(stderr, "%s: Error reading %s: %s\n", progname, radutmp_file, fr_syserror(errno)); return 0; } /* * Don't print the headers if raw or RADIUS */ if (!rawoutput && !radiusoutput) { fputs(showname ? hdr1 : hdr2, stdout); fputs(eol, stdout); } /* * Read the file, printing out active entries. */ while (fread(&rt, sizeof(rt), 1, fp) == 1) { char name[sizeof(rt.login) + 1]; if (rt.type != P_LOGIN) continue; /* hide logout sessions */ /* * We don't show shell users if we are * fingerd, as we have done that above. */ if (hideshell && !strchr("PCS", rt.proto)) continue; /* * Print out sessions only for the given user. */ if (user) { /* only for a particular user */ if (((user_cmp == 0) && (strncasecmp(rt.login, user, strlen(user)) != 0)) || ((user_cmp == 1) && (strncmp(rt.login, user, strlen(user)) != 0))) { continue; } } /* * Print out only for the given NAS port. */ if (~nas_port != 0) { if (rt.nas_port != nas_port) continue; } /* * Print out only for the given NAS IP address */ if (nas_ip_address != INADDR_NONE) { if (rt.nas_address != nas_ip_address) continue; } memcpy(session_id, rt.session_id, sizeof(rt.session_id)); session_id[sizeof(rt.session_id)] = 0; if (!rawoutput && rt.nas_port > (showname ? 999 : 99999)) { portind = ">"; portno = (showname ? 999 : 99999); } else { portind = "S"; portno = rt.nas_port; } /* * Print output as RADIUS attributes */ if (radiusoutput) { memcpy(nasname, rt.login, sizeof(rt.login)); nasname[sizeof(rt.login)] = '\0'; fr_print_string(nasname, 0, buffer, sizeof(buffer)); printf("User-Name = \"%s\"\n", buffer); fr_print_string(session_id, 0, buffer, sizeof(buffer)); printf("Acct-Session-Id = \"%s\"\n", buffer); if (zap) printf("Acct-Status-Type = Stop\n"); printf("NAS-IP-Address = %s\n", hostname(buffer, sizeof(buffer), rt.nas_address)); printf("NAS-Port = %u\n", rt.nas_port); switch (rt.proto) { case 'S': printf("Service-Type = Framed-User\n"); printf("Framed-Protocol = SLIP\n"); break; case 'P': printf("Service-Type = Framed-User\n"); printf("Framed-Protocol = PPP\n"); break; default: printf("Service-type = Login-User\n"); break; } if (rt.framed_address != INADDR_NONE) { printf("Framed-IP-Address = %s\n", hostname(buffer, sizeof(buffer), rt.framed_address)); } /* * Some sanity checks on the time */ if ((rt.time <= now) && (now - rt.time) <= (86400 * 365)) { printf("Acct-Session-Time = %" PRId64 "\n", (int64_t) (now - rt.time)); } if (rt.caller_id[0] != '\0') { memcpy(nasname, rt.caller_id, sizeof(rt.caller_id)); nasname[sizeof(rt.caller_id)] = '\0'; fr_print_string(nasname, 0, buffer, sizeof(buffer)); printf("Calling-Station-Id = \"%s\"\n", buffer); } printf("\n"); /* separate entries with a blank line */ continue; } /* * Show the fill name, or not. */ memcpy(name, rt.login, sizeof(rt.login)); name[sizeof(rt.login)] = '\0'; if (showname) { if (rawoutput == 0) { printf("%-10.10s %-17.17s %-5.5s %s%-3u %-9.9s %-15.15s %-.19s%s", name, showcid ? rt.caller_id : (showsid? session_id : fullname(rt.login)), proto(rt.proto, rt.porttype), portind, portno, dotime(rt.time), hostname(nasname, sizeof(nasname), rt.nas_address), hostname(othername, sizeof(othername), rt.framed_address), eol); } else { printf("%s,%s,%s,%s%u,%s,%s,%s%s", name, showcid ? rt.caller_id : (showsid? session_id : fullname(rt.login)), proto(rt.proto, rt.porttype), portind, portno, dotime(rt.time), hostname(nasname, sizeof(nasname), rt.nas_address), hostname(othername, sizeof(othername), rt.framed_address), eol); } } else { if (rawoutput == 0) { printf("%-10.10s %s%-5u %-6.6s %-13.13s %-15.15s %-.28s%s", name, portind, portno, proto(rt.proto, rt.porttype), dotime(rt.time), hostname(nasname, sizeof(nasname), rt.nas_address), hostname(othername, sizeof(othername), rt.framed_address), eol); } else { printf("%s,%s%u,%s,%s,%s,%s%s", name, portind, portno, proto(rt.proto, rt.porttype), dotime(rt.time), hostname(nasname, sizeof(nasname), rt.nas_address), hostname(othername, sizeof(othername), rt.framed_address), eol); } } } fclose(fp); return 0; }
/** * Adds a new user to anopes internal userlist. * * If the SVID passed is 2, the user will not be marked registered or requested to ID. * This is an addition to accomodate IRCds where we cannot determine this based on the NICK * or UID command. Some IRCd's keep +r on when changing nicks and do not use SVID (ex. InspIRCd 1.2). * Instead we get a METADATA command containing the accountname the user was last identified to. * Since this is received after the user is introduced to us we should not yet mark the user * as identified or ask him to identify. We will mark him as recognized for the time being and let * him keep his +r if he has it. * It is the responsibility of the protocol module to make sure that this is either invalidated, * or changed to identified. ~ Viper **/ User *do_nick(const char *source, char *nick, char *username, char *host, char *server, char *realname, time_t ts, uint32 svid, uint32 ip, char *vhost, char *uid) { User *user = NULL; char *tmp = NULL; NickAlias *old_na; /* Old nick rec */ int nc_changed = 1; /* Did nick core change? */ int status = 0; /* Status to apply */ char mask[USERMAX + HOSTMAX + 2]; char *logrealname; char *oldnick; if (!*source) { char ipbuf[16]; struct in_addr addr; if (ircd->nickvhost) { if (vhost) { if (!strcmp(vhost, "*")) { vhost = NULL; if (debug) alog("debug: new user�with no vhost in NICK command: %s", nick); } } } /* This is a new user; create a User structure for it. */ if (debug) alog("debug: new user: %s", nick); if (ircd->nickip) { addr.s_addr = htonl(ip); ntoa(addr, ipbuf, sizeof(ipbuf)); } if (LogUsers) { /** * Ugly swap routine for Flop's bug :) **/ if (realname) { tmp = strchr(realname, '%'); while (tmp) { *tmp = '-'; tmp = strchr(realname, '%'); } } logrealname = normalizeBuffer(realname); /** * End of ugly swap **/ if (ircd->nickvhost) { if (ircd->nickip) { alog("LOGUSERS: %s (%s@%s => %s) (%s) [%s] connected to the network (%s).", nick, username, host, (vhost ? vhost : "none"), logrealname, ipbuf, server); } else { alog("LOGUSERS: %s (%s@%s => %s) (%s) connected to the network (%s).", nick, username, host, (vhost ? vhost : "none"), logrealname, server); } } else { if (ircd->nickip) { alog("LOGUSERS: %s (%s@%s) (%s) [%s] connected to the network (%s).", nick, username, host, logrealname, ipbuf, server); } else { alog("LOGUSERS: %s (%s@%s) (%s) connected to the network (%s).", nick, username, host, logrealname, server); } } Anope_Free(logrealname); } /* We used to ignore the ~ which a lot of ircd's use to indicate no * identd response. That caused channel bans to break, so now we * just take what the server gives us. People are still encouraged * to read the RFCs and stop doing anything to usernames depending * on the result of an identd lookup. */ /* First check for AKILLs. */ /* DONT just return null if its an akill match anymore - yes its more efficent to, however, now that ircd's are * starting to use things like E/F lines, we cant be 100% sure the client will be removed from the network :/ * as such, create a user_struct, and if the client is removed, we'll delete it again when the QUIT notice * comes in from the ircd. **/ if (check_akill(nick, username, host, vhost, ipbuf)) { /* return NULL; */ } /** * DefCon AKILL system, if we want to akill all connecting user's here's where to do it * then force check_akill again on them... **/ /* don't akill on netmerges -Certus */ /* don't akill clients introduced by ulines. -Viper */ if (is_sync(findserver(servlist, server)) && checkDefCon(DEFCON_AKILL_NEW_CLIENTS) && !is_ulined(server)) { strncpy(mask, "*@", 3); strncat(mask, host, HOSTMAX); alog("DEFCON: adding akill for %s", mask); add_akill(NULL, mask, s_OperServ, time(NULL) + dotime(DefConAKILL), DefConAkillReason ? DefConAkillReason : "DEFCON AKILL"); if (check_akill(nick, username, host, vhost, ipbuf)) { /* return NULL; */ } } /* SGLINE */ if (ircd->sgline) { if (check_sgline(nick, realname)) return NULL; } /* SQLINE */ if (ircd->sqline) { if (check_sqline(nick, 0)) return NULL; } /* SZLINE */ if (ircd->szline && ircd->nickip) { if (check_szline(nick, ipbuf)) return NULL; } /* Now check for session limits */ if (LimitSessions && !is_ulined(server) && !add_session(nick, host, ipbuf)) return NULL; /* Allocate User structure and fill it in. */ user = new_user(nick); user->username = sstrdup(username); user->host = sstrdup(host); user->server = findserver(servlist, server); user->realname = sstrdup(realname); user->timestamp = ts; user->my_signon = time(NULL); user->chost = vhost ? sstrdup(vhost) : sstrdup(host); user->vhost = vhost ? sstrdup(vhost) : sstrdup(host); if (uid) { user->uid = sstrdup(uid); /* p10/ts6 stuff */ } else { user->uid = NULL; } user->vident = sstrdup(username); /* We now store the user's ip in the user_ struct, * because we will use it in serveral places -- DrStein */ if (ircd->nickip) { user->hostip = sstrdup(ipbuf); } else { user->hostip = NULL; } if (svid == 0) { display_news(user, NEWS_LOGON); display_news(user, NEWS_RANDOM); } if (svid == 2 && user->na) { /* We do not yet know if the user should be identified or not. * mark him as recognized for now. * It s up to the protocol module to make sure this either becomes ID'd or * is invalidated. ~ Viper */ if (debug) alog("debug: Marking %s as recognized..", user->nick); user->svid = 1; user->na->status |= NS_RECOGNIZED; nc_changed = 0; } else if (svid == ts && user->na) { /* Timestamp and svid match, and nick is registered; automagically identify the nick */ user->svid = svid; user->na->status |= NS_IDENTIFIED; check_memos(user); nc_changed = 0; /* Start nick tracking if available */ if (NSNickTracking) nsStartNickTracking(user); } else if (svid != 1) { /* Resets the svid because it doesn't match */ user->svid = 1; anope_cmd_svid_umode(user->nick, user->timestamp); } else { user->svid = 1; } send_event(EVENT_NEWNICK, 1, nick); } else { /* An old user changing nicks. */ if (UseTS6 && ircd->ts6) user = find_byuid(source); if (!user) user = finduser(source); if (!user) { alog("user: NICK from nonexistent nick %s", source); return NULL; } user->isSuperAdmin = 0; /* Dont let people nick change and stay SuperAdmins */ if (debug) alog("debug: %s changes nick to %s", source, nick); if (LogUsers) { logrealname = normalizeBuffer(user->realname); if (ircd->vhost) { alog("LOGUSERS: %s (%s@%s => %s) (%s) changed nick to %s (%s).", user->nick, user->username, user->host, (user->vhost ? user->vhost : "(none)"), logrealname, nick, user->server->name); } else { alog("LOGUSERS: %s (%s@%s) (%s) changed nick to %s (%s).", user->nick, user->username, user->host, logrealname, nick, user->server->name); } if (logrealname) { free(logrealname); } } user->timestamp = ts; if (stricmp(nick, user->nick) == 0) { /* No need to redo things */ change_user_nick(user, nick); nc_changed = 0; } else { /* Update this only if nicks aren't the same */ user->my_signon = time(NULL); old_na = user->na; if (old_na) { if (nick_recognized(user)) user->na->last_seen = time(NULL); status = old_na->status & NS_TRANSGROUP; cancel_user(user); } oldnick = sstrdup(user->nick); change_user_nick(user, nick); if ((old_na ? old_na->nc : NULL) == (user->na ? user->na->nc : NULL)) nc_changed = 0; if (!nc_changed && (user->na)) user->na->status |= status; else { anope_cmd_nc_change(user); } send_event(EVENT_CHANGE_NICK, 2, nick, oldnick); free(oldnick); } if (ircd->sqline) { if (!is_oper(user) && check_sqline(user->nick, 1)) return NULL; } } /* if (!*source) */ /* Check for nick tracking to bypass identification */ if (NSNickTracking && nsCheckNickTracking(user)) { user->na->status |= NS_IDENTIFIED; nc_changed = 0; } if (nc_changed || !nick_recognized(user)) { if (validate_user(user)) check_memos(user); } else { if (nick_identified(user)) { char tsbuf[16]; user->na->last_seen = time(NULL); if (user->na->last_usermask) free(user->na->last_usermask); user->na->last_usermask = smalloc(strlen(common_get_vident(user)) + strlen(common_get_vhost(user)) + 2); sprintf(user->na->last_usermask, "%s@%s", common_get_vident(user), common_get_vhost(user)); snprintf(tsbuf, sizeof(tsbuf), "%lu", (unsigned long int) user->timestamp); anope_cmd_svid_umode2(user, tsbuf); alog("%s: %s!%s@%s automatically identified for nick %s", s_NickServ, user->nick, user->username, user->host, user->nick); } } /* Bahamut sets -r on every nick changes, so we must test it even if nc_changed == 0 */ if (ircd->check_nick_id) { if (nick_identified(user)) { char tsbuf[16]; snprintf(tsbuf, sizeof(tsbuf), "%lu", (unsigned long int) user->timestamp); anope_cmd_svid_umode3(user, tsbuf); } } return user; }
/* * Main program, either pmwho or fingerd. */ int main(int argc, char **argv) { CONF_SECTION *maincs, *cs; FILE *fp; struct radutmp rt; char inbuf[128]; char othername[256]; char nasname[1024]; char session_id[sizeof(rt.session_id)+1]; int fingerd = 0; int hideshell = 0; int showsid = 0; int rawoutput = 0; int radiusoutput = 0; /* Radius attributes */ char *p, *q; const char *portind; int c; unsigned int portno; char buffer[2048]; const char *user = NULL; int user_cmp = 0; time_t now = 0; uint32_t nas_port = ~0; uint32_t nas_ip_address = INADDR_NONE; int zap = 0; raddb_dir = RADIUS_DIR; while((c = getopt(argc, argv, "d:fF:nN:sSipP:crRu:U:Z")) != EOF) switch(c) { case 'd': raddb_dir = optarg; break; case 'f': fingerd++; showname = 0; break; case 'F': radutmp_file = optarg; break; case 'h': usage(0); break; case 'S': hideshell = 1; break; case 'n': showname = 0; break; case 'N': if (inet_pton(AF_INET, optarg, &nas_ip_address) < 0) { usage(1); } break; case 's': showname = 1; break; case 'i': showsid = 1; break; case 'p': showptype = 1; break; case 'P': nas_port = atoi(optarg); break; case 'c': showcid = 1; showname = 1; break; case 'r': rawoutput = 1; break; case 'R': radiusoutput = 1; now = time(NULL); break; case 'u': user = optarg; user_cmp = 0; break; case 'U': user = optarg; user_cmp = 1; break; case 'Z': zap = 1; break; default: usage(1); break; } /* * Be safe. */ if (zap && !radiusoutput) zap = 0; /* * zap EVERYONE, but only on this nas */ if (zap && !user && (~nas_port == 0)) { /* * We need to know which NAS to zap users in. */ if (nas_ip_address == INADDR_NONE) usage(1); printf("Acct-Status-Type = Accounting-Off\n"); printf("NAS-IP-Address = %s\n", hostname(buffer, sizeof(buffer), nas_ip_address)); printf("Acct-Delay-Time = 0\n"); exit(0); /* don't bother printing anything else */ } if (radutmp_file) goto have_radutmp; /* * Initialize mainconfig */ memset(&mainconfig, 0, sizeof(mainconfig)); mainconfig.radlog_dest = RADLOG_STDOUT; /* Read radiusd.conf */ snprintf(buffer, sizeof(buffer), "%.200s/radiusd.conf", raddb_dir); maincs = cf_file_read(buffer); if (!maincs) { fprintf(stderr, "%s: Error reading or parsing radiusd.conf.\n", argv[0]); exit(1); } /* Read the radutmp section of radiusd.conf */ cs = cf_section_find_name2(cf_section_sub_find(maincs, "modules"), "radutmp", NULL); if(!cs) { fprintf(stderr, "%s: No configuration information in radutmp section of radiusd.conf!\n", argv[0]); exit(1); } cf_section_parse(cs, NULL, module_config); /* Assign the correct path for the radutmp file */ radutmp_file = radutmpconfig.radutmp_fn; have_radutmp: /* * See if we are "fingerd". */ if (strstr(argv[0], "fingerd")) { fingerd++; eol = "\r\n"; if (showname < 0) showname = 0; } if (showname < 0) showname = 1; if (fingerd) { /* * Read first line of the input. */ fgets(inbuf, 128, stdin); p = inbuf; while(*p == ' ' || *p == '\t') p++; if (*p == '/' && *(p + 1)) p += 2; while(*p == ' ' || *p == '\t') p++; for(q = p; *q && *q != '\r' && *q != '\n'; q++) ; *q = 0; /* * See if we fingered a specific user. */ ffile("header"); if (*p) sys_finger(p); } /* * Show the users logged in on the terminal server(s). */ if ((fp = fopen(radutmp_file, "r")) == NULL) { fprintf(stderr, "%s: Error reading %s: %s\n", progname, radutmp_file, strerror(errno)); return 0; } /* * Don't print the headers if raw or RADIUS */ if (!rawoutput && !radiusoutput) { fputs(showname ? hdr1 : hdr2, stdout); fputs(eol, stdout); } /* * Read the file, printing out active entries. */ while (fread(&rt, sizeof(rt), 1, fp) == 1) { if (rt.type != P_LOGIN) continue; /* hide logout sessions */ /* * We don't show shell users if we are * fingerd, as we have done that above. */ if (hideshell && !strchr("PCS", rt.proto)) continue; /* * Print out sessions only for the given user. */ if (user) { /* only for a particular user */ if (((user_cmp == 0) && (strncasecmp(rt.login, user, strlen(user)) != 0)) || ((user_cmp == 1) && (strncmp(rt.login, user, strlen(user)) != 0))) { continue; } } /* * Print out only for the given NAS port. */ if (~nas_port != 0) { if (rt.nas_port != nas_port) continue; } /* * Print out only for the given NAS IP address */ if (nas_ip_address != INADDR_NONE) { if (rt.nas_address != nas_ip_address) continue; } memcpy(session_id, rt.session_id, sizeof(rt.session_id)); session_id[sizeof(rt.session_id)] = 0; if (!rawoutput && rt.nas_port > (showname ? 999 : 99999)) { portind = ">"; portno = (showname ? 999 : 99999); } else { portind = "S"; portno = rt.nas_port; } /* * Print output as RADIUS attributes */ if (radiusoutput) { memcpy(nasname, rt.login, sizeof(rt.login)); nasname[sizeof(rt.login)] = '\0'; fr_print_string(nasname, 0, buffer, sizeof(buffer)); printf("User-Name = \"%s\"\n", buffer); fr_print_string(session_id, 0, buffer, sizeof(buffer)); printf("Acct-Session-Id = \"%s\"\n", buffer); if (zap) printf("Acct-Status-Type = Stop\n"); printf("NAS-IP-Address = %s\n", hostname(buffer, sizeof(buffer), rt.nas_address)); printf("NAS-Port = %u\n", rt.nas_port); switch (rt.proto) { case 'S': printf("Service-Type = Framed-User\n"); printf("Framed-Protocol = SLIP\n"); break; case 'P': printf("Service-Type = Framed-User\n"); printf("Framed-Protocol = PPP\n"); break; default: printf("Service-type = Login-User\n"); break; } if (rt.framed_address != INADDR_NONE) { printf("Framed-IP-Address = %s\n", hostname(buffer, sizeof(buffer), rt.framed_address)); } /* * Some sanity checks on the time */ if ((rt.time <= now) && (now - rt.time) <= (86400 * 365)) { printf("Acct-Session-Time = %ld\n", now - rt.time); } if (rt.caller_id[0] != '\0') { memcpy(nasname, rt.caller_id, sizeof(rt.caller_id)); nasname[sizeof(rt.caller_id)] = '\0'; fr_print_string(nasname, 0, buffer, sizeof(buffer)); printf("Calling-Station-Id = \"%s\"\n", buffer); } printf("\n"); /* separate entries with a blank line */ continue; } /* * Show the fill name, or not. */ if (showname) { printf((rawoutput == 0? rfmt1: rfmt1r), rt.login, showcid ? rt.caller_id : (showsid? session_id : fullname(rt.login)), proto(rt.proto, rt.porttype), portind, portno, dotime(rt.time), hostname(nasname, sizeof(nasname), rt.nas_address), hostname(othername, sizeof(othername), rt.framed_address), eol); } else { printf((rawoutput == 0? rfmt2: rfmt2r), rt.login, portind, portno, proto(rt.proto, rt.porttype), dotime(rt.time), hostname(nasname, sizeof(nasname), rt.nas_address), hostname(othername, sizeof(othername), rt.framed_address), eol); } } fclose(fp); return 0; }
int parse_directive(Directive * d, char *dir, int ac, char *av[MAXPARAMS], int linenum, int reload, char *s) { int retval = 1; int i; long val; int optind; if (stricmp(dir, d->name) != 0) return 1; optind = 0; for (i = 0; i < MAXPARAMS && d->params[i].type != PARAM_NONE; i++) { if (reload && !(d->params[i].flags & PARAM_RELOAD)) continue; if (d->params[i].type == PARAM_SET) { *(int *) d->params[i].ptr = 1; continue; } #ifdef STREAMLINED if (d->params[i].flags & PARAM_FULLONLY) { error(linenum, "Directive `%s' not available in STREAMLINED mode", d->name); break; } #endif /* Should we remove PARAM_DEPRECATED because it's * useless right now? -GD */ if (d->params[i].type == PARAM_DEPRECATED) { union func_union { void *ptr; void (*func)(void); } u; error(linenum, "Deprecated directive `%s' used", d->name); u.ptr = d->params[i].ptr; u.func(); continue; } if (optind >= ac) { if (!(d->params[i].flags & PARAM_OPTIONAL)) { error(linenum, "Not enough parameters for `%s'", d->name); retval = 0; } break; } switch (d->params[i].type) { case PARAM_INT: val = strtol(av[optind++], &s, 10); if (*s) { error(linenum, "%s: Expected an integer for parameter %d", d->name, optind); retval = 0; break; } *(int *) d->params[i].ptr = val; break; case PARAM_POSINT: val = strtol(av[optind++], &s, 10); if (*s || val <= 0) { error(linenum, "%s: Expected a positive integer for parameter %d", d->name, optind); retval = 0; break; } if (errno == ERANGE && val == LONG_MAX) { /* well the true top off is 2,147,483,647 but lets not give them the real top */ error(linenum, "%s: paramter %d is to large, reduce this value (0 to 2,147,483,646)", d->name, optind); } *(int *) d->params[i].ptr = val; break; case PARAM_PORT: val = strtol(av[optind++], &s, 10); if (*s) { error(linenum, "%s: Expected a port number for parameter %d", d->name, optind); retval = 0; break; } if (val < 1 || val > 65535) { error(linenum, "Port numbers must be in the range 1..65535"); retval = 0; break; } *(int *) d->params[i].ptr = val; break; case PARAM_STRING: /* * Anope_Free(*(char **)d->params[i].ptr); * Historically dumb modules pass uninitialized values here so * we can't free this */ *(char **) d->params[i].ptr = sstrdup(av[optind++]); if (!d->params[i].ptr) { error(linenum, "%s: Out of memory", d->name); return 0; } break; case PARAM_TIME: val = dotime(av[optind++]); if (val < 0) { error(linenum, "%s: Expected a time value for parameter %d", d->name, optind); retval = 0; break; } *(int *) d->params[i].ptr = val; break; default: error(linenum, "%s: Unknown type %d for param %d", d->name, d->params[i].type, i + 1); retval = 0; /* don't bother continuing--something's bizarre */ break; } } return retval;; }
static int do_akill(User * u) { char *cmd = strtok(NULL, " "); char breason[BUFSIZE]; if (!cmd) cmd = ""; if (!stricmp(cmd, "ADD")) { int deleted = 0; char *expiry, *mask, *reason; time_t expires, now = time(NULL); mask = strtok(NULL, " "); if (mask && *mask == '+') { expiry = mask; mask = strtok(NULL, " "); } else { expiry = NULL; } expires = expiry ? dotime(expiry) : AutokillExpiry; /* If the expiry given does not contain a final letter, it's in days, * said the doc. Ah well. */ if (expiry && isdigit(expiry[strlen(expiry) - 1])) expires *= 86400; /* Do not allow less than a minute expiry time */ if (expires != 0 && expires < 60) { notice_lang(s_OperServ, u, BAD_EXPIRY_TIME); return MOD_CONT; } else if (expires > 0) { expires += time(NULL); } if (mask && (reason = strtok(NULL, ""))) { /* We first do some sanity check on the proposed mask. */ if (strchr(mask, '!')) { notice_lang(s_OperServ, u, OPER_AKILL_NO_NICK); return MOD_CONT; } if (!strchr(mask, '@')) { notice_lang(s_OperServ, u, BAD_USERHOST_MASK); return MOD_CONT; } if (mask && strspn(mask, "~@.*?") == strlen(mask)) { notice_lang(s_OperServ, u, USERHOST_MASK_TOO_WIDE, mask); return MOD_CONT; } /** * Changed sprintf() to snprintf()and increased the size of * breason to match bufsize * -Rob **/ if (AddAkiller) { snprintf(breason, sizeof(breason), "[%s] %s", u->nick, reason); reason = sstrdup(breason); } deleted = add_akill(u, mask, u->nick, expires, reason); if (deleted < 0) { if (AddAkiller) { free(reason); } return MOD_CONT; } else if (deleted) { notice_lang(s_OperServ, u, OPER_AKILL_DELETED_SEVERAL, deleted); } notice_lang(s_OperServ, u, OPER_AKILL_ADDED, mask); if (WallOSAkill) { char buf[128]; if (!expires) { strcpy(buf, "does not expire"); } else { int wall_expiry = expires - now; char *s = NULL; if (wall_expiry >= 86400) { wall_expiry /= 86400; s = "day"; } else if (wall_expiry >= 3600) { wall_expiry /= 3600; s = "hour"; } else if (wall_expiry >= 60) { wall_expiry /= 60; s = "minute"; } snprintf(buf, sizeof(buf), "expires in %d %s%s", wall_expiry, s, (wall_expiry == 1) ? "" : "s"); } anope_cmd_global(s_OperServ, "%s added an AKILL for %s (%s) (%s)", u->nick, mask, reason, buf); } if (readonly) { notice_lang(s_OperServ, u, READ_ONLY_MODE); } if (AddAkiller) { free(reason); } } else { syntax_error(s_OperServ, u, "AKILL", OPER_AKILL_SYNTAX); } } else if (!stricmp(cmd, "DEL")) { char *mask; int res = 0; mask = strtok(NULL, " "); if (!mask) { syntax_error(s_OperServ, u, "AKILL", OPER_AKILL_SYNTAX); return MOD_CONT; } if (akills.count == 0) { notice_lang(s_OperServ, u, OPER_AKILL_LIST_EMPTY); return MOD_CONT; } if (isdigit(*mask) && strspn(mask, "1234567890,-") == strlen(mask)) { /* Deleting a range */ res = slist_delete_range(&akills, mask, NULL); if (res == 0) { notice_lang(s_OperServ, u, OPER_AKILL_NO_MATCH); return MOD_CONT; } else if (res == 1) { notice_lang(s_OperServ, u, OPER_AKILL_DELETED_ONE); } else { notice_lang(s_OperServ, u, OPER_AKILL_DELETED_SEVERAL, res); } } else { if ((res = slist_indexof(&akills, mask)) == -1) { notice_lang(s_OperServ, u, OPER_AKILL_NOT_FOUND, mask); return MOD_CONT; } slist_delete(&akills, res); notice_lang(s_OperServ, u, OPER_AKILL_DELETED, mask); } if (readonly) notice_lang(s_OperServ, u, READ_ONLY_MODE); } else if (!stricmp(cmd, "LIST")) { char *mask; int res, sent_header = 0; if (akills.count == 0) { notice_lang(s_OperServ, u, OPER_AKILL_LIST_EMPTY); return MOD_CONT; } mask = strtok(NULL, " "); if (!mask || (isdigit(*mask) && strspn(mask, "1234567890,-") == strlen(mask))) { res = slist_enum(&akills, mask, &akill_list_callback, u, &sent_header); if (res == 0) { notice_lang(s_OperServ, u, OPER_AKILL_NO_MATCH); return MOD_CONT; } else { notice_lang(s_OperServ, u, END_OF_ANY_LIST, "Akill"); } } else { int i; char amask[BUFSIZE]; for (i = 0; i < akills.count; i++) { snprintf(amask, sizeof(amask), "%s@%s", ((Akill *) akills.list[i])->user, ((Akill *) akills.list[i])->host); if (!stricmp(mask, amask) || match_wild_nocase(mask, amask)) akill_list(i + 1, akills.list[i], u, &sent_header); } if (!sent_header) notice_lang(s_OperServ, u, OPER_AKILL_NO_MATCH); else { notice_lang(s_OperServ, u, END_OF_ANY_LIST, "Akill"); } } } else if (!stricmp(cmd, "VIEW")) { char *mask; int res, sent_header = 0; if (akills.count == 0) { notice_lang(s_OperServ, u, OPER_AKILL_LIST_EMPTY); return MOD_CONT; } mask = strtok(NULL, " "); if (!mask || (isdigit(*mask) && strspn(mask, "1234567890,-") == strlen(mask))) { res = slist_enum(&akills, mask, &akill_view_callback, u, &sent_header); if (res == 0) { notice_lang(s_OperServ, u, OPER_AKILL_NO_MATCH); return MOD_CONT; } } else { int i; char amask[BUFSIZE]; for (i = 0; i < akills.count; i++) { snprintf(amask, sizeof(amask), "%s@%s", ((Akill *) akills.list[i])->user, ((Akill *) akills.list[i])->host); if (!stricmp(mask, amask) || match_wild_nocase(mask, amask)) akill_view(i + 1, akills.list[i], u, &sent_header); } if (!sent_header) notice_lang(s_OperServ, u, OPER_AKILL_NO_MATCH); } } else if (!stricmp(cmd, "CLEAR")) { slist_clear(&akills, 1); notice_lang(s_OperServ, u, OPER_AKILL_CLEAR); } else { syntax_error(s_OperServ, u, "AKILL", OPER_AKILL_SYNTAX); } return MOD_CONT; }
/** * ChanKill - Akill an entire channel (got botnet?) * * /msg OperServ ChanKill +expire #channel reason * @param u The user who issued the command * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. * **/ int do_chankill(User * u) { char *expiry, *channel, *reason; time_t expires; char breason[BUFSIZE]; char mask[USERMAX + HOSTMAX + 2]; struct c_userlist *cu, *next; Channel *c; channel = strtok(NULL, " "); if (channel && *channel == '+') { expiry = channel; channel = strtok(NULL, " "); } else { expiry = NULL; } expires = expiry ? dotime(expiry) : ChankillExpiry; if (expiry && isdigit(expiry[strlen(expiry) - 1])) expires *= 86400; if (expires != 0 && expires < 60) { notice_lang(s_OperServ, u, BAD_EXPIRY_TIME); return MOD_CONT; } else if (expires > 0) { expires += time(NULL); } if (channel && (reason = strtok(NULL, ""))) { if (AddAkiller) { snprintf(breason, sizeof(breason), "[%s] %s", u->nick, reason); reason = sstrdup(breason); } if ((c = findchan(channel))) { for (cu = c->users; cu; cu = next) { next = cu->next; if (is_oper(cu->user)) { continue; } (void) strncpy(mask, "*@", 3); /* Use *@" for the akill's, */ strncat(mask, cu->user->host, HOSTMAX); add_akill(NULL, mask, s_OperServ, expires, reason); check_akill(cu->user->nick, cu->user->username, cu->user->host, NULL, NULL); } if (WallOSAkill) { xanadu_cmd_global(s_OperServ, "%s used CHANKILL on %s (%s)", u->nick, channel, reason); } } else { notice_lang(s_OperServ, u, CHAN_X_NOT_IN_USE, channel); } if (AddAkiller) { free(reason); } } else { syntax_error(s_OperServ, u, "CHANKILL", OPER_CHANKILL_SYNTAX); } return MOD_CONT; }
void DoAdd(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; Anope::string mask, expiry, limitstr; unsigned last_param = 3; mask = params.size() > 1 ? params[1] : ""; if (!mask.empty() && mask[0] == '+') { expiry = mask; mask = params.size() > 2 ? params[2] : ""; last_param = 4; } limitstr = params.size() > last_param - 1 ? params[last_param - 1] : ""; if (params.size() <= last_param) { this->OnSyntaxError(source, "ADD"); return; } Anope::string reason = params[last_param]; if (last_param == 3 && params.size() > 4) reason += " " + params[4]; if (reason.empty()) { this->OnSyntaxError(source, "ADD"); return; } time_t expires = !expiry.empty() ? dotime(expiry) : Config->ExceptionExpiry; if (expires < 0) { source.Reply(BAD_EXPIRY_TIME); return; } else if (expires > 0) expires += Anope::CurTime; int limit = -1; try { limit = convertTo<int>(limitstr); } catch (const ConvertException &) { } if (limit < 0 || limit > static_cast<int>(Config->MaxSessionLimit)) { source.Reply(_("Invalid session limit. It must be a valid integer greater than or equal to zero and less than \002%d\002."), Config->MaxSessionLimit); return; } else { if (mask.find('!') != Anope::string::npos || mask.find('@') != Anope::string::npos) { source.Reply(_("Invalid hostmask. Only real hostmasks are valid, as exceptions are not matched against nicks or usernames.")); return; } for (std::vector<Exception *>::iterator it = session_service->GetExceptions().begin(), it_end = session_service->GetExceptions().end(); it != it_end; ++it) { Exception *e = *it; if (e->mask.equals_ci(mask)) { if (e->limit != limit) { e->limit = limit; source.Reply(_("Exception for \002%s\002 has been updated to %d."), mask.c_str(), e->limit); } else source.Reply(_("\002%s\002 already exists on the EXCEPTION list."), mask.c_str()); return; } } Exception *exception = new Exception(); exception->mask = mask; exception->limit = limit; exception->reason = reason; exception->time = Anope::CurTime; exception->who = u->nick; exception->expires = expires; EventReturn MOD_RESULT; FOREACH_RESULT(I_OnExceptionAdd, OnExceptionAdd(exception)); if (MOD_RESULT == EVENT_STOP) delete exception; else { session_service->AddException(exception); source.Reply(_("Session limit for \002%s\002 set to \002%d\002."), mask.c_str(), limit); if (readonly) source.Reply(READ_ONLY_MODE); } } return; }
int do_exception(User * u) { char *cmd = strtok(NULL, " "); char *mask, *reason, *expiry, *limitstr; int limit, expires; int i; int x; if (!LimitSessions) { notice_lang(s_OperServ, u, OPER_EXCEPTION_DISABLED); return MOD_CONT; } if (!cmd) cmd = ""; if (stricmp(cmd, "ADD") == 0) { if (nexceptions >= 32767) { notice_lang(s_OperServ, u, OPER_EXCEPTION_TOO_MANY); return MOD_CONT; } mask = strtok(NULL, " "); if (mask && *mask == '+') { expiry = mask; mask = strtok(NULL, " "); } else { expiry = NULL; } limitstr = strtok(NULL, " "); reason = strtok(NULL, ""); if (!reason) { syntax_error(s_OperServ, u, "EXCEPTION", OPER_EXCEPTION_ADD_SYNTAX); return MOD_CONT; } expires = expiry ? dotime(expiry) : ExceptionExpiry; if (expires < 0) { notice_lang(s_OperServ, u, BAD_EXPIRY_TIME); return MOD_CONT; } else if (expires > 0) { expires += time(NULL); } limit = (limitstr && isdigit(*limitstr)) ? atoi(limitstr) : -1; if (limit < 0 || limit > MaxSessionLimit) { notice_lang(s_OperServ, u, OPER_EXCEPTION_INVALID_LIMIT, MaxSessionLimit); return MOD_CONT; } else { if (strchr(mask, '!') || strchr(mask, '@')) { notice_lang(s_OperServ, u, OPER_EXCEPTION_INVALID_HOSTMASK); return MOD_CONT; } x = exception_add(u, mask, limit, reason, u->nick, expires); if (x == 1) { notice_lang(s_OperServ, u, OPER_EXCEPTION_ADDED, mask, limit); } if (readonly) notice_lang(s_OperServ, u, READ_ONLY_MODE); } } else if (stricmp(cmd, "DEL") == 0) { mask = strtok(NULL, " "); if (!mask) { syntax_error(s_OperServ, u, "EXCEPTION", OPER_EXCEPTION_DEL_SYNTAX); return MOD_CONT; } if (isdigit(*mask) && strspn(mask, "1234567890,-") == strlen(mask)) { int count, deleted, last = -1; deleted = process_numlist(mask, &count, exception_del_callback, u, &last); if (!deleted) { if (count == 1) { notice_lang(s_OperServ, u, OPER_EXCEPTION_NO_SUCH_ENTRY, last); } else { notice_lang(s_OperServ, u, OPER_EXCEPTION_NO_MATCH); } } else if (deleted == 1) { notice_lang(s_OperServ, u, OPER_EXCEPTION_DELETED_ONE); } else { notice_lang(s_OperServ, u, OPER_EXCEPTION_DELETED_SEVERAL, deleted); } } else { int deleted = 0; for (i = 0; i < nexceptions; i++) { if (stricmp(mask, exceptions[i].mask) == 0) { exception_del(i); notice_lang(s_OperServ, u, OPER_EXCEPTION_DELETED, mask); deleted = 1; break; } } if (!deleted && i == nexceptions) notice_lang(s_OperServ, u, OPER_EXCEPTION_NOT_FOUND, mask); } /* Renumber the exception list. I don't believe in having holes in * lists - it makes code more complex, harder to debug and we end up * with huge index numbers. Imho, fixed numbering is only beneficial * when one doesn't have range capable manipulation. -TheShadow */ for (i = 0; i < nexceptions; i++) exceptions[i].num = i; if (readonly) notice_lang(s_OperServ, u, READ_ONLY_MODE); } else if (stricmp(cmd, "MOVE") == 0) { Exception *exception; char *n1str = strtok(NULL, " "); /* From position */ char *n2str = strtok(NULL, " "); /* To position */ int n1, n2; if (!n2str) { syntax_error(s_OperServ, u, "EXCEPTION", OPER_EXCEPTION_MOVE_SYNTAX); return MOD_CONT; } n1 = atoi(n1str) - 1; n2 = atoi(n2str) - 1; if ((n1 >= 0 && n1 < nexceptions) && (n2 >= 0 && n2 < nexceptions) && (n1 != n2)) { exception = scalloc(sizeof(Exception), 1); memcpy(exception, &exceptions[n1], sizeof(Exception)); if (n1 < n2) { /* Shift upwards */ memmove(&exceptions[n1], &exceptions[n1 + 1], sizeof(Exception) * (n2 - n1)); memmove(&exceptions[n2], exception, sizeof(Exception)); } else { /* Shift downwards */ memmove(&exceptions[n2 + 1], &exceptions[n2], sizeof(Exception) * (n1 - n2)); memmove(&exceptions[n2], exception, sizeof(Exception)); } free(exception); notice_lang(s_OperServ, u, OPER_EXCEPTION_MOVED, exceptions[n1].mask, n1 + 1, n2 + 1); /* Renumber the exception list. See the DEL block above for why. */ for (i = 0; i < nexceptions; i++) exceptions[i].num = i; if (readonly) notice_lang(s_OperServ, u, READ_ONLY_MODE); } else { syntax_error(s_OperServ, u, "EXCEPTION", OPER_EXCEPTION_MOVE_SYNTAX); } } else if (stricmp(cmd, "LIST") == 0) { int sent_header = 0; expire_exceptions(); mask = strtok(NULL, " "); if (mask && strspn(mask, "1234567890,-") == strlen(mask)) { process_numlist(mask, NULL, exception_list_callback, u, &sent_header); } else { for (i = 0; i < nexceptions; i++) { if (!mask || match_wild_nocase(mask, exceptions[i].mask)) exception_list(u, i, &sent_header); } } if (!sent_header) notice_lang(s_OperServ, u, OPER_EXCEPTION_NO_MATCH); } else if (stricmp(cmd, "VIEW") == 0) { int sent_header = 0; expire_exceptions(); mask = strtok(NULL, " "); if (mask && strspn(mask, "1234567890,-") == strlen(mask)) { process_numlist(mask, NULL, exception_view_callback, u, &sent_header); } else { for (i = 0; i < nexceptions; i++) { if (!mask || match_wild_nocase(mask, exceptions[i].mask)) exception_view(u, i, &sent_header); } } if (!sent_header) notice_lang(s_OperServ, u, OPER_EXCEPTION_NO_MATCH); } else { syntax_error(s_OperServ, u, "EXCEPTION", OPER_EXCEPTION_SYNTAX); } return MOD_CONT; }
/** * The /os sgline command. * @param u The user who issued the command * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. **/ int do_sgline(User * u) { char *cmd = strtok(NULL, " "); if (!cmd) cmd = ""; if (!stricmp(cmd, "ADD")) { int deleted = 0; char *expiry, *mask, *reason; time_t expires; mask = strtok(NULL, ":"); if (mask && *mask == '+') { expiry = mask; mask = strchr(expiry, ' '); if (mask) { *mask = 0; mask++; } } else { expiry = NULL; } expires = expiry ? dotime(expiry) : SGLineExpiry; /* If the expiry given does not contain a final letter, it's in days, * said the doc. Ah well. */ if (expiry && isdigit(expiry[strlen(expiry) - 1])) expires *= 86400; /* Do not allow less than a minute expiry time */ if (expires != 0 && expires < 60) { notice_lang(s_OperServ, u, BAD_EXPIRY_TIME); return MOD_CONT; } else if (expires > 0) { expires += time(NULL); } if (mask && (reason = strtok(NULL, ""))) { /* Clean up the last character of the mask if it is a space * See bug #761 */ size_t masklen = strlen(mask); if (mask[masklen - 1] == ' ') mask[masklen - 1] = '\0'; /* We first do some sanity check on the proposed mask. */ if (mask && strspn(mask, "*?") == strlen(mask)) { notice_lang(s_OperServ, u, USERHOST_MASK_TOO_WIDE, mask); return MOD_CONT; } deleted = add_sgline(u, mask, u->nick, expires, reason); if (deleted < 0) return MOD_CONT; else if (deleted) notice_lang(s_OperServ, u, OPER_SGLINE_DELETED_SEVERAL, deleted); notice_lang(s_OperServ, u, OPER_SGLINE_ADDED, mask); if (WallOSSGLine) { char buf[128]; if (!expires) { strcpy(buf, "does not expire"); } else { int wall_expiry = expires - time(NULL); char *s = NULL; if (wall_expiry >= 86400) { wall_expiry /= 86400; s = "day"; } else if (wall_expiry >= 3600) { wall_expiry /= 3600; s = "hour"; } else if (wall_expiry >= 60) { wall_expiry /= 60; s = "minute"; } snprintf(buf, sizeof(buf), "expires in %d %s%s", wall_expiry, s, (wall_expiry == 1) ? "" : "s"); } xanadu_cmd_global(s_OperServ, "%s added an SGLINE for %s (%s)", u->nick, mask, buf); } if (readonly) notice_lang(s_OperServ, u, READ_ONLY_MODE); } else { syntax_error(s_OperServ, u, "SGLINE", OPER_SGLINE_SYNTAX); } } else if (!stricmp(cmd, "DEL")) { char *mask; int res = 0; mask = strtok(NULL, ""); if (!mask) { syntax_error(s_OperServ, u, "SGLINE", OPER_SGLINE_SYNTAX); return MOD_CONT; } if (sglines.count == 0) { notice_lang(s_OperServ, u, OPER_SGLINE_LIST_EMPTY); return MOD_CONT; } if (isdigit(*mask) && strspn(mask, "1234567890,-") == strlen(mask)) { /* Deleting a range */ res = slist_delete_range(&sglines, mask, NULL); if (res == 0) { notice_lang(s_OperServ, u, OPER_SGLINE_NO_MATCH); return MOD_CONT; } else if (res == 1) { notice_lang(s_OperServ, u, OPER_SGLINE_DELETED_ONE); } else { notice_lang(s_OperServ, u, OPER_SGLINE_DELETED_SEVERAL, res); } } else { if ((res = slist_indexof(&sglines, mask)) == -1) { notice_lang(s_OperServ, u, OPER_SGLINE_NOT_FOUND, mask); return MOD_CONT; } slist_delete(&sglines, res); notice_lang(s_OperServ, u, OPER_SGLINE_DELETED, mask); } if (readonly) notice_lang(s_OperServ, u, READ_ONLY_MODE); } else if (!stricmp(cmd, "LIST")) { char *mask; int res, sent_header = 0; if (sglines.count == 0) { notice_lang(s_OperServ, u, OPER_SGLINE_LIST_EMPTY); return MOD_CONT; } mask = strtok(NULL, ""); if (!mask || (isdigit(*mask) && strspn(mask, "1234567890,-") == strlen(mask))) { res = slist_enum(&sglines, mask, &sgline_list_callback, u, &sent_header); if (res == 0) { notice_lang(s_OperServ, u, OPER_SGLINE_NO_MATCH); return MOD_CONT; } } else { int i; char *amask; for (i = 0; i < sglines.count; i++) { amask = ((SXLine *) sglines.list[i])->mask; if (!stricmp(mask, amask) || match_wild_nocase(mask, amask)) sgline_list(i + 1, sglines.list[i], u, &sent_header); } if (!sent_header) notice_lang(s_OperServ, u, OPER_SGLINE_NO_MATCH); else { notice_lang(s_OperServ, u, END_OF_ANY_LIST, "SGLine"); } } } else if (!stricmp(cmd, "VIEW")) { char *mask; int res, sent_header = 0; if (sglines.count == 0) { notice_lang(s_OperServ, u, OPER_SGLINE_LIST_EMPTY); return MOD_CONT; } mask = strtok(NULL, ""); if (!mask || (isdigit(*mask) && strspn(mask, "1234567890,-") == strlen(mask))) { res = slist_enum(&sglines, mask, &sgline_view_callback, u, &sent_header); if (res == 0) { notice_lang(s_OperServ, u, OPER_SGLINE_NO_MATCH); return MOD_CONT; } } else { int i; char *amask; for (i = 0; i < sglines.count; i++) { amask = ((SXLine *) sglines.list[i])->mask; if (!stricmp(mask, amask) || match_wild_nocase(mask, amask)) sgline_view(i + 1, sglines.list[i], u, &sent_header); } if (!sent_header) notice_lang(s_OperServ, u, OPER_SGLINE_NO_MATCH); } } else if (!stricmp(cmd, "CLEAR")) { slist_clear(&sglines, 1); notice_lang(s_OperServ, u, OPER_SGLINE_CLEAR); } else { syntax_error(s_OperServ, u, "SGLINE", OPER_SGLINE_SYNTAX); } return MOD_CONT; }