Main Page | Modules | Namespace List | Class Hierarchy | Class List | File List | Class Members | File Members | Related Pages

operserv.c

Go to the documentation of this file.
00001 
00014 /*
00015  * Copyright (c) 1996-1997 Chip Norkus
00016  * Copyright (c) 1997 Max Byrd
00017  * Copyright (c) 1997 Greg Poma
00018  * Copyright (c) 1998-2001 James Hess
00019  * All rights reserved.
00020  *
00021  * Redistribution and use in source and binary forms, with or without
00022  * modification, are permitted provided that the following conditions
00023  * are met:
00024  * 1. Redistributions of source code must retain the above copyright
00025  *    notice, this list of conditions and the following disclaimer.
00026  * 2. Redistributions in binary form must reproduce the above copyright
00027  *    notice, this list of conditions and the following disclaimer in the
00028  *    documentation and/or other materials provided with the distribution.
00029  * 3. Neither the name of the authors nor the names of its contributors
00030  *    may be used to endorse or promote products derived from this software
00031  *    without specific prior written permission.
00032  *
00033  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
00034  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00035  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00036  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
00037  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00038  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00039  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00040  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00041  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00042  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00043  * SUCH DAMAGE.
00044  */
00045 
00046 #include "services.h"
00047 #include "nickserv.h"
00048 #include "chanserv.h"
00049 #include "operserv.h"
00050 #include "infoserv.h"
00051 #include "gameserv.h"
00052 #include "clone.h"
00053 #include "hash.h"
00054 #include "log.h"
00055 #include "macro.h"
00056 #include "interp.h"
00057 #include "hash/md5pw.h"
00058 
00059 // *INDENT-OFF*
00060 
00061 void listCloneAlerts(UserList *);
00062 
00063 u_long counterOldCSFmt = 0;
00064 static UserList *os_user_override = (UserList *)0;
00065 
00067 interp::service_cmd_t operserv_commands[] = {
00068   /* string     function     Flags  L */
00069   { "help",     os_help,     0,     LOG_NO },
00070   { "autokill", os_akill,    0,     LOG_NO },
00071   { "akill",    os_akill,    0,     LOG_NO },  /* alias for autokill */
00072   { "tempakill",os_tempakill,0,     LOG_DB },  /* for temporary autokills */
00073 #ifdef ENABLE_AHURT
00074   { "ahurt",    os_akill,    0,     LOG_NO },
00075   { "autohurt", os_akill,    0,     LOG_NO },
00076 #endif
00077   { "clonerule",os_clonerule,0,     LOG_DB },
00078   { "ignore",   os_akill,    0,     LOG_NO },
00079   { "mode",     os_mode,     0,     LOG_OK },
00080   { "raw",      os_raw,      ORAW,  LOG_OK },
00081   { "shutdown", os_shutdown, OROOT, LOG_OK },
00082   { "reset",    os_reset,    OROOT, LOG_OK },
00083   { "rehash",   os_reset,    OROOT, LOG_OK },  /* alias for reset */
00084   { "jupe",     os_jupe,     OJUPE, LOG_OK },
00085   { "uptime",   os_uptime,   0,     LOG_NO },
00086   { "timers",   os_timers,   1,     LOG_NO },
00087   { "sync",     os_sync,     OROOT, LOG_OK },
00088   { "trigger",  os_trigger,  0,     LOG_OK },
00089   { "match",    os_match,    0,     LOG_NO },
00090   { "cloneset", os_cloneset, 0,     LOG_OK },
00091 #ifndef _DOXYGEN
00092   { MSG_REMSRA,  os_remsra,  0, LOG_NO },
00093 #endif
00094   { "setop",    os_setop,    0,     LOG_NO },
00095   { "grpop",    os_grpop  ,  0,     LOG_DB },
00096   { "override", os_override, 0,     LOG_NO },
00097   { "heal", os_heal,     0,     LOG_OK },
00098   { "strike",   os_strike,   0,     LOG_ALWAYS },
00099   { "nixghost", os_nixghost, 0,     LOG_ALWAYS },
00100   { NULL,       NULL,        0,     LOG_NO }
00101 };
00102 
00104 const char *cloneset_bits[] = {
00105   "KILL", "IGNORE", "", "OK", NULL
00106 };
00107 
00108 // *INDENT-ON*
00109 /************************************************************************/
00110 
00112 #define SETCLR(var, flag, onoff) do {   \
00113   if (onoff)                            \
00114     (var) |= (flag);                    \
00115   else                                  \
00116     (var) &= ~(flag);                   \
00117 } while (0)
00118 
00128 void sendToOperServ(UserList * nick, char **args, int numargs)
00129 {
00130     char *from = nick->nick;
00131     interp::parser * cmd;
00132 
00133     if (numargs < 1) {
00134         sSend(":%s NOTICE %s :huh?", OperServ, from);
00135         return;
00136     }
00137 
00138     if (!isOper(nick)) {
00139         sSend(":%s NOTICE %s "
00140               ":You must be an IRC Operator to use this service.",
00141               OperServ, from);
00142         return;
00143     }
00144 
00145 
00146     cmd =
00147         new interp::parser(OperServ, getOpFlags(nick), operserv_commands,
00148                            args[0]);
00149     if (!cmd)
00150         return;
00151     switch (cmd->run(nick, args, numargs)) {
00152     default:
00153         break;
00154     case RET_FAIL:
00155         sSend(":%s NOTICE %s :Unknown command %s.\r\n"
00156               ":%s NOTICE %s :Please try /msg %s HELP", OperServ, from,
00157               args[0], OperServ, from, OperServ);
00158         break;
00159     }
00160     delete cmd;
00161     return;
00162 }
00163 
00164 /************************************************************************/
00165 
00167 int userOverriding(UserList * nick)
00168 {
00169     return (os_user_override == nick);
00170 }
00171 
00172 /************************************************************************/
00173 
00174 
00180 OCMD(os_help)
00181 {
00182     help(nick->nick, OperServ, args, numargs);
00183     return RET_OK;
00184 }
00185 
00186 
00187 /************************************************************************/
00188 
00194 OCMD(os_setop)
00195 {
00196     sendToNickServ(nick, args, numargs);
00197     return RET_OK;
00198 }
00199 
00200 /************************************************************************/
00240 OCMD(os_akill)
00241 {
00242     int i, t, count, akill_type, has_prim = 0;
00243     interp::services_cmd_id log_type = OS_AKILL;
00244     char akreason[IRCBUF];
00245     const char *listProper, *p;
00246     flag_t permPrim, perm2;
00247     char *from = nick->nick;
00248 #       if AKREASON_LEN >= IRCBUF
00249 #          error AKREASON_LEN cannot be >= IRCBUF!
00250            *;
00251 #       endif
00252 
00253     permPrim = perm2 = OROOT;
00254 
00255     if (numargs < 1)
00256         return RET_EFAULT;
00257 
00258     /*
00259      * First figure out which command we are, will later simplify this
00260      * by introducing the notion of a 'sub command' into the parser
00261      */
00262 
00263     if (!str_cmp(args[0], "akill") || !str_cmp(args[0], "autokill")) 
00264     {
00265         permPrim = OAKILL;
00266         perm2 = ORAKILL;
00267         akill_type = A_AKILL;
00268         log_type = OS_AKILL;
00269     }
00270     else if (!str_cmp(args[0], "ahurt") || !str_cmp(args[0], "autohurt"))
00271     {
00272         permPrim = OAHURT;
00273         akill_type = A_AHURT;
00274         log_type = OS_AHURT;
00275     }
00276     else if (!str_cmp(args[0], "ignore"))
00277     {
00278         permPrim = OIGNORE;
00279         akill_type = A_IGNORE;
00280         log_type = OS_IGNORE;
00281     }
00282     else {
00283         sSend(":%s NOTICE %s :Internal Error (args[0] = %s)",
00284               OperServ, from, args[0]);
00285         sSend(":%s GLOBOPS :os_akill: Internal Error (args[0] = %s)",
00286               OperServ, args[0]);
00287         return RET_FAIL;
00288     }
00289 
00290     // Store the proper name of the list being edited
00291 
00292     listProper = aktype_str(akill_type, 0);
00293 
00294     /*
00295      * No subcommand means list, and so does "list"
00296      */
00297     if ((numargs < 2) || (!str_cmp(args[1], "list"))) {
00298         if (!opFlagged(nick, OVERRIDE))
00299             listAkills(from, akill_type);
00300         else
00301             listAkills(from, 0);
00302         return RET_OK;
00303     }
00304 
00305     /*
00306      * More than a list of XXX requires more permissions.
00307      */
00308     if (!isServop(nick) && !isRoot(nick) && !opFlagged(nick, permPrim)
00309         && !opFlagged(nick, perm2)) {
00310         sSend(":%s NOTICE %s :Permission denied.", OperServ, from);
00311 
00312         return RET_NOPERM;
00313     }
00314     else if (isRoot(nick) || isServop(nick) || opFlagged(nick, permPrim))
00315     {
00316         has_prim = 1;
00317     }
00318 
00319     /*
00320      * delete a nickname
00321      */
00322     if (args[1][0] == '-' || !strcasecmp(args[1], "del")) {
00323         if (args[1][0] != '-' || args[1][1] == '\0')
00324         {
00325             if ((numargs < 3) || !strchr(args[2], '!')
00326                 || !strchr(args[2], '@')) 
00327             {
00328                 PutError(OperServ, nick, ERR_AKILLSYNTAX_1ARG, args[0], 0, 0);
00329                 PutReply(OperServ, nick, RPL_AKILLHELP_2ARG, OperServ, listProper, 0);
00330                 return RET_SYNTAX;
00331             }
00332             if (!removeAkillType(from, args[2], akill_type,
00333                     has_prim == 0 ? 1 : 0))
00334                 operlog->log(nick, log_type, args[2], LOGF_OFF);
00335         }
00336         else {
00337             if ((numargs != 2) || !strchr(args[1], '!')
00338                 || !strchr(args[1], '@')) 
00339             {
00340                 PutError(OperServ, nick, ERR_AKILLSYNTAX_1ARG, args[0], 0, 0);
00341                 PutReply(OperServ, nick, RPL_AKILLHELP_2ARG, OperServ, listProper, 0);
00342                 return RET_SYNTAX;
00343             }
00344 
00345             // operserv override ignore -<blah> for example
00346             // can remove 'bad items', for example
00347             if (!opFlagged(nick, OVERRIDE)) {
00348                 if (!removeAkillType(from, args[1]+1, akill_type, has_prim == 0 ? 1 : 0))
00349                     operlog->log(nick, log_type, args[1]+1, LOGF_OFF);
00350             }
00351             else {
00352                 if (!removeAkill(from, args[1]+1))
00353                     operlog->log(nick, log_type, args[1]+1, LOGF_OFF);
00354             }
00355         }
00356 
00357         return RET_OK_DB;
00358     }
00359 
00360     /*
00361      * Must be an add.  If it has less than 4 arguments is is invalid.
00362      * Also, if the second argument doesn't have a @ and a ! in it,
00363      * it is also invalid.
00364      */
00365     if ((numargs < 4)
00366         || (strchr(args[2], '!') == NULL)
00367         || (strchr(args[2], '@') == NULL)
00368         || match("*?!?*@?*", args[2])) {
00369 
00370         PutError(OperServ, nick, ERR_AKILLSYNTAX_1ARG, args[0], 0, 0);
00371         PutReply(OperServ, nick, RPL_AKILLHELP_2ARG, OperServ, listProper, 0);
00372         return RET_SYNTAX;
00373     }
00374 
00375     if (((p = strchr(args[2], '!')) && strchr(p+1, '!')) ||
00376         ((p = strchr(args[2], '%')) && strchr(p+1, '%')) ||
00377         (strchr(args[2], '@') < strchr(args[2], '!')) ||
00378         (((p = strchr(args[2], '@')) && strchr(p+1, '@')))) {
00379         sSend(":%s NOTICE %s :Your specified pattern \2%s\2 does not "
00380               "seem to be well-formed.",
00381                OperServ, from, args[2]);
00382         return RET_FAIL;
00383     }
00384 
00385     /*
00386      * find out how long this will last
00387      */
00388     if (!str_cmp(args[1], "add") || !str_cmp(args[1], "forever"))
00389         t = 0;
00390     else if (*args[1] == '-' || isdigit(*args[1]))
00391         t = atoi(args[1]) * 3600;
00392     else {
00393         PutError(OperServ, nick, ERR_AKILLSYNTAX_1ARG, args[0], 0, 0);
00394         PutReply(OperServ, nick, RPL_AKILLHELP_2ARG, OperServ, listProper, 0);
00395         return RET_SYNTAX;
00396     }
00397 
00398     if (!match(args[2], "...!..@...com")
00399         || !match(args[2], "...!..@...net")
00400         || !match(args[2], "...!..@...edu")
00401         || !match(args[2], "...!..@...org")) {
00402         sSend(":%s NOTICE %s :That %s is too broad.", OperServ,
00403               from, listProper);
00404         sSend(":%s GLOBOPS :%s attempts to set %s for %s", OperServ,
00405               from, listProper, args[2]);
00406         return RET_NOPERM;
00407     }
00408     if (!opFlagged(nick, permPrim)) {
00409         char nick[MAXBUF], user[MAXBUF], host[MAXBUF];
00410         if (t > (10800 * 1) || !t)
00411             t = 10800;
00412         sscanf(args[2], "%s!%s@%s", nick, user, host);
00413 
00414         if (strlen(args[2]) > 255 || strlen(nick) > 2*NICKLEN ||
00415                      strlen(user) > 2*USERLEN || strlen(host) > 2*HOSTLEN
00416                     || (strlen(nick)+strlen(user)+strlen(host)) > (NICKLEN+USERLEN+HOSTLEN+2)) {
00417             sSend(":%s NOTICE %s :Pattern too long.", OperServ, from);
00418             return RET_SYNTAX;
00419         }
00420 
00421         if ((strchr(host, '*') || strchr(host, '?'))
00422             && (strchr(user, '*') || strchr(user, '?'))
00423             && (strchr(nick, '*') || strchr(nick, '?'))) {
00424             sSend
00425                 (":%s NOTICE %s :Your %s access is restricted: you cannot wildcard more than one of the 2 parts of the mask (nick, user, or host).",
00426                  OperServ, from, listProper);
00427             return RET_NOPERM;
00428         }
00429     }
00430 
00431     strncpyzt(akreason, args[3], AKREASON_LEN);
00432     count = strlen(akreason);
00433 
00434     for (i = 4; i < numargs; i++) {
00435         if ((AKREASON_LEN - count) <= 0)
00436             break;
00437         count +=
00438             snprintf(akreason + count, AKREASON_LEN - count, " %s",
00439                      args[i]);
00440     }
00441     sSend(":%s NOTICE %s :Adding %s for %s for %d hours [%s]", OperServ,
00442           from, listProper, args[2], t / 3600, akreason);
00443     if (!addakill(t, args[2], from, akill_type, akreason))
00444         operlog->log(nick, log_type, args[2], LOGF_ON,
00445                      "%d: %s", t, akreason);
00446     return RET_OK_DB;
00447 }
00448 
00449 /************************************************************************/
00450 
00458 OCMD(os_tempakill)
00459 {
00460     char *from = nick->nick;
00461     char akreason[IRCBUF];
00462     int i, count;
00463     UserList *user;
00464     char addr[128];
00465 
00466     if (numargs < 3) {
00467         sSend(":%s NOTICE %s :Invalid syntax.  Try /msg %s help tempakill",
00468               OperServ, from, OperServ);
00469 
00470         return RET_SYNTAX;
00471     }
00472 
00473     if (strchr(args[1], '*') || strchr(args[1], '?')) {
00474         sSend(":%s NOTICE %s :No wildcards are allowed in a tempakill.",
00475               OperServ, from);
00476 
00477         return RET_EFAULT;
00478     }
00479 
00480     if (strchr(args[1], '!') || strchr(args[1], '@')) {
00481         sSend
00482             (":%s NOTICE %s :TempAKill should be placed on a nick or hostname, not a full mask.",
00483              OperServ, from);
00484 
00485         return RET_EFAULT;
00486     }
00487 
00488     if (strchr(args[1], '.'))
00489         snprintf(addr, 128, "*!*@%s", args[1]); /* they gave an address, not a nick */
00490     else {
00491         user = getNickData(args[1]);    /* they gave what we assume is a nickname */
00492         if (!user) {
00493             sSend(":%s NOTICE %s :No one by that nick is online.",
00494                   OperServ, from);
00495 
00496             return RET_EFAULT;
00497         }
00498         snprintf(addr, 128, "*!*@%s", user->host);
00499     }
00500 
00501     sSend(":%s NOTICE %s :Adding a temp akill for %s for 1 hour.",
00502           OperServ, from, addr);
00503 
00504     strncpyzt(akreason, args[2], AKREASON_LEN);
00505     count = strlen(akreason);
00506 
00507     for (i = 3; i < numargs; i++) {
00508         if ((AKREASON_LEN - count) <= 0)
00509             break;
00510         count +=
00511             snprintf(akreason + count, AKREASON_LEN - count, "%s%s",
00512                      i != 3 ? " " : "", args[i]);
00513     }
00514     addakill(3600, addr, from, A_AKILL, akreason);
00515     return RET_OK_DB;
00516 }
00517 
00518 
00519 /************************************************************************/
00520 
00526 OCMD(os_mode)
00527 {
00528     char *from = nick->nick;
00529     char modeString[IRCBUF];
00530     int on;
00531     int onarg;
00532     int i;
00533     ChanList *tmp;
00534     cBanList *tmpban;
00535     cNickList *tmpnick;
00536 
00537 
00538     if (numargs < 3) {
00539         sSend(":%s NOTICE %s :You must specify a channel and mode.",
00540               OperServ, from);
00541 
00542         return RET_SYNTAX;
00543     }
00544 
00545     tmp = getChanData(args[1]);
00546     on = 1;
00547     onarg = 3;
00548 
00549     if (!tmp) {
00550         sSend("%s NOTICE %s :No such channel.", OperServ, from);
00551 
00552         return RET_EFAULT;
00553     }
00554 
00555     for (i = 0; args[2][i]; i++) {
00556         switch (args[2][i]) {
00557         case '+':
00558             on = 1;
00559             break;
00560         case '-':
00561             on = 0;
00562             break;
00563 
00564         case 'b':
00565             if (on) {
00566                 tmpban = (cBanList *) oalloc(sizeof(cBanList));
00567 
00569                 if (strlen(args[onarg]) > sizeof(tmpban->ban))
00570                     args[onarg][sizeof(tmpban->ban) - 1] = '\0';
00571                 strcpy(tmpban->ban, args[onarg]);
00572                 addChanBan(tmp, tmpban);
00573             } else {
00574                 tmpban = getChanBan(tmp, args[onarg]);
00575                 if (tmpban)
00576                     delChanBan(tmp, tmpban);
00577             }
00578 
00579             onarg++;
00580             break;
00581 
00582         case 'i':
00583             SETCLR(tmp->modes, PM_I, on);
00584             break;
00585 
00586         case 'l':
00587             SETCLR(tmp->modes, PM_L, on);
00588             if ((on == 0) && tmp->reg)
00589                 tmp->reg->limit = 0;
00590             onarg++;
00591             break;
00592 
00593         case 'k':
00594             SETCLR(tmp->modes, PM_K, on);
00595             if ((on == 0) && tmp->reg)
00596                 tmp->reg->key[0] = 0;
00597             onarg++;
00598             break;
00599 
00600         case 'm':
00601             SETCLR(tmp->modes, PM_M, on);
00602             break;
00603 
00604         case 'n':
00605             SETCLR(tmp->modes, PM_N, on);
00606             break;
00607 
00608         case 'o':
00609             tmpnick = getChanUserData(tmp, getNickData(args[onarg]));
00610             onarg++;
00611             if (tmpnick == NULL)
00612                 continue;
00613 
00614             SETCLR(tmpnick->op, CHANOP, on);
00615             break;
00616 
00617         case 'p':
00618             SETCLR(tmp->modes, PM_P, on);
00619             break;
00620 
00621         case 's':
00622             SETCLR(tmp->modes, PM_S, on);
00623             break;
00624 
00625         case 't':
00626             SETCLR(tmp->modes, PM_T, on);
00627             break;
00628 
00629         case 'v':
00630             tmpnick = getChanUserData(tmp, getNickData(args[onarg]));
00631             onarg++;
00632             if (tmpnick == NULL)
00633                 continue;
00634 
00635             SETCLR(tmpnick->op, CHANVOICE, on);
00636             break;
00637         }
00638     }
00639 
00640     modeString[0] = 0;
00641 
00642     for (i = 2; i < onarg; i++) {
00643         strcat(modeString, args[i]);
00644         strcat(modeString, " ");
00645     }
00646 
00647     modeString[strlen(modeString) - 1] = 0;
00648     sSend(":%s MODE %s %s", ChanServ, args[1], modeString);
00649 
00650     sSend(":%s GLOBOPS :%s MODE %s (%s)", OperServ, from, args[1], modeString);
00651     return RET_OK;
00652 }
00653 
00654 /************************************************************************/
00655 
00656 /* RAW - cause services to send a RAW line, restricted to root because it */
00657 /*       has security implications.                                       */
00658 
00664 OCMD(os_raw)
00665 {
00666     char *from = nick->nick;
00667     char msg[IRCBUF];
00668     int i;
00669 
00670     strncpyzt(msg, args[1], sizeof(msg));
00671 
00672     for (i = 2; i < numargs; i++) {
00673         strcat(msg, " ");
00674         strcat(msg, args[i]);
00675     }
00676 
00677 #ifdef GLOBOPS_ON_RAW
00678     sSend(":%s GLOBOPS :%s used RAW: %s", OperServ, from, msg);
00679 #endif
00680 
00681     sSend("%s", msg);
00682     return RET_OK;
00683 }
00684 
00685 /************************************************************************/
00686 
00687 /* Shutdown - terminate services                                          */
00688 
00694 OCMD(os_shutdown)
00695 {
00696     char *from = nick->nick;
00697     char msg[IRCBUF];
00698     int i;
00699 
00700     if (numargs > 1) {
00701         strncpyzt(msg, args[1], sizeof(msg));
00702 
00703         for (i = 2; i < numargs; i++) {
00704             strcat(msg, " ");
00705             strcat(msg, args[i]);
00706         }
00707 
00708         sSend(":%s WALLOPS :!SHUTDOWN! From %s (%s)", myname, from, msg);
00709     } else
00710         sSend(":%s WALLOPS :!SHUTDOWN! From %s", myname, from);
00711 
00712     sshutdown(0);
00713     return RET_OK;
00714 }
00715 
00716 /************************************************************************/
00717 
00718 /* Rehash - reload services' config                                       */
00719 
00725 
00726 OCMD(os_reset)
00727 {
00728     char *from = nick->nick;
00729     char msg[IRCBUF];
00730     int i;
00731 
00732     if (numargs > 1) {
00733         strncpyzt(msg, args[1], sizeof(msg));
00734 
00735         for (i = 2; i < numargs; i++) {
00736             strcat(msg, " ");
00737             strcat(msg, args[i]);
00738         }
00739 
00740         sSend(":%s WALLOPS :Services has been rehashed by %s (%s)", myname,
00741               from, msg);
00742     } else
00743         sSend(":%s WALLOPS :Services has been rehashed by %s", myname,
00744               from);
00745 
00746     readConf();
00747     flush_help_cache();
00748     return RET_OK;
00749 }
00750 
00751 /************************************************************************/
00752 
00753 /* Jupe - jupe a server                                                   */
00754 /* jupe is restricted to root because it can inadvertently cause services */
00755 /* to be dropped...                                                       */
00756 
00761 OCMD(os_jupe)
00762 {
00763     char *from = nick->nick;
00764     time_t now = time(NULL);
00765     char msg[IRCBUF];
00766     int i;
00767 
00768     if (numargs < 2) {
00769         sSend(":%s NOTICE %s :Must specify a server to jupe", OperServ,
00770               from);
00771         return RET_SYNTAX;
00772     }
00773 
00774     if (numargs > 2) {
00775         strncpyzt(msg, args[2], sizeof(msg));
00776 
00777         for (i = 2; i < numargs; i++) {
00778             strcat(msg, " ");
00779             strcat(msg, args[i]);
00780         }
00781 
00782         sSend("SERVER %s 2 :Jupitered server [%s:%s] (%s)", args[1], from,
00783               ctime(&now), msg);
00784         sSend(":%s GLOBOPS :Server %s Jupitered by %s at %s (%s)", myname,
00785               args[1], from, ctime(&now), msg);
00786     } else {
00787         sSend("SERVER %s 2 :Jupitered server [%s:%s]", args[1], from,
00788               ctime(&now));
00789         sSend(":%s GLOBOPS :Server %s Jupitered by %s at %s", myname,
00790               args[1], from, ctime(&now));
00791     }
00792     return RET_OK;
00793 }
00794 
00795 /************************************************************************/
00796 
00803 /* ARGSUSED1 */
00804 OCMD(os_uptime)
00805 {
00806     char *from = nick->nick;
00807 
00808     time_t now;
00809     int days, hours, mins, seconds;
00810 
00811     now = time(NULL);
00812     now -= startup;
00813     days = (now / (24 * 3600));
00814     now %= (24 * 3600);
00815     hours = (now / 3600);
00816     now %= 3600;
00817     mins = (now / 60);
00818     now %= 60;
00819     seconds = now;
00820 
00821     sSend(":%s NOTICE %s :Services has been online for:\r\n"
00822           ":%s NOTICE %s :%i days, %i hours, %i minutes, and %i seconds",
00823           OperServ, from, OperServ, from, days, hours, mins, seconds);
00824     sSend(":%s NOTICE %s :(%ld chanserv commands interpreted by hack)",
00825           OperServ, from, counterOldCSFmt);
00826     return RET_OK;
00827 }
00828 
00829 /************************************************************************/
00830 
00835 /* ARGSUSED1 */
00836 OCMD(os_timers)
00837 {
00838     char *from = nick->nick;
00839 
00840     dumptimer(from);
00841     return RET_OK;
00842 }
00843 
00844 /************************************************************************/
00845 
00850 
00851 OCMD(os_sync)
00852 {
00853     void writeServicesTotals();
00854 
00855 #ifdef GLOBOP_ON_SYNC
00856     char *from = nick->nick;
00857 #endif
00858 
00859 #ifdef GLOBOP_ON_SYNC
00860     sSend(":%s GLOBOP :Saving all databases (%s)", OperServ, from);
00861 #endif
00862     strcpy(args[0], "save");
00863     sendToNickServ(nick, args, numargs);
00864     sendToChanServ(nick, args, numargs);
00865     sendToInfoServ(nick, args, numargs);
00866     strcpy(args[0], "savememo");
00867     sendToNickServ(nick, args, numargs);
00868     saveakills();
00869     writeServicesTotals();
00870 
00871     return RET_OK_DB;
00872 }
00873 
00874 
00875 /************************************************************************/
00876 
00888 OCMD(os_clonerule)
00889 {
00890     extern void saveTriggerData(void);
00891     char *from = nick->nick, *pCheck;
00892     int c = 0, ct = 0, minargs = 3;
00893     CloneRule *rule, orig;
00894     typedef enum
00895     { CLONEARG_NONE, CLONEARG_LIST, CLONEARG_INFO, CLONEARG_ADD,
00896         CLONEARG_INSERT, CLONEARG_SET, CLONEARG_DEL
00897     }
00898     clonerule_cmds;
00899 
00900     if (numargs > 1 && *args[1])
00901         if (!strcasecmp(args[1], "LIST")) {
00902             c = CLONEARG_LIST;
00903             --minargs;
00904         } else if (!strcasecmp(args[1], "INFO")) {
00905             c = CLONEARG_INFO;
00906         } else if (!strcasecmp(args[1], "ADD")) {
00907             c = CLONEARG_ADD;
00908         } else if (!strcasecmp(args[1], "INSERT")) {
00909             c = CLONEARG_INSERT;
00910         } else if (!strcasecmp(args[1], "SET")) {
00911             c = CLONEARG_SET;
00912             ++minargs;
00913         } else if (!strcasecmp(args[1], "DEL")) {
00914             c = CLONEARG_DEL;
00915         }
00916 
00917     if (numargs < minargs || c == CLONEARG_NONE) {
00918         sSend(":%s NOTICE %s :Syntax: CLONERULE <list|info|add|del|set>",
00919               OperServ, from);
00920         sSend(":%s NOTICE %s :        CLONERULE list [mask]", OperServ,
00921               from);
00922         sSend(":%s NOTICE %s :        CLONERULE info <rule#|mask>",
00923               OperServ, from);
00924         if (opFlagged(nick, OOPER | OCLONE) || isRoot(nick)) {
00925             sSend
00926                 (":%s NOTICE %s :        CLONERULE add <mask> [host trigger]",
00927                  OperServ, from);
00928             sSend
00929                 (":%s NOTICE %s :        CLONERULE insert <mask> [before #]",
00930                  OperServ, from);
00931             sSend
00932                 (":%s NOTICE %s :        CLONERULE set <rule#|mask> FLAGS <flag>",
00933                  OperServ, from);
00934             sSend
00935                 (":%s NOTICE %s :        CLONERULE set <rule#|mask> UTRIGGER <number|0>",
00936                  OperServ, from);
00937             sSend
00938                 (":%s NOTICE %s :        CLONERULE set <rule#|mask> HTRIGGER <number|0>",
00939                  OperServ, from);
00940             sSend
00941                 (":%s NOTICE %s :        CLONERULE set <rule#|mask> WARNMSG <message>",
00942                  OperServ, from);
00943             sSend(":%s NOTICE %s :        CLONERULE del <rule#|mask>",
00944                   OperServ, from);
00945         }
00946         return RET_SYNTAX;
00947     }
00948 
00949     if (!opFlagged(nick, OOPER | OCLONE) && !isRoot(nick)
00950         && (c > CLONEARG_INFO)) {
00951         sSend(":%s NOTICE %s :Permission denied.", OperServ, from);
00952         return RET_NOPERM;
00953     }
00954 
00955     switch (c) {
00956         /* cryptic code block starts here */
00957     case CLONEARG_INFO:
00958     case CLONEARG_LIST:
00959         if (c == CLONEARG_LIST)
00960             sSend(":%s NOTICE %s :***** \2Clone Trigger rules\2 *****",
00961                   OperServ, from);
00962         for (rule = first_crule, ct = 1; rule; rule = rule->next, ++ct)
00963             /* show an entry if the 'list' command had no extra args 
00964              * or if the argument IS the current mask */
00965             if ((numargs < 3)
00966                 || ((isdigit(*args[2]) && atoi(args[2]) == ct)
00967                     || !strcasecmp(args[2], rule->mask))) {
00968                 if (c == CLONEARG_LIST)
00969                     sSend(":%s NOTICE %s :\2%3d\2.  %-45s %3d %3d",
00970                           OperServ, from, ct, rule->mask, rule->trigger,
00971                           rule->utrigger);
00972                 else {
00973                     sSend
00974                         (":%s NOTICE %s :***** \2Persistent clone trigger rule information\2 *****",
00975                          OperServ, from);
00976                     sSend(":%s NOTICE %s :Mask: \2%s\2", OperServ, from,
00977                           rule->mask);
00978                     sSend
00979                         (":%s NOTICE %s :Username trigger level: \2%3d\2, Host Trigger level: \2%3d\2",
00980                          OperServ, from, rule->utrigger, rule->trigger);
00981                     sSend(":%s NOTICE %s :Flags: \2%s\2", OperServ, from,
00982                           flagstring(rule->flags, cloneset_bits));
00983                     sSend(":%s NOTICE %s :Kill Message: \2%s\2", OperServ,
00984                           from,
00985                           rule->kill_msg ? rule->kill_msg : "(default)");
00986                     sSend(":%s NOTICE %s :Warning Message: \2%s\2",
00987                           OperServ, from,
00988                           rule->warn_msg ? rule->warn_msg : "(none)");
00989                     sSend(":%s NOTICE %s :***** \2End of info\2 *****",
00990                           OperServ, from);
00991                 }
00992             }
00993         if (c == CLONEARG_LIST)
00994             sSend(":%s NOTICE %s :***** \2End of list\2 *****", OperServ,
00995                   from);
00996         return RET_OK;
00997         return RET_OK;
00998     case CLONEARG_ADD:
00999     case CLONEARG_INSERT:
01000         if (index(args[2], '!') || !index(args[2], '@')
01001             || !index(args[2], '.')) {
01002             sSend(":%s NOTICE %s :\2%s\2: Invalid mask.", OperServ, from,
01003                   args[2]);
01004             return RET_EFAULT;
01005         }
01006         if (GetCrule(args[2])) {
01007             sSend(":%s NOTICE %s :There's already a rule for that mask.",
01008                   OperServ, from);
01009             return RET_FAIL;
01010         }
01011         if (!(rule = NewCrule()))
01012             return RET_MEMORY;
01013         orig = *rule;
01014         rule->kill_msg = NULL;
01015         strncpyzt(rule->mask, args[2], sizeof(rule->mask));
01016         rule->trigger = 0;
01017         if (c == CLONEARG_ADD)
01018             if (numargs > 3 && *args[3] && isdigit(*args[3]))
01019                 rule->trigger = rule->utrigger = atoi(args[3]);
01020         if (!rule->trigger) {   /* keep defaults by default */
01021             rule->utrigger = 0;
01022             rule->trigger = 0;
01023         }
01024         rule->flags = DEFCLONEFLAGS;
01025         if (c == CLONEARG_ADD || numargs < 4)
01026             AddCrule(rule, -1);
01027         else {
01028             AddCrule(rule, atoi(args[3]));
01029             sSend(":%s NOTICE %s :--- inserting at point %d", OperServ,
01030                   from, atoi(args[3]));
01031         }
01032         sSend(":%s GLOBOPS :%s adding trigger rule for \2%s\2", OperServ,
01033               from, args[2]);
01034         UpdateCrule(orig, rule);
01035         saveTriggerData();
01036         return RET_OK_DB;
01037     case CLONEARG_SET:
01038         if (!(rule = GetCrule(args[2]))) {
01039             sSend(":%s NOTICE %s :\2%s\2: No such trigger default.",
01040                   OperServ, from, args[2]);
01041             return RET_NOTARGET;
01042         }
01043         if (numargs < 5) {
01044             sSend(":%s NOTICE %s :Set it to what?", OperServ, from);
01045             return RET_SYNTAX;
01046         }
01047 
01048         orig = *rule;
01049 
01050         if (!strcasecmp(args[3], "flags")) {
01051             if ((ct = flagbit(args[4], cloneset_bits)) < 0) {
01052                 sSend(":%s NOTICE %s :\2%s\2: No such cloneset flag.",
01053                       OperServ, from, args[4]);
01054                 return RET_EFAULT;
01055             }
01056             sSend(":%s NOTICE %s :\2%s\2 flag %s \2%s\2.", OperServ, from,
01057                   args[4],
01058                   (rule->flags & (1 << ct)) ? "removed from" : "added to",
01059                   rule->mask);
01060             sSend(":%s GLOBOPS :%s %s %s flag on trigger rule for \2%s\2",
01061                   OperServ, from,
01062                   rule->flags & (1 << ct) ? "cleared" : "set", args[4],
01063                   rule->mask);
01064             rule->flags ^= (1 << ct);
01065             UpdateCrule(orig, rule);
01066         } else if (!strcasecmp(args[3], "htrigger")) {
01067             if (!isdigit(*args[4])) {
01068                 sSend(":%s NOTICE %s :Invalid host trigger level.",
01069                       OperServ, from);
01070                 return RET_EFAULT;
01071             }
01072 
01073 
01074             if (!(pCheck = strchr(args[3], '@')) && atoi(args[4])) {
01075                 sSend(":%s NOTICE %s :Cannot set host trigger "
01076                       "rewrite unless rule contains a @.",
01077                       OperServ, from);
01078                 return RET_EFAULT;
01079             }
01080 
01081             if (pCheck && (strchr(pCheck, '*') || strchr(pCheck, '?'))
01082                 && atoi(args[4]) 
01083                 && !opFlagged(nick, OROOT | OVERRIDE)) 
01084             {
01085                 sSend(":%s NOTICE %s :Cannot set host trigger "
01086                       "rewrite with a wildcarded host.",
01087                       OperServ, from);
01088                 return RET_EFAULT;
01089             }
01090 
01091             sSend
01092                 (":%s GLOBOPS :%s set host trigger for rule of \2%s\2 %d->%d",
01093                  OperServ, from, rule->mask, rule->trigger, atoi(args[4]));
01094             rule->trigger = atoi(args[4]);
01095             sSend(":%s NOTICE %s :Trigger level is now %d.", OperServ,
01096                   from, rule->trigger);
01097             UpdateCrule(orig, rule);
01098         } else if (!strcasecmp(args[3], "utrigger")) {
01099             if (!isdigit(*args[4])) {
01100                 sSend(":%s NOTICE %s :Invalid user trigger level.",
01101                       OperServ, from);
01102                 return RET_EFAULT;
01103             }
01104             sSend
01105                 (":%s GLOBOPS :%s set user trigger for rule of \2%s\2 %d->%d",
01106                  OperServ, from, rule->mask, rule->utrigger,
01107                  atoi(args[4]));
01108             rule->utrigger = atoi(args[4]);
01109             sSend(":%s NOTICE %s :User trigger level is now %d.", OperServ,
01110                   from, rule->utrigger);
01111             UpdateCrule(orig, rule);
01112         } else if (!strcasecmp(args[3], "kill")
01113                    || !strcasecmp(args[3], "killmsg")) {
01114             char tmpbuf[8192] = "";
01115             if (args[4][0] == '\0' || !strcasecmp(args[4], "none")) {
01116                 if (rule->kill_msg)
01117                     FREE(rule->kill_msg);
01118                 rule->kill_msg = NULL;
01119                 sSend(":%s NOTICE %s :Kill message cleared.", OperServ,
01120                       from);
01121             } else {
01122                 parse_str(args, numargs, 4, tmpbuf, IRCBUF);
01123                 if (strlen(tmpbuf) > MEMOLEN) {
01124                     sSend
01125                         (":%s NOTICE %s :Kill message cannot exceed %d characters.",
01126                          OperServ, from, MEMOLEN);
01127                     return RET_EFAULT;
01128                 }
01129                 if (rule->kill_msg)
01130                     FREE(rule->kill_msg);
01131                 rule->kill_msg = strdup(tmpbuf);
01132                 if (!rule->kill_msg) {
01133                     logDump(corelog,
01134                             "Error allocating (%d) bytes of memory for clonerule kill message. (%s!%s@%s)",
01135                             strlen(tmpbuf), from, nick->user, nick->host);
01136                     sSend
01137                         (":%s GLOBOPS :Error allocating (%d) bytes of memory for clonerule kill message. (%s!%s@%s)",
01138                          NickServ, strlen(tmpbuf), from, nick->user,
01139                          nick->host);
01140                     return RET_MEMORY;
01141                 }
01142                 sSend(":%s NOTICE %s :Kill message set.", OperServ, from);
01143             }
01144         } else if (!strcasecmp(args[3], "warn")
01145                    || !strcasecmp(args[3], "warnmsg")) {
01146             char tmpbuf[8192] = "";
01147             if (args[4][0] == '\0' || !strcasecmp(args[4], "none")) {
01148                 if (rule->warn_msg)
01149                     FREE(rule->warn_msg);
01150                 rule->warn_msg = NULL;
01151                 sSend(":%s NOTICE %s :Warning message cleared.", OperServ,
01152                       from);
01153             } else {
01154                 parse_str(args, numargs, 4, tmpbuf, IRCBUF);
01155                 if (strlen(tmpbuf) > MEMOLEN) {
01156                     sSend
01157                         (":%s NOTICE %s :Warning message cannot exceed %d characters.",
01158                          OperServ, from, MEMOLEN);
01159                     return RET_EFAULT;
01160                 }
01161                 if (rule->warn_msg)
01162                     FREE(rule->warn_msg);
01163                 rule->warn_msg = strdup(tmpbuf);
01164                 if (!rule->warn_msg) {
01165                     logDump(corelog,
01166                             "Error allocating (%d) bytes of memory for clonerule warn message. (%s!%s@%s)",
01167                             strlen(tmpbuf), from, nick->user, nick->host);
01168                     sSend
01169                         (":%s GLOBOPS :Error allocating (%d) bytes of memory for clonerule arn message. (%s!%s@%s)",
01170                          NickServ, strlen(tmpbuf), from, nick->user,
01171                          nick->host);
01172                     return RET_MEMORY;
01173                 }
01174                 sSend(":%s NOTICE %s :Warning message set.", OperServ,
01175                       from);
01176             }
01177         } else {
01178             sSend
01179                 (":%s NOTICE %s :Valid settings are: FLAGS, HTRIGGER, UTRIGGER, KILLMSG, and WARNMSG",
01180                  OperServ, from);
01181             sSend(":%s NOTICE %s :Valid flags are: %s", OperServ, from,
01182                   flagstring(~0, cloneset_bits));
01183             return RET_OK;
01184         }
01185         saveTriggerData();
01186         return RET_OK_DB;
01187     case CLONEARG_DEL:
01188         if (!(rule = GetCrule(args[2]))) {
01189             sSend(":%s NOTICE %s :\2%s\2: No such trigger default.",
01190                   OperServ, from, args[2]);
01191             return RET_NOTARGET;
01192         }
01193         RemoveCrule(rule);
01194         sSend(":%s NOTICE %s :Trigger rule for %s removed.", OperServ,
01195               from, rule->mask);
01196         sSend(":%s GLOBOPS :%s removing trigger rule for \2%s\2", OperServ,
01197               from, rule->mask);
01198         if (rule->kill_msg)
01199             FREE(rule->kill_msg);
01200         if (rule->warn_msg)
01201             FREE(rule->warn_msg);
01202         FREE(rule);
01203         saveTriggerData();
01204         return RET_OK_DB;
01205     }
01206     sSend(":%s NOTICE %s :Huh?", OperServ, from);
01207     return RET_SYNTAX;
01208 }
01209 
01210 /************************************************************************/
01211 
01216 OCMD(os_trigger)
01217 {
01218     char *from = nick->nick;
01219     char user[USERLEN];
01220     char host[HOSTLEN];
01221     HostClone *hc;
01222     UserClone *uc;
01223     int i;
01224 
01225     if (numargs < 2) {
01226         sSend(":%s NOTICE %s :Default host trigger: \2%i\2", OperServ, from,
01227             DEFHOSTCLONETRIGGER);
01228         sSend(":%s NOTICE %s :Default user trigger: \2%i\2", OperServ, from,
01229             DEFUSERCLONETRIGGER);
01230         sSend(":%s NOTICE %s :/OPERSERV trigger list' to show "
01231               "any outstanding alerts.", OperServ, from);
01232 
01233         return RET_OK;
01234     }
01235 
01236     if (numargs >= 2 && !str_cmp(args[1], "list")) {
01237         listCloneAlerts(nick);
01238 
01239         return RET_OK;
01240     }
01241 
01242     /*
01243      * If they specified a user as well as a host handle it right.
01244      * If they only asked about a host, just use that one.
01245      */
01246     if (index(args[1], '@')) {
01247         user[0] = host[0] = '\0';
01248         sscanf(args[1], "%[^@]@%s", user, host);
01249 
01250         hc = getCloneData(host);
01251         if (hc != NULL)
01252             uc = getUserCloneData(hc, user);
01253         else
01254             uc = NULL;
01255 
01256         if ((uc == NULL) || (hc == NULL)) {
01257             sSend(":%s NOTICE %s :No such user@host (%s@%s), ", OperServ,
01258                   from, user, host);
01259 
01260             return RET_NOTARGET;
01261         }
01262 
01263         if (numargs < 3) {
01264             sSend(":%s NOTICE %s :%s@%s has %d/%d clones (total/trigger)",
01265                   OperServ, from, user, host, uc->clones, uc->trigger);
01266 
01267             return RET_OK;
01268         }
01269 
01270         i = atoi(args[2]);
01271         if (i <= 0) {
01272             sSend(":%s NOTICE %s :Please specify a proper trigger level",
01273                   OperServ, from);
01274 
01275             return RET_EFAULT;
01276         }
01277 
01278         uc->trigger = i;
01279         sSend(":%s GLOBOPS :%s@%s retriggered to %d by %s", OperServ, user,
01280               host, i, from);
01281 
01282         return RET_OK_DB;
01283     }
01284 
01285     /*
01286      * fallthrough case, is just a host specified.
01287      */
01288     strncpyzt(host, args[1], HOSTLEN);
01289 
01290     hc = getCloneData(host);
01291     if (hc == NULL) {
01292         sSend(":%s NOTICE %s :%s does not exist", OperServ, from, host);
01293 
01294         return RET_NOTARGET;
01295     }
01296 
01297     if (numargs < 3) {
01298         sSend(":%s NOTICE %s :%s has %i/%i clones (total/trigger)",
01299               OperServ, from, host, hc->clones, hc->trigger);
01300 
01301         return RET_OK;
01302     }
01303 
01304     i = atoi(args[2]);
01305 
01306     if (i <= 0) {
01307         sSend(":%s NOTICE %s :Please specify a proper trigger level",
01308               OperServ, from);
01309 
01310         return RET_EFAULT;
01311     }
01312 
01313     hc->trigger = i;
01314     sSend(":%s GLOBOPS :%s retriggered to %i by %s", OperServ, host, i,
01315           from);
01316     return RET_OK_DB;
01317 }
01318 
01319 /************************************************************************/
01320 
01325 
01326 OCMD(os_match)
01327 {
01328     char *from = nick->nick;
01329 
01330     if (numargs > 2)
01331         sSend(":%s NOTICE %s :match(%s, %s) returns %i", OperServ, from,
01332               args[1], args[2], match(args[1], args[2]));
01333     return RET_OK;
01334 }
01335 
01336 /************************************************************************/
01337 
01346 OCMD(os_cloneset)
01347 {
01348     char *from = nick->nick;
01349     HostClone *hc;
01350 
01351     if (numargs < 2) {
01352         sSend(":%s NOTICE %s :You must specify at least an address",
01353               OperServ, from);
01354         return RET_SYNTAX;
01355     }
01356 
01357     hc = getCloneData(args[1]);
01358     if (hc == NULL) {
01359         sSend(":%s NOTICE %s :No such host %s", OperServ, from, args[1]);
01360 
01361         return RET_NOTARGET;
01362     }
01363 
01364     if (numargs < 3) {
01365         sSend(":%s NOTICE %s :%s has flags:%s%s.", OperServ, from, args[1],
01366               ((hc->flags & CLONE_KILLFLAG) ? " Auto Remove" : ""),
01367               ((hc->flags & CLONE_IGNOREFLAG) ? "Ignore all" : ""));
01368     } else {
01369         if (!strcasecmp(args[2], "kill"))
01370             hc->flags |= CLONE_KILLFLAG;
01371         else if (!strcasecmp(args[2], "-kill"))
01372             hc->flags &= ~CLONE_KILLFLAG;
01373         else if (!strcasecmp(args[2], "ok"))
01374             hc->flags |= CLONE_OK;
01375         else if (!strcasecmp(args[2], "-ok"))
01376             hc->flags &= ~CLONE_OK;
01377         else if (!strcasecmp(args[2], "ignore"))
01378             hc->flags |= CLONE_IGNOREFLAG;
01379         else if (!strcasecmp(args[2], "-ignore"))
01380             hc->flags &= ~CLONE_IGNOREFLAG;
01381         else {
01382             sSend(":%s NOTICE %s :Unknown flag %s", OperServ, from,
01383                   args[2]);
01384             return RET_EFAULT;
01385         }
01386 
01387         sSend(":%s GLOBOPS :%s changed cloneflags for %s (now %s%s)",
01388               OperServ, from, hc->host,
01389               ((hc->flags & CLONE_KILLFLAG) ? " Auto Remove" : ""),
01390               ((hc->flags & CLONE_IGNOREFLAG) ? "Ignore all" : ""));
01391         return RET_OK_DB;
01392     }
01393     return RET_OK;
01394 }
01395 
01396 /**************************************************************************
01397  * The existence of this command and its syntax is SRA privileged         *
01398  * information.                                                           *
01399  *************************************************************************/
01400 OCMD(os_remsra)
01401 {
01402     char NickGetEnc(RegNickList *);
01403     char *from = nick->nick;
01404     RegNickList *root;
01405 
01406     if (!nick->reg)
01407         return RET_NOPERM;
01408 
01409     if ((numargs < 3)
01410         || (!(nick->reg->opflags & OREMROOT))
01411         || !Valid_pw(args[2], nick->reg->password, NickGetEnc(nick->reg))) {
01412         operlog->log(nick, OS_REMSRA, (numargs > 1 ? args[1] : ""), 0,
01413                      "failed");
01414         sSend(":%s NOTICE %s :Unknown command %s.\r\n"
01415               ":%s NOTICE %s :Please try /msg %s HELP", OperServ, from,
01416               args[0], OperServ, from, OperServ);
01417         return RET_NOPERM;
01418     }
01419 
01420     root = getRegNickData(args[1]);
01421     if (!root)
01422         return RET_NOPERM;
01423     delOpData(root);
01424     root->opflags &= ~(OROOT | OPROT);
01425     if (root->opflags)
01426         addOpData(root);
01427     sSend(":%s NOTICE %s :Rootflags for %s removed", OperServ, from,
01428           args[1]);
01429     operlog->log(nick, OS_REMSRA, (numargs > 1 ? args[1] : ""));
01430     return RET_OK_DB;
01431 }
01432 
01437 /**************************************************************************
01438  * List those with the +g oper flag who can use getrealpass to help users *
01439  * This is deprecated and will eventually be removed.                     *
01440  **************************************************************************/
01441 OCMD(os_grpop)
01442 {
01443     char *from = nick->nick;
01444     RegNickList *grpop;
01445     int bucket;
01446 
01447     if (!nick->reg)
01448         return RET_NOPERM;
01449 
01450     if ((numargs < 2) || (!strcasecmp(args[1], "list"))) {
01451         sSend(":%s NOTICE %s :Now listing GRP-Ops:", OperServ, from);
01452 
01453         for (bucket = 0; bucket < NICKHASHSIZE; bucket++) {
01454             for (grpop = LIST_FIRST(&RegNickHash[bucket]); grpop;
01455                  grpop = LIST_NEXT(grpop, rn_lst))
01456                 if (grpop->opflags & OGRP)
01457                     sSend(":%s NOTICE %s :%s", OperServ, from,
01458                           grpop->nick);
01459         }
01460         return RET_OK;
01461     }
01462 
01463     if (!isRoot(nick)) {
01464         sSend(":%s NOTICE %s :Permission denied.", OperServ, from);
01465         return RET_NOPERM;
01466     }
01467 
01468     if ((!strcasecmp(args[1], "convert"))) {
01469         sSend(":%s NOTICE %s :Now converting GRP-Ops to new format.",
01470               OperServ, from);
01471 
01472         for (bucket = 0; bucket < NICKHASHSIZE; bucket++) {
01473             for (grpop = LIST_FIRST(&RegNickHash[bucket]); grpop;
01474                  grpop = LIST_NEXT(grpop, rn_lst))
01475                 if (grpop->flags & NGRPOP) {
01476                     grpop->flags &= ~NGRPOP;
01477                     grpop->opflags |= OGRP;
01478                     sSend(":%s NOTICE %s :%s", OperServ, from,
01479                           grpop->nick);
01480                 }
01481         }
01482         return RET_OK_DB;
01483     }
01484 
01485     sSend(":%s NOTICE %s :-- This command is deprecated, use setop.",
01486           OperServ, from);
01487 
01488     if (!strcasecmp(args[1], "del")) {
01489         if (numargs != 3) {
01490             sSend
01491                 (":%s NOTICE %s :Improper format.  Try /msg %s help grpop",
01492                  OperServ, from, OperServ);
01493             return RET_SYNTAX;
01494         }
01495         if ((grpop = getRegNickData(args[2])) != NULL) {
01496             grpop->opflags &= ~OGRP;
01497             if (!grpop->opflags)
01498                 delOpData(grpop);
01499             sSend(":%s NOTICE %s :%s no longer flagged GRP-op.", OperServ,
01500                   from, args[2]);
01501         } else {
01502             sSend
01503                 (":%s NOTICE %s :Target nickname, %s, is not registered. No changes made.",
01504                  OperServ, from, args[2]);
01505             return RET_NOTARGET;
01506         }
01507     } else if (!strcasecmp(args[1], "add")) {
01508         if (numargs != 3) {
01509             sSend
01510                 (":%s NOTICE %s :Improper format.  Try /msg %s help grpop",
01511                  OperServ, from, OperServ);
01512             return RET_SYNTAX;
01513         }
01514         if ((grpop = getRegNickData(args[2])) != 0) {
01515             if (!grpop->opflags)
01516                 addOpData(grpop);
01517             grpop->opflags |= OGRP;
01518             sSend(":%s NOTICE %s :%s flagged GRP-op.", OperServ, from,
01519                   args[2]);
01520         } else {
01521             sSend
01522                 (":%s NOTICE %s :Target nickname, %s, is not registered. No changes made.",
01523                  OperServ, from, args[2]);
01524             return RET_NOTARGET;
01525         }
01526     }
01527     return RET_OK_DB;
01528 }
01529 
01530 /************************************************************************/
01531 
01538 OCMD(os_override)
01539 {
01540     UserList *tmp = nick;
01541     char *orig_cmd, *service;
01542     char stuff[IRCBUF + 25];
01543     int i = 0;
01544 
01545     if (!nick)
01546         return RET_NOPERM;
01547 
01548     if (!isOper(nick) || os_user_override) {
01549         sSend(":%s NOTICE %s :I don't think so!", ChanServ, nick->nick);
01550         return RET_INVALID;
01551     }
01552 
01553     if ((!nick->reg || !(nick->reg->opflags & OACC)) && !isRoot(nick)) {
01554         sSend(":%s NOTICE %s "
01555               ":You do not have the proper flags to use this command.",
01556               OperServ, nick->nick);
01557         return RET_NOPERM;
01558     }
01559 
01560     if (numargs < 3) {
01561         sSend
01562             (":%s NOTICE %s :Override user access restrictions, but for what service and what command?",
01563              ChanServ, nick->nick);
01564         return RET_SYNTAX;
01565     }
01566 
01567     orig_cmd = args[0];
01568     service = args[1];
01569     for (i = 0; i < (numargs - 2); i++)
01570         args[i] = args[i + 2];
01571     args[numargs - 1] = NULL;
01572     numargs -= 2;
01573     os_user_override = nick;
01574 
01575     parse_str(args, numargs, 0, stuff, IRCBUF);
01576     operlog->log(nick, OS_OVERRIDE, args[1], LOGF_OK, "%s", stuff);
01577 
01578     if (!strncasecmp(service, OperServ, strlen(OperServ)))
01579         sendToOperServ(tmp, args, numargs);
01580     else if (!strncasecmp(service, NickServ, strlen(NickServ)))
01581         sendToNickServ(tmp, args, numargs);
01582     else if (!strncasecmp(service, ChanServ, strlen(ChanServ)))
01583         sendToChanServ(tmp, args, numargs);
01584     else if (!strncasecmp(service, MemoServ, strlen(MemoServ)))
01585         sendToMemoServ(tmp, args, numargs);
01586     else if (!strncasecmp(service, InfoServ, strlen(InfoServ)))
01587         sendToInfoServ(tmp, args, numargs);
01588     else if (!strncasecmp(service, GameServ, strlen(GameServ)))
01589         sendToGameServ(tmp, args, numargs);
01590     else
01591         sSend(":%s NOTICE %s :No such service.", OperServ, nick->nick);
01592     os_user_override = NULL;
01593     return RET_KILLED;          /* We really don't know if they're still alive or not */
01594 }
01595 
01596 /************************************************************************/
01597 
01599 OCMD(os_strike)
01600 {
01601 #ifdef USE_SQL
01602     char *tnick, *p, *mask;
01603     char query_ln[(2 * (NICKLEN + 1)) + 512];
01604 
01605     if (!isRoot(nick)) {
01606         sSend
01607             (":%s NOTICE %s :This is a test command and requires root acess currently.",
01608              OperServ, nick->nick);
01609         return RET_NOPERM;
01610     }
01611 
01612     if (numargs < 2 || !strchr(args[1], '!') || !strchr(args[1], '@')
01613         || !strchr(args[1], '.')) {
01614         sSend(":%s NOTICE %s :Usage: /operserv strike nick!user@host",
01615               OperServ, nick->nick);
01616         return RET_SYNTAX;
01617     }
01618 
01619     tnick = args[1];
01620     p = strchr(args[1], '!');
01621     *p = '\0';
01622     mask = p + 1;
01623 
01624     sprintf(query_ln,
01625             "INSERT into strikes (setby, nick, mask, status, auth_num) "
01626             "VALUES (\'%s\', \'%s\', \'%s\', 0, %ld);", nick->nick, tnick,
01627             mask, (time(NULL) / 100000) ^ nick->nick[0]);
01628     if (PQsendQuery(dbConn, query_ln) < 0) {
01629         sSend
01630             (":%s NOTICE %s :Services is busy at the moment, please try again in a bit.",
01631              OperServ, nick->nick);
01632         return RET_OK_DB;
01633     }
01634 #else
01635     sSend(":%s NOTICE %s :This test command is not compiled in.", OperServ,
01636           nick->nick);
01637 #endif
01638     return RET_OK;
01639 }
01640 
01641 /************************************************************************/
01642 
01649 OCMD(os_heal)
01650 {
01651     const char *from = nick->nick;
01652     UserList *tarNick;
01653 
01654     if (numargs < 2) {
01655         sSend(":%s NOTICE %s :Syntax Error.", OperServ, from);
01656         sSend(":%s NOTICE %s :Usage: /msg %s HEAL <nick>", OperServ, from,
01657               OperServ);
01658         return RET_FAIL;
01659     }
01660 
01661     if (!(tarNick = getNickData(args[1]))) {
01662         sSend(":%s NOTICE %s :No user by that name.", OperServ, from);
01663         return RET_NOTARGET;
01664     }
01665 
01666     sSend(":%s HEAL %s", NickServ, args[1]);
01667     tarNick->oflags &= ~(NISAHURT);
01668     return RET_OK;
01669 }
01670 
01671 /**************************************************************************/
01672 
01673 /* Debugging command */
01674 
01675 OCMD(os_nixghost) {
01676     if (numargs < 2)
01677         return RET_SYNTAX;
01678     if (isGhost(args[1])) {
01679         sSend(":%s QUIT :nixxed", args[1]);
01680     }
01681 }
01682 
01683 /************************************************************************/
01684 
01685 /* $Id: operserv.c,v 1.3 2003/10/19 20:26:27 Mysid Exp $ */

Generated at Sat Oct 25 20:56:09 2003 for Services using Doxygen.
Services Copyr. 1996-2001 Chip Norkus, Max Byrd, Greg Poma, Michael Graff, James Hess, Dafydd James. All rights reserved See LICENSE for licensing information.