GOOGLE
/************************************************************************
* psybnc2.3, src/p_script.c
* Copyright (C) 2001 the most psychoid and
* the cool lam3rz IRC Group, IRCnet
* http://www.psychoid.lam3rz.de
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 1, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef lint
static char rcsid[] = "@(#)$Id: p_script.c, v 2.3 2001/07/13 02:03:00 psychoid Exp $";
#endif
#define P_SCRIPT
#include <p_global.h>
#ifdef SCRIPTING
#define ERR_SUB "Cannot execute program '%s' invoked by %s"
static int forks=0;
#define MAXFORKS 50
/*
* Scripting for psyBNC
* the two following routines are the 'core' for scripting usage.
* addsubtask will be called by startpipe, which will be called
* from the high level event and alias routines
*
* We are using socketpair to create sockets for the in&output
* to allow the usage of those in the socketdriver.
* This is 4.3BSDish, so it should work even on proprietry
* Operating Systems as like SunOs :P
* STDIN will be used also to read data from. As file that
* wont be possible, as socketpair it is possible.
*/
struct subtask *previoustask;
/* getting a subtask structure by pid */
struct subtask *getsubtaskbypid(int pid)
{
struct subtask *sts;
sts=subtasks;
previoustask=NULL;
while(sts!=NULL)
{
if(sts->pid==pid) return sts;
previoustask=sts;
sts=sts->next;
}
return NULL;
}
/* handling the internal structure */
int addsubtask(int uid, int pid, int fdin, int fdout, int fderr, char *program, struct scriptt *script)
{
struct subtask *st,*pst;
pcontext;
st=subtasks;
pst=st;
if(st==NULL)
{
st=(struct subtask *)pmalloc(sizeof(struct subtask));
subtasks=st;
} else {
while (st!=NULL)
{
pst=st;
st=st->next;
}
pst->next=(struct subtask *)pmalloc(sizeof(struct subtask));
st=pst->next;
}
st->uid=uid;
st->pid=pid;
st->fdin=fdin;
st->fdout=fdout;
st->fderr=fderr;
st->script=script;
st->desc=(char *)pmalloc(strlen(program)+1);
strmncpy(st->desc,program,strlen(program)+1);
return 0x1;
}
/* the forking pipe for the subtask */
int startpipe( int usern,
char *program,
struct scriptt *script,
int(*setenvironment)(int,struct scriptt *),
int(*inboundhandler)(int),
int(*outboundhandler)(int),
int(*errorlog)(int),
int(*terminated)(int,int),
int(*destroyed)(int))
{
int in_fds[2],out_fds[2],err_fds[2];
int pid,ss1=0,ss2=0,ss3=0,rc;
int temp_in,temp_out,temp_err;
int mypid;
struct socketnodes *sdes;
pcontext;
if(forks>MAXFORKS)
{
log(LOG_ERROR,usern,gettxt(714),program,user(usern)->login);
return -1;
}
if(mainlog!=NULL)
{
fclose(mainlog);
mainlog=NULL;
}
if(socketpair(AF_UNIX,SOCK_STREAM,0,in_fds)<0)
{
log(LOG_ERROR,usern,ERR_SUB,program,user(usern)->login);
return -1;
}
if(socketpair(AF_UNIX,SOCK_STREAM,0,out_fds)<0)
{
shutdown(in_fds[0],2);
close(in_fds[0]);
shutdown(in_fds[1],2);
close(in_fds[1]);
log(LOG_ERROR,usern,ERR_SUB,program,user(usern)->login);
return -1;
}
if(socketpair(AF_UNIX,SOCK_STREAM,0,err_fds)<0)
{
shutdown(in_fds[0],2);
close(in_fds[0]);
shutdown(in_fds[1],2);
close(in_fds[1]);
shutdown(out_fds[0],2);
close(out_fds[0]);
shutdown(out_fds[1],2);
close(out_fds[1]);
log(LOG_ERROR,usern,ERR_SUB,program,user(usern)->login);
return -1;
}
signal(SIGCHLD,SIG_IGN); /* zombie.. */
if ((pid=fork())<0)
{
shutdown(in_fds[0],2);
close(in_fds[0]);
shutdown(in_fds[1],2);
close(in_fds[1]);
shutdown(out_fds[0],2);
close(out_fds[0]);
shutdown(out_fds[1],2);
close(out_fds[1]);
shutdown(err_fds[0],2);
close(err_fds[0]);
shutdown(err_fds[1],2);
close(err_fds[1]);
log(LOG_ERROR,usern,ERR_SUB,program,user(usern)->login);
return -1;
}
if (!pid)
{
close(out_fds[0]);
dup2(out_fds[1],STD_OUT);
close(out_fds[1]);
close(in_fds[1]);
dup2(in_fds[0],STD_IN);
close(in_fds[0]);
close(err_fds[0]);
dup2(err_fds[1],STD_ERR);
close(err_fds[1]);
if(setenvironment!=NULL)
rc=(*setenvironment)(usern,script);
sleep(1); /* one second delay for mothers actions */
/*
* we call "system", which is normally not called by
* demon applications. But in this case the call will
* only get the parameters being taken from the user
* defined script. So no "bogus" data can be passed
* on. Also we only define the environment, there
* are no "usergiven" env-parameters.
*/
system(program);
/* write(STD_ERR,gettxt(715),4); sending us an EOF */
sleep(1); /* wait some time, until mother gets we died. */
exit(0x0);
} else {
/* creating internal structures */
close(out_fds[1]);
close(in_fds[0]);
close(err_fds[1]);
ss1=createsocket(in_fds[1],ST_CONNECT,0,NULL,NULL,terminated,outboundhandler,destroyed,AF_INET,SSL_OFF);
if(ss1>0)
{
ss2=createsocket(out_fds[0],ST_CONNECT,0,NULL,NULL,terminated,inboundhandler,destroyed,AF_INET,SSL_OFF);
if(ss2>0)
{
ss3=createsocket(err_fds[0],ST_CONNECT,0,NULL,NULL,terminated,errorlog,destroyed,AF_INET,SSL_OFF);
}
}
if(ss3<=0)
{
if(ss1>0) killsocket(ss1);
if(ss2>0) killsocket(ss2);
log(LOG_ERROR,usern,gettxt(716),program,user(usern)->login);
return -1;
}
forks++;
/* post fill of the psockets */
sdes=getpsocketbysock(in_fds[1]);
if(sdes!=NULL)
{
ap_snprintf(sdes->sock->source,sizeof(sdes->sock->source),gettxt(717),pid);
strcpy(sdes->sock->dest,"0:0");
sdes->sock->sport=pid;
sdes->sock->dport=usern;
sdes->sock->param=pid;
sdes->sock->flag=SOC_CONN;
}
sdes=getpsocketbysock(out_fds[0]);
if(sdes!=NULL)
{
ap_snprintf(sdes->sock->source,sizeof(sdes->sock->source),gettxt(718),pid);
strcpy(sdes->sock->dest,"0:0");
sdes->sock->sport=pid;
sdes->sock->dport=usern;
sdes->sock->param=pid;
sdes->sock->flag=SOC_CONN;
}
sdes=getpsocketbysock(err_fds[0]);
if(sdes!=NULL)
{
ap_snprintf(sdes->sock->source,sizeof(sdes->sock->source),gettxt(719),pid);
strcpy(sdes->sock->dest,"0:0");
sdes->sock->sport=pid;
sdes->sock->dport=usern;
sdes->sock->param=pid;
sdes->sock->flag=SOC_CONN;
}
addsubtask(usern,pid,in_fds[1],out_fds[0],err_fds[0],program,script);
}
return pid;
}
/* standard routine to kill a task */
int terminatetask(int pid,int err)
{
struct subtask *st;
struct scriptt *scr;
struct socketnodes *ps;
pcontext;
if(pid<=0) return -1;
if(forks>0) forks--;
st=getsubtaskbypid(pid);
if(st==NULL) return 0x0;
if(previoustask==NULL)
subtasks=st->next;
else
previoustask->next=st->next;
ps=getpsocketbysock(st->fdin);
if(ps!=NULL)
{
ps->sock->destructor=NULL;
ps->sock->errorhandler=NULL;
killsocket(st->fdin);
}
ps=getpsocketbysock(st->fdout);
if(ps!=NULL)
{
ps->sock->destructor=NULL;
ps->sock->errorhandler=NULL;
killsocket(st->fdout);
}
ps=getpsocketbysock(st->fderr);
if(ps!=NULL)
{
ps->sock->destructor=NULL;
ps->sock->errorhandler=NULL;
killsocket(st->fderr);
}
scr=st->script;
if(scr!=NULL)
{
scr->pid=0;
}
kmd:
free(st->desc);
free(st);
return 0x0;
}
int terminatedest(int pid)
{
return terminatetask(pid,0);
}
/* clearing the script from a user */
int clearuserscript(int usern)
{
struct scriptt *sm,*lsm;
struct subtask *stsk,*ntsk;
pcontext;
sm=user(usern)->script;
while(sm!=NULL)
{
lsm=sm->next;
if(sm->event!=NULL) free(sm->event);
if(sm->from!=NULL) free(sm->from);
if(sm->to!=NULL) free(sm->to);
if(sm->content!=NULL) free(sm->content);
if(sm->command!=NULL) free(sm->command);
/* we need to kill all bound tasks */
stsk=subtasks;
while(stsk!=NULL)
{
ntsk=stsk->next;
if(stsk->script==sm && stsk->pid!=0)
{
terminatetask(stsk->pid,0);
}
stsk=ntsk;
}
free(sm);
sm=lsm;
}
user(usern)->script=NULL;
return 0x0;
}
/* get the function from the string */
int getscriptfunction(char *func)
{
char ffunc[strlen(func)+1];
strmncpy(ffunc,func,strlen(func)+1);
ucase(ffunc);
if(strmcmp(ffunc,gettxt(720))) return SCR_DCCCHAT;
if(strmcmp(ffunc,gettxt(721))) return SCR_DCCSEND;
if(strmcmp(ffunc,gettxt(722))) return SCR_SERVER;
if(strmcmp(ffunc,gettxt(723))) return SCR_DIALOGUE;
if(strmcmp(ffunc,"CTCP")) return SCR_CTCP;
if(strmcmp(ffunc,gettxt(724))) return SCR_ALIAS;
return SCR_NONE;
}
/* parsing a single line of a user script */
int processscriptline(int usern, char *line)
{
char *nothing=gettxt(1315);
char *function=nothing,*event=nothing,*from=nothing,*to=nothing,*content=nothing,*command=nothing;
char *pt,*ept;
char *ln;
struct scriptt *uscript,*ouscript=NULL;
char nline[strlen(line)+1];
int zncount=0;
pcontext;
strmncpy(nline,line,strlen(line)+1);
ln=nline;
while(ln!=NULL && zncount!=6)
{
while(*ln!=0 && (*ln==' ' || *ln=='\t')) ln++; /* stripping */
if(*ln=='"')
{
ln++;
pt=strchr(ln,'"');
if(pt==NULL) return -1;
*pt=0;pt++;
} else {
pt=strchr(ln,0x9); /* tabs */
if(pt==NULL) pt=strchr(ln,' ');
ept=strchr(ln,' ');
if(ept!=NULL && ept<pt) pt=ept;
if(pt!=NULL && zncount!=5)
{*pt=0;pt++;}
}
switch(zncount)
{
case 0:
function=ln;
break;
case 1:
event=ln;
break;
case 2:
from=ln;
break;
case 3:
to=ln;
break;
case 4:
content=ln;
break;
case 5:
command=ln;
break;
}
zncount++;
ln=pt;
}
/* when we are here, we did not get enough parameters */
if(zncount!=6) return -1;
pcontext;
if(getscriptfunction(function)==SCR_NONE) return -1;
uscript=user(usern)->script;
while(uscript!=NULL)
{
ouscript=uscript;
uscript=uscript->next;
}
if(ouscript==NULL)
{
user(usern)->script=(struct scriptt *)pmalloc(sizeof(struct scriptt));
uscript=user(usern)->script;
} else {
ouscript->next=(struct scriptt *)pmalloc(sizeof(struct scriptt));
uscript=ouscript->next;
}
uscript->event=(char *)pmalloc(strlen(event)+1);
uscript->from=(char *)pmalloc(strlen(from)+1);
uscript->to=(char *)pmalloc(strlen(to)+1);
uscript->content=(char *)pmalloc(strlen(content)+1);
uscript->command=(char *)pmalloc(strlen(command)+1);
strmncpy(uscript->event,event,strlen(event)+1);
strmncpy(uscript->from,from,strlen(from)+1);
strmncpy(uscript->to,to,strlen(to)+1);
strmncpy(uscript->content,content,strlen(content)+1);
strmncpy(uscript->command,command,strlen(command)+1);
uscript->function=getscriptfunction(function);
uscript->pid=0;
return 0x0;
}
/* loading the script of a single user */
int loadscript(int usern)
{
FILE *script;
char bf[60];
char *pt;
char scline[4096];
int line=1;
pcontext;
if(user(usern)->script!=NULL)
clearuserscript(usern);
ap_snprintf(bf,sizeof(bf),"scripts/USER%d.SCRIPT",usern);
script=fopen(bf,"r");
if(script==NULL)
{
strcpy(bf,"scripts/DEFAULT.SCRIPT");
script=fopen(bf,"r");
}
if(script==NULL)
return -1;
while(fgets(scline,sizeof(scline),script))
{
pt=strchr(scline,'\r');
if(pt==NULL) pt=strchr(scline,'\n');
if(pt!=NULL) *pt=0;
if(strlen(scline)>1 && *scline!=';' && processscriptline(usern, scline)==-1)
{
log(LOG_ERROR,usern,"Bogus scripting Line in %s Line %d: %s",bf,line,scline);
}
line++;
}
fclose(script);
return 0x0;
}
/* get next script entry from script identifier */
struct scriptt *getnextfunctionentry(struct scriptt *msc,int func)
{
if(msc==NULL) return NULL;
msc=msc->next;
while(msc!=NULL)
{
if(msc->function==func) return 0x0;
msc=msc->next;
}
return NULL;
}
/* setup standard environments */
int setupstandardenv(int usern,struct scriptt *script)
{
char fn[20];
char *pt,*pt2,*pt3;
char c;
int icnt=1;
setenv("NICK",ircnick,1);
setenv("IDENT",ircident,1);
setenv("HOST",irchost,1);
setenv("USER",ircfrom,1);
setenv("CMD",irccommand,1);
setenv("TO",ircto,1);
setenv("CONTENT",irccontent,1);
ap_snprintf(fn,sizeof(fn),"%d",usern);
setenv("USERNUMBER",fn,1);
setenv("USERLOGIN",user(usern)->login,1);
setenv("USERNICK",user(usern)->nick,1);
setenv("USERHOST",user(usern)->host,1);
if(user(usern)->instate==STD_CONN)
setenv("USERON","1",1);
else
setenv("USERON","0",1);
/* setup P parameters (from ircinput) */
pt=ircbuf;
pt2=pt;
while(pt2!=NULL)
{
pt2=strchr(pt,' ');
if(pt2!=NULL)
{
*pt2=0;
}
ap_snprintf(fn,sizeof(fn),"P%d",icnt);
pt3=strchr(pt,'\r');
if(pt3==NULL) pt3=strchr(pt,'\n');
if(pt3!=NULL)
{
c=*pt3;
*pt3=0;
}
setenv(fn,pt,1);
if(pt3!=NULL) *pt3=c;
if(pt2!=NULL)
{
*pt2=' ';
pt2++;
pt=pt2;
}
icnt++;
}
return 0x0;
}
/* generic script-error routine */
int scripterror(int pid)
{
struct subtask *stsk;
char *pt;
stsk=getsubtaskbypid(pid);
if(stsk!=NULL)
{
pt=strchr(ircbuf,'\r');
if(pt==NULL) pt=strchr(ircbuf,'\n');
if(pt!=NULL) *pt=0;
log(LOG_WARNING,stsk->uid,"[%d/%s]: %s",pid,user(stsk->uid)->login,ircbuf);
}
return 0x0;
}
/*
* Now the application specific routines
* dialogues, aliases etc.
*/
/* dialogue events */
/* setting the environment for the dialogue */
int setdialogueenv(int usern,struct scriptt *script)
{
setupstandardenv(usern,script);
setenv("MYNICK",script->to,1);
return 0x0;
}
/* dialogue input handler */
int dialogueevent(int pid)
{
struct subtask *stsk;
pcontext;
stsk=getsubtaskbypid(pid);
if(stsk!=NULL)
{
if(user(stsk->uid)->instate==STD_CONN)
{
if(stsk->script!=NULL)
{
ssnprintf(user(stsk->uid)->insock,"(%s)!psyBNC@lam3rz.de PRIVMSG %s :%s\r\n",stsk->script->to,user(stsk->uid)->nick,ircbuf);
}
}
}
return 0x0;
}
/* start all dialogues when the user sings on */
int startdialogues(int usern)
{
struct scriptt *msc;
pcontext;
msc=user(usern)->script;
while(msc!=NULL)
{
if(msc!=NULL)
{
if(msc->function==SCR_DIALOGUE)
msc->pid=startpipe(usern,msc->command,msc,setdialogueenv,dialogueevent,dialogueevent,scripterror,terminatetask,terminatedest);
}
msc=msc->next;
}
}
/* stop the dialogues if the user signs off */
int stopdialogues(int usern)
{
struct scriptt *msc,*pmsc;
pcontext;
msc=user(usern)->script;
while(msc!=NULL)
{
pmsc=msc->next;
if(msc->function==SCR_DIALOGUE && msc->pid!=0)
{
terminatetask(msc->pid,0);
}
msc=pmsc;
}
return 0x0;
}
/* send a users input to the dialogue */
int senddialoguequery(int usern)
{
char *tnick;
struct subtask *tsk;
char sndcmd[2048];
pcontext;
tnick=strchr(ircto,'(');
if(tnick!=ircto) return 0x0;
tnick=strchr(ircto,')');
if(tnick==NULL)
{
return querydccchat(usern,ircto+1);
}
*tnick=0;
tnick=ircto+1;
tsk=subtasks;
while(tsk!=NULL)
{
if(tsk->script!=NULL)
{
if(tsk->script->function==SCR_DIALOGUE && strmcmp(tsk->script->to,tnick)==1)
{
ap_snprintf(sndcmd,sizeof(sndcmd),"%s\n",irccontent); /* \n only */
writesock_STREAM(tsk->fdout,sndcmd,strlen(sndcmd));
return 0x1;
}
}
tsk=tsk->next;
}
return 0x0; /* no match found */
}
/*
* server events
* run normally not backgrounded, and dont get any user input.
* STD_OUT output goes to the Server, using the USERINBOUND, so that
* a script could even call psybnc commands.
* everything else than a command of psybnc goes directly to the
* server without user notification.
* STD_IN is being abused as output to the clientside, if it is
* connected. The script user has to "simulate" valid server
* messages for the USEROUTBOUND.
* STD_ERR always goes into the log of psybnc and is logged with
* pid and usernumber.
*/
/* check a single server event for plausibility */
int checkserverevent(int usern,struct scriptt *scr)
{
static char pm[200];
static char pm1[200];
if(strmcmp(scr->event,irccommand))
{
strmncpy(pm,scr->to,sizeof(pm));
ucase(pm);
strmncpy(pm1,ircto,sizeof(pm1));
ucase(pm1);
if(strmcmp(pm,pm1) || *scr->to=='*')
{
if(strmwildcmp(irccontent,scr->content) || strmcmp(scr->content,"*")==1)
{
if(wild_match(scr->from,ircfrom) || strmcmp(scr->from,"*!*@*"))
{
return 1;
}
}
}
}
return 0x0;
}
/* setting the environment for the server event */
int setserverenv(int usern,struct scriptt *script)
{
struct uchannelt *chan;
struct uchannelusert *chanuser;
char us[100];
char ebuf[600];
int nr=1;
setupstandardenv(usern,script);
chan=getuserchannel(usern,rtrim(script->to));
if(chan!=NULL)
{
setenv("CHANNEL",chan->name,1);
setenv("CHANTOPIC",chan->topic,1);
setenv("CHANMODE",chan->modes,1);
if(chan->key[0]!=0)
setenv("CHANKEY",chan->key,1);
if(chan->limit!=0)
{
ap_snprintf(us,sizeof(us),"%d",chan->limit);
setenv("CHANLIMIT",us,1);
}
chanuser=chan->users;
while(chanuser!=NULL)
{
ap_snprintf(us,sizeof(us),"CHANUSER%d",nr);
ap_snprintf(ebuf,sizeof(ebuf),"%s!%s@%s|%c",chanuser->nick,chanuser->ident,chanuser->host,chanuser->mode[0]);
setenv(us,ebuf,1);
chanuser=chanuser->next;
}
} else {
if(strchr("#&+!",*script->to)!=NULL)
{
setenv("CHANNEL",script->to,1);
}
}
return 0x0;
}
/* the running server event or alias, sending data to server */
int servertoserverevent(int pid)
{
struct subtask *stsk;
stsk=getsubtaskbypid(pid);
if(stsk!=NULL)
{
if(user(stsk->uid)->outstate==STD_CONN)
{
userinbound(stsk->uid); /* simulate as if it came from the client */
}
}
return 0x0;
}
/* the running server event or alias, sending data to the client */
int servertoclientevent(int pid)
{
struct subtask *stsk;
stsk=getsubtaskbypid(pid);
if(stsk!=NULL)
{
if(user(stsk->uid)->instate==STD_CONN)
{
useroutbound(stsk->uid); /* simulate as if it came from the server */
}
}
return 0x0;
}
/* the event loop for a user */
int serverevent(int usern)
{
struct scriptt *scr;
scr=user(usern)->script;
while(scr!=NULL)
{
if(scr->function==SCR_SERVER)
{
if(checkserverevent(usern,scr)==1)
{
scr->pid=startpipe(usern,scr->command,scr,setserverenv,servertoclientevent,servertoserverevent,scripterror,terminatetask,terminatedest);
}
}
scr=scr->next;
}
}
/*
* aliases
* This are commands a user may execute as like he executes psyBNC
* commands. If an alias ist existent which is similiar to a fixed
* command used by psyBNC, the alias will replace the internal
* command.
* An alias may not stay in the background, if the alias task is
* still active, when the alias will be triggered by the user,
* then another alias background task will be raised. If as "TO"
* parameter a channel is defined, then the channel will be handed
* over as environment. If BHELP should show proper Infos for the
* specific command, a COMMAND.TXT file has to be added to the help
* directory of psybnc.
* STDIN output will be sent to the clients input (see server events)
* STDOUT will be sent to the server similiar to server events.
* STDERR goes to the error log.
*/
/* setting the environment for the alias event */
int setaliasenv(int usern,struct scriptt *script)
{
struct uchannelt *chan;
struct uchannelusert *chanuser;
char us[100];
char ebuf[600];
int nr=1;
setupstandardenv(usern,script);
chan=getuserchannel(usern,rtrim(ircto));
if(chan!=NULL)
{
setenv("CHANNEL",chan->name,1);
setenv("CHANTOPIC",chan->topic,1);
setenv("CHANMODE",chan->modes,1);
if(chan->key[0]!=0)
setenv("CHANKEY",chan->key,1);
if(chan->limit!=0)
{
ap_snprintf(us,sizeof(us),"%d",chan->limit);
setenv("CHANLIMIT",us,1);
}
chanuser=chan->users;
while(chanuser!=NULL)
{
ap_snprintf(us,sizeof(us),"CHANUSER%d",nr);
ap_snprintf(ebuf,sizeof(ebuf),"%s!%s@%s|%c",chanuser->nick,chanuser->ident,chanuser->host,chanuser->mode[0]);
setenv(us,ebuf,1);
nr++;
chanuser=chanuser->next;
}
} else {
if(strchr("#&+!",*ircto)!=NULL)
{
setenv("CHANNEL",ircto,1);
}
}
return 0x0;
}
/* check if a command is an alias */
int checkalias(int usern, struct scriptt *scr)
{
char ebuf[40];
strmncpy(ebuf,scr->event,sizeof(ebuf));
ucase(ebuf);
return strmcmp(ebuf,irccommand);
}
/* the bhelp-extension to aliases */
int aliasbhelp(int usern)
{
int headout=0;
struct scriptt *scr;
char *event,*from;
char defev[]="Undef.";
char deffrom[]="*";
scr=user(usern)->script;
while(scr!=NULL)
{
if(scr->function==SCR_ALIAS)
{
if(headout==0)
{
headout=1;
ssnprintf(user(usern)->insock,":irc.psychoid.net NOTICE %s :BHELP User defined Aliases:\n",user(usern)->nick);
}
event=defev;
from=deffrom;
if(scr->event!=NULL)
event=scr->event;
if(scr->from!=NULL)
from=scr->from;
ssnprintf(user(usern)->insock,":irc.psychoid.net NOTICE %s :BHELP %-15s - %s\n",user(usern)->nick,event,from);
}
scr=scr->next;
}
return 0x0;
}
/* execute an alias */
int executealias(int usern)
{
struct scriptt *scr;
struct subtask *sub;
scr=user(usern)->script;
while(scr!=NULL)
{
if(scr->function==SCR_ALIAS)
{
if(checkalias(usern,scr)==1)
{
scr->pid=startpipe(usern,scr->command,scr,setaliasenv,servertoclientevent,servertoserverevent,scripterror,terminatetask,terminatedest);
return 0x1; /* success, alias executed */
}
}
scr=scr->next;
}
return 0x0; /* no alias found */
}
/*
* DCC Chats and Files
* DCC Chat requests will be sent to the event, which may
* background itself. The creation of DCC Chat scriptingevents
* happens from the DCC Chat Control in p_dcc.c and wants a
* pid in return. That pid will, as long as it exists, be
* fed with the input of the DCC Chat and in return the
* DCC Chat will be fed with the output of the task while
* the User on the bouncer will be able to monitor both the
* in and output.
* DCC Filesends will be sent to the event, which possibly
* could automatically answer the Send Request via an answer
* to the User-Inbound (Triggering the DCCGET command).
*/
/* setting the environment for the dccchat event */
int setdccchatenv(int usern,struct scriptt *script)
{
setupstandardenv(usern,script);
setenv("IP",irchost,1);
return 0x0;
}
/* carring data from the task to the dcc chat */
int tasktochatevent(int pid)
{
struct dcct *pdcc;
struct subtask *stsk;
char netc[20];
netc[0]=0;
stsk=getsubtaskbypid(pid);
if(stsk==NULL) return 0x0;
pdcc=user(stsk->uid)->pdcc;
if(user(stsk->uid)->parent!=0)
{
ap_snprintf(netc,sizeof(netc),"%s~",user(stsk->uid)->network);
}
while(pdcc!=NULL)
{
if(pdcc->pid==pid)
{
if(pdcc->type==PDC_CHATFROM)
writesock(pdcc->sock,ircbuf);
if(user(stsk->uid)->instate==STD_CONN)
{
ssnprintf(user(stsk->uid)->insock,":%s(%s!DCCChat@%s PRIVMSG %s :[%d] %s",netc,pdcc->nick,pdcc->host,user(stsk->uid)->nick,pid,ircbuf);
}
return 0x0;
}
pdcc=pdcc->next;
}
return 0x0;
}
/* the event called by the dcc chat receive */
int dccchatscript(int usern, char *from)
{
struct scriptt *scr;
struct subtask *sub;
scr=user(usern)->script;
while(scr!=NULL)
{
if(scr->function==SCR_DCCCHAT)
{
if(wild_match(scr->from,from))
{
scr->pid=startpipe(usern,scr->command,scr,setdccchatenv,servertoserverevent,tasktochatevent,scripterror,terminatetask,terminatedest);
return scr->pid; /* success, chat executed */
}
}
scr=scr->next;
}
return 0x0; /* no dcc chat found */
}
/* setting the environment for the dccfile event */
int setdccfileenv(int usern,struct scriptt *script)
{
setupstandardenv(usern,script);
setenv("IP",irchost,1);
setenv("FILE",irccontent,1);
return 0x0;
}
/* the event called by the dcc file receive */
int dccfilescript(int usern, char *from)
{
struct scriptt *scr;
struct subtask *sub;
scr=user(usern)->script;
while(scr!=NULL)
{
if(scr->function==SCR_DCCSEND)
{
if(wild_match(scr->from,from))
{
scr->pid=startpipe(usern,scr->command,scr,setdccfileenv,servertoserverevent,servertoclientevent,scripterror,terminatetask,terminatedest);
return scr->pid; /* success, chat executed */
}
}
scr=scr->next;
}
return 0x0; /* no dcc chat found */
}
/*
* the ctcp event
* simple. print all output to the userinbound.
*/
/* set the ctcp environment */
int setctcpenv(int usern, struct scriptt *script)
{
char x01[]="\x01";
setupstandardenv(usern,script);
setenv("X01",x01,1);
return 0x0;
}
/* the event */
int ctcpscript(int usern, char *ctcp)
{
struct scriptt *scr;
struct subtask *sub;
scr=user(usern)->script;
while(scr!=NULL)
{
if(scr->function==SCR_CTCP)
{
if(strmcmp(scr->event,ctcp)==1 && wild_match(scr->from,ircfrom))
{
scr->pid=startpipe(usern,scr->command,scr,setctcpenv,servertoclientevent,servertoserverevent,scripterror,terminatetask,terminatedest);
return scr->pid; /* success, chat executed */
}
}
scr=scr->next;
}
return 0x0; /* no dcc chat found */
}
#endif
Copyright © 1945 -