diff -urdBN emech-2.8.1/README.SERVICES emech-2.8.1-services/README.SERVICES --- emech-2.8.1/README.SERVICES Thu Jan 1 10:00:00 1970 +++ emech-2.8.1-services/README.SERVICES Tue Dec 14 00:00:00 1999 @@ -0,0 +1,65 @@ +*** Please keep in mind this is BETA code.. *** + +Usage: + +-SERVICE [channel] +or +-SERVICE LIST [|LOGIN] + +There are 2 facilities supported by this SERVICE command.. One is +for sending requests upon logging into a server, and the other is +for requesting channel-op status from another channel-op. Both can +have multiple requests specified, so authorizing to many different +services is possible. + +With multiple requests upon logging in, there is no flood control, +so if you have to many requests, you will most likely flood the bot +off IRC before you even get to see it. Use your judgement. + +With the channel-op request, things are different. The bot will +only send a request if it detects that the recipent of the message +is present and opped. If there are multiple requests involved, the +bot will cycle the list, with one request about every 10 seconds, +until it has been opped. + +This semi-intellegent facility also makes it reasonably safe to gain +channel-ops from other standard bots, like eggdrop. (reason: if +somebody dupes a botnick, and gets opped as well, your channel +security is already screwed. ;) Again, use your judgement. + +Examples: +~~~~~~~~~ +1) Sending a service request upon login: + + -SERVICE ADD W@Channels2.Undernet.Org LOGIN #mychan mypass + -SERVICE ADD X@Channels.Undernet.Org LOGIN #myotherchan coolpass + + Everytime it connects to a server, it will send + 'LOGIN #mychan mypass' to 'W@Channels2.Undernet.Org' and + 'LOGIN #myotherchan coolpass' to 'X@Channels.Undernet.Org' + +2) Sending a need ops request upon joining a channel: + + -SERVICE ADD #mychannel W OP #mychannel $nick + + This will send 'OP #mychannel ' to W as soon as the + bot joins the channel #mychannel, on the condition that W is + actually *present* and *opped*. + The '$nick' is used to substitute the bots current nick + at the time. + +3) Displaying which services requests are set: + + -SERVICE LIST (displays all services requests) + -SERVICE LIST LOGIN (displays LOGIN services requests) + -SERVICE LIST #mychannel (displays #mychannel NEEDOP requests) + +4) Deleting a service request: + + -SERVICE DEL W@Channels2.Undernet.Org LOGIN #mychan mypass + + will delete the first service used in example 1. + + -SERVICE DEL #mychannel W OP #mychannel $nick + + will delete the service used in example 2. \ No newline at end of file diff -urdBN emech-2.8.1/src/cfgfile.c emech-2.8.1-services/src/cfgfile.c --- emech-2.8.1/src/cfgfile.c Mon Apr 2 04:26:12 2001 +++ emech-2.8.1-services/src/cfgfile.c Wed Apr 4 17:10:46 2001 @@ -737,6 +737,33 @@ #endif /* ALIASES */ +void cfg_service(char *args) +{ + char *to,*msg; + aService **servicesptr; + + to = get_token(&args,TOC); + msg = args; + + if (!msg || !*msg) return; + + if (cfgChan) + servicesptr = &(cfgChan->ServicesList); + else + servicesptr = &(current->ServicesList); + + if (find_service(servicesptr,to,msg)) + { + printf("init: Service %s already exists (ignored)\n",to); + return; + } + + if (!add_service(servicesptr,to,msg)) + printf("init: Failed to add service %s",to); + + return; +} + typedef struct CommandStruct { char *name; @@ -788,6 +815,7 @@ #ifdef ALIASES { "ALIAS", cfg_alias, 0 }, #endif /* ALIASES */ +{ "SERVICE", cfg_service, 0 }, { NULL, NULL, 0 } }; diff -urdBN emech-2.8.1/src/channel.c emech-2.8.1-services/src/channel.c --- emech-2.8.1/src/channel.c Mon Apr 2 04:26:12 2001 +++ emech-2.8.1-services/src/channel.c Wed Apr 4 17:11:02 2001 @@ -109,6 +109,43 @@ } } +void needop_via_msg(char *channel) +{ + aChan *Chan; + aService *tmpserviceptr; + int cycled; + + if ((Chan = find_channel(channel,CH_ACTIVE)) == NULL) + return; + + if (Chan->ServicesList == NULL) + return; + + if (is_opped(current->nick,channel)) + return; + + tmpserviceptr = Chan->nextservice; + + cycled = 0; + while (!cycled) + { + if (tmpserviceptr == NULL) + tmpserviceptr = Chan->ServicesList; + + if (is_opped(tmpserviceptr->to,channel)) + { + send_to_server("PRIVMSG %s :%s",tmpserviceptr->to, + subststrvar(tmpserviceptr->msg)); + Chan->nextservice = tmpserviceptr->next; + return; + } + + tmpserviceptr = tmpserviceptr->next; + if (tmpserviceptr == Chan->nextservice) + cycled = 1; + } +} + void check_shit(void) { aChanUser *User; diff -urdBN emech-2.8.1/src/combot.c emech-2.8.1-services/src/combot.c --- emech-2.8.1/src/combot.c Mon Apr 2 04:26:12 2001 +++ emech-2.8.1-services/src/combot.c Wed Apr 4 17:11:43 2001 @@ -31,6 +31,8 @@ #ifdef LINKING aLinkConf *lc; #endif /* LINKING */ + aService *tmpserviceptr; + VarStruct *Vars,*CV; aServer *sp; aChan *Chan; @@ -105,6 +107,13 @@ tofile(sf,"ircname %s\n",bot->ircname); if (bot->modes[0]) tofile(sf,"modes %s\n",bot->modes); + tmpserviceptr = bot->ServicesList; + while (tmpserviceptr) + { + tofile(sf, "service %s %s\n", + tmpserviceptr->to,tmpserviceptr->msg); + tmpserviceptr = tmpserviceptr->next; + } if (bot->cmdchar != DEFAULTCMDCHAR) tofile(sf,"cmdchar %c\n",bot->cmdchar); tofile(sf,"userfile %s\n\n",bot->Userfile); @@ -147,6 +156,13 @@ if ((Chan->active == CH_OLD) && (!Chan->rejoin)) continue; tofile(sf,"channel %s\n",Chan->name,(Chan->key && *Chan->key) ? Chan->key : ""); + tmpserviceptr = Chan->ServicesList; + while (tmpserviceptr) + { + tofile(sf, "service %s %s\n", + tmpserviceptr->to,tmpserviceptr->msg); + tmpserviceptr = tmpserviceptr->next; + } Vars = Chan->Vars; for(j=0;VarName[j].name;j++) { @@ -213,6 +229,58 @@ * Bot adding and killing */ +int add_service(aService **l_list, char *to, char *msg) +{ + aService *tmpserviceptr; + + if ((tmpserviceptr = (aService*)MyMalloc(sizeof(aService))) == NULL) + return(FALSE); + + tmpserviceptr->next = *l_list; + mstrcpy(&tmpserviceptr->to,to); + mstrcpy(&tmpserviceptr->msg,msg); + *l_list = tmpserviceptr; + return(TRUE); +} + +int delete_service(aService **l_list, aService *service) +{ + aService **old; + + for(old=l_list;*old;old=&(**old).next) + if (*old == service) + { + *old = service->next; + MyFree(&service->to); + MyFree(&service->msg); + MyFree((char **)&service); + return(TRUE); + } + return(FALSE); +} + +aService *find_service(aService **l_list, char *to, char *msg) +{ + aService *tmpserviceptr; + + tmpserviceptr = *l_list; + + while (tmpserviceptr) + { + if (!strcasecmp(to,tmpserviceptr->to)) + if (!strcasecmp(msg,tmpserviceptr->msg)) + return(tmpserviceptr); + tmpserviceptr = tmpserviceptr->next; + } + return(NULL); +} + +void delete_all_services(aService *ServicesList) +{ + while (ServicesList) + delete_service(&ServicesList,ServicesList); +} + aBot *add_bot(char *nick) { #ifdef MULTI @@ -469,6 +537,7 @@ delete_seen(); MyFree(¤t->seenfile); #endif /* SEEN */ + delete_all_services(current->ServicesList); #ifdef DEBUG debug("(signoff) Removing userlist...\n"); @@ -770,6 +839,12 @@ if (!Chan->bot_is_op && Chan->active == CH_ACTIVE) needop(Chan->name); #endif /* LINKING */ + if ((now - Chan->lastservice) > 10) + { + if ((usermode(Chan->name,current->nick) & CU_CHANOP) == 0) + needop_via_msg(Chan->name); + Chan->lastservice = now; + } } if (!x) { diff -urdBN emech-2.8.1/src/commands.c emech-2.8.1-services/src/commands.c --- emech-2.8.1/src/commands.c Mon Apr 2 04:26:12 2001 +++ emech-2.8.1-services/src/commands.c Wed Apr 4 17:11:59 2001 @@ -20,6 +20,186 @@ */ #include "config.h" +void do_service(char *from, char *to, char *rest, int cmdlevel) +{ + char *scmd,*schan,*sto,*smsg; + aChan *tmpchanptr; + aService **servicesptr,*tmpserviceptr; + + scmd = get_token(&rest," "); + + if (!scmd || !*scmd) + goto usage; + + if (!strcasecmp(scmd,"ADD")) + { + sto = get_token(&rest," "); + + if (!sto || !*sto) + goto usage; + + if (ischannel(sto)) + { + schan = sto; + sto = get_token(&rest," "); + + if ((tmpchanptr = find_channel(schan,CH_ANY)) == NULL) + { + send_to_user(from,"I have no knowledge of channel %s",schan); + return; + } + + servicesptr = &tmpchanptr->ServicesList; + } + else + { + servicesptr = ¤t->ServicesList; + } + + smsg = rest; + + if (!smsg || !*smsg) + goto usage; + + if (find_service(servicesptr,sto,smsg)) + { + send_to_user(from,"Service definition already exists."); + return; + } + + if (!add_service(servicesptr,sto,smsg)) + send_to_user(from,"Error adding service."); + else + send_to_user(from,"Service added successfully."); + + return; + } + else + if (!strcasecmp(scmd,"DEL")) + { + sto = get_token(&rest," "); + + if (!sto || !*sto) + goto usage; + + if (ischannel(sto)) + { + schan = sto; + sto = get_token(&rest," "); + + if ((tmpchanptr = find_channel(schan,CH_ANY)) == NULL) + { + send_to_user(from,"I have no knowledge of channel %s",schan); + return; + } + + servicesptr = &tmpchanptr->ServicesList; + } + else + { + servicesptr = ¤t->ServicesList; + } + + smsg = rest; + + if (!smsg || !*smsg) + goto usage; + + if ((tmpserviceptr = find_service(servicesptr,sto,smsg)) == NULL) + { + send_to_user(from,"Service definition specified doesn't exist!"); + return; + } + + if (!delete_service(servicesptr,tmpserviceptr)) + send_to_user(from,"Error deleting service."); + else + send_to_user(from,"Service deleted."); + + return; + } + else + if (!strcasecmp(scmd,"LIST")) + { + sto = get_token(&rest," "); + + if (!sto || !*sto) + { + send_to_user(from,"Services List:"); + send_to_user(from," LOGIN:"); + + tmpserviceptr = current->ServicesList; + while (tmpserviceptr) + { + send_to_user(from," TO: %s, MSG: %s", + tmpserviceptr->to,tmpserviceptr->msg); + tmpserviceptr = tmpserviceptr->next; + } + + send_to_user(from,""); + + tmpchanptr = current->Channels; + + while (tmpchanptr) + { + send_to_user(from," NEEDOP for %s:",tmpchanptr->name); + + tmpserviceptr = tmpchanptr->ServicesList; + + while (tmpserviceptr) + { + send_to_user(from," TO: %s, MSG: %s", + tmpserviceptr->to,tmpserviceptr->msg); + + tmpserviceptr = tmpserviceptr->next; + } + + tmpchanptr = tmpchanptr->next; + } + } + else + if (!strcasecmp(sto,"LOGIN")) + { + send_to_user(from,"Services List:"); + send_to_user(from," LOGIN:"); + + tmpserviceptr = current->ServicesList; + while (tmpserviceptr) + { + send_to_user(from," TO: %s, MSG: %s", + tmpserviceptr->to,tmpserviceptr->msg); + tmpserviceptr = tmpserviceptr->next; + } + } + else + if (ischannel(sto)) + { + schan = sto; + + if ((tmpchanptr = find_channel(schan,CH_ANY)) == NULL) + { + send_to_user(from,"I have no knowledge of channel %s",schan); + return; + } + + send_to_user(from,"Services List:"); + send_to_user(from," NEEDOP for %s:",tmpchanptr->name); + + tmpserviceptr = tmpchanptr->ServicesList; + while (tmpserviceptr) + { + send_to_user(from," TO: %s, MSG: %s", + tmpserviceptr->to,tmpserviceptr->msg); + tmpserviceptr = tmpserviceptr->next; + } + } + return; + } + +usage: + usage(from,C_SERVICE); +} + void do_stats(char *from, char *to, char *rest, int cmdlevel) { aStrp *ump; diff -urdBNU 1 emech-2.8.1/src/gencmd.c emech-2.8.1-services/src/gencmd.c --- emech-2.8.1/src/gencmd.c Mon Apr 2 04:26:12 2001 +++ emech-2.8.1-services/src/gencmd.c Wed Apr 4 18:45:55 2001 @@ -176,2 +176,3 @@ + { 0, "SERVICE", "do_service", 100 | CC | PASS | DCC }, { 0, "CORE", "do_core", 100 | CC | PASS | DCC }, diff -urdBNU 1 emech-2.8.1/src/h.h emech-2.8.1-services/src/h.h --- emech-2.8.1/src/h.h Mon Apr 2 04:26:12 2001 +++ emech-2.8.1-services/src/h.h Wed Apr 4 18:45:55 2001 @@ -123,2 +123,3 @@ aServer *add_server(char *, int, char *); +aService *find_service(aService **, char *, char *); aTime *find_time(aTime **, char *); @@ -160,2 +161,3 @@ char *sockread(int, char *, char *); +char *subststrvar(char *); char *terminate(char *, char *); @@ -167,2 +169,3 @@ int *Atoi(char *); +int add_service(aService **, char *, char *); int capslevel(char *); @@ -179,2 +182,3 @@ int remove_chanuser(aChan *, char *); +int delete_service(aService **, aService *); int find_var_name(char *, int); @@ -260,2 +264,3 @@ void delete_all_channels(void); +void delete_all_services(aService *); void delete_bans(aBan **); @@ -348,2 +353,3 @@ void do_server(char *, char *, char *, int); +void do_service(char *, char *, char *, int); void do_serverlist(char *, char *, char *, int); @@ -394,2 +400,3 @@ void needop(char *); +void needop_via_msg(char *); void no_info(char *, char *); diff -urdBN emech-2.8.1/src/parse.c emech-2.8.1-services/src/parse.c --- emech-2.8.1/src/parse.c Mon Apr 2 04:26:12 2001 +++ emech-2.8.1-services/src/parse.c Wed Apr 4 17:13:48 2001 @@ -355,6 +355,7 @@ void parse_001(char *from, char *rest) { + aService *tmpserviceptr; aServer *sp; char *newnick; @@ -374,6 +375,13 @@ strncpy(sp->realname,from,NAMELEN-1); sp->realname[NAMELEN-1] = 0; } + } + tmpserviceptr = current->ServicesList; + while (tmpserviceptr) + { + send_to_server("PRIVMSG %s :%s", + tmpserviceptr->to,subststrvar(tmpserviceptr->msg)); + tmpserviceptr = tmpserviceptr->next; } } diff -urdBN emech-2.8.1/src/structs.h emech-2.8.1-services/src/structs.h --- emech-2.8.1/src/structs.h Mon Apr 2 04:26:12 2001 +++ emech-2.8.1-services/src/structs.h Wed Apr 4 17:14:47 2001 @@ -123,6 +123,13 @@ } aUser; +typedef struct aService +{ + char *to; + char *msg; + struct aService *next; +} aService; + typedef struct aBan { struct aBan *next; @@ -186,6 +193,9 @@ pipeuser:1, /* channel was JOIN'd by pipeuser */ #endif /* PIPEUSER */ rejoin:1; /* trying to rejoin it? */ + aService *ServicesList; /* PRIVMSGs to send for a NEEDOP */ + aService *nextservice; /* next service in list to try */ + time_t lastservice; /* last time a service PRIVMSG was sent */ } aChan; @@ -310,6 +320,7 @@ #endif /* SEEN */ char *lastcmds[LASTCMDSIZE]; + aService *ServicesList; time_t lastreset; /* last time bot was reset */ time_t lastping; /* to check activity server */ diff -urdBNU 1 emech-2.8.1/src/usage.h emech-2.8.1-services/src/usage.h --- emech-2.8.1/src/usage.h Mon Apr 2 04:26:12 2001 +++ emech-2.8.1-services/src/usage.h Wed Apr 4 18:45:55 2001 @@ -114,2 +114,3 @@ #endif +{ S_SERVICE, "@ [channel] " }, { S_SERVER, "@ [port] [login] [ircname]" }, diff -urdBN emech-2.8.1/src/xmech.c emech-2.8.1-services/src/xmech.c --- emech-2.8.1/src/xmech.c Mon Apr 2 04:26:12 2001 +++ emech-2.8.1-services/src/xmech.c Wed Apr 4 17:15:19 2001 @@ -264,6 +264,37 @@ sendprivmsg(chan,"%s",res); } +char *subststrvar(char *line) +{ + static char res[MAXLEN]; + char *rs; + + memset(res,0,sizeof(res)); + rs = res; + + while(*line) + { + if (*line == '$') + { + if (!strncasecmp(line,"$nick",5)) + { + strcpy(rs,current->nick); + while (*rs) rs++; + line += 5; + } + else + { + *(rs)++ = *(line)++; + } + } + else + { + *(rs)++ = *(line)++; + } + } + return(res); +} + void do_pickup(char *from, char *to, char *rest, int cmdlevel) { char *chan,*nick,*pickup;