extern struct DenyConf* denyConfList;
extern struct CRuleConf* cruleConfList;
extern struct ServerConf* serverConfList;
- extern struct qline *GlobalQuarantineList;
+ extern struct s_map* GlobalServiceMapList;
+ extern struct qline* GlobalQuarantineList;
int yylex(void);
struct DenyConf *dconf;
struct ServerConf *sconf;
struct qline *qconf = NULL;
+ struct s_map *smap;
static void parse_error(char *pattern,...) {
- va_list vl;
- struct VarData vd;
- va_start(vl,pattern);
- vd.vd_format = pattern;
- vd.vd_args = vl;
- sendto_opmask_butone(0, SNO_OLDSNO, "Config: %v", &vd);
- va_end(vl);
+ static char error_buffer[1024];
+ va_list vl;
+ va_start(vl,pattern);
+ ircd_vsnprintf(NULL, error_buffer, sizeof(error_buffer), pattern, vl);
+ va_end(vl);
+ yyerror(error_buffer);
}
+
%}
%token <text> QSTRING
%token IP
%token FEATURES
%token QUARANTINE
+%token PSEUDO
+%token PREPEND
+%token USERMODE
/* and now a lot of priviledges... */
%token TPRIV_CHAN_LIMIT TPRIV_MODE_LCHAN TPRIV_DEOP_LCHAN TPRIV_WALK_LCHAN
%token TPRIV_KILL TPRIV_LOCAL_KILL TPRIV_REHASH TPRIV_RESTART TPRIV_DIE
blocks: blocks block | block;
block: adminblock | generalblock | classblock | connectblock |
serverblock | operblock | portblock | jupeblock | clientblock |
- killblock | cruleblock | motdblock | featuresblock | quarantineblock;
+ killblock | cruleblock | motdblock | featuresblock | quarantineblock |
+ pseudoblock | error;
/* The timespec, sizespec and expr was ripped straight from
* ircd-hybrid-7. */
jupeblock: JUPE '{' jupeitems '}' ';' ;
jupeitems: jupeitem jupeitems | jupeitem;
-jupeitem: jupenick;
+jupeitem: jupenick | error;
jupenick: NICK '=' QSTRING
{
addNickJupes(yylval.text);
generalblock: GENERAL '{' generalitems '}' ';' ;
generalitems: generalitem generalitems | generalitem;
-generalitem: generalnumeric | generalname | generalvhost | generaldesc;
+generalitem: generalnumeric | generalname | generalvhost | generaldesc | error;
generalnumeric: NUMERIC '=' NUMBER ';'
{
if (localConf.numeric == 0)
DupString(localConf.contact, "");
} ';';
adminitems: adminitems adminitem | adminitem;
-adminitem: adminlocation | admincontact;
+adminitem: adminlocation | admincontact | error;
adminlocation: LOCATION '=' QSTRING ';'
{
if (localConf.location1 == NULL)
tconn = 0;
maxlinks = 0;
sendq = 0;
+ pass = NULL;
} '{' classitems '}'
{
if (name != NULL)
{
add_class(name, tping, tconn, maxlinks, sendq);
+ find_class(name)->default_umode = pass;
}
else {
parse_error("Missing name in class block");
}
+ pass = NULL;
} ';';
classitems: classitem classitems | classitem;
classitem: classname | classpingfreq | classconnfreq | classmaxlinks |
- classsendq;
+ classsendq | classusermode | error;
classname: NAME '=' QSTRING ';'
{
MyFree(name);
{
sendq = yylval.num;
};
+classusermode: USERMODE '=' QSTRING ';'
+{
+ if (pass)
+ MyFree(pass);
+ DupString(pass, yylval.text);
+};
connectblock: CONNECT
{
}';';
connectitems: connectitem connectitems | connectitem;
connectitem: connectname | connectpass | connectclass | connecthost
- | connectport;
+ | connectport | error;
connectname: NAME '=' QSTRING ';'
{
MyFree(name);
} ';';
serveritems: serveritem serveritems | serveritem;
serveritem: servername | servermask | serverhub | serverleaf |
- serveruworld;
+ serveruworld | error;
servername: NAME '=' QSTRING
{
MyFree(aconf->name);
}
};
operitems: operitem | operitems operitem;
-operitem: opername | operpass | operlocal | operhost | operclass | operpriv;
+operitem: opername | operpass | operlocal | operhost | operclass | operpriv | error;
opername: NAME '=' QSTRING ';'
{
}
};
portitems: portitem portitems | portitem;
-portitem: portnumber | portvhost | portmask | portserver | porthidden;
+portitem: portnumber | portvhost | portmask | portserver | porthidden | error;
portnumber: PORT '=' NUMBER ';'
{
port = yylval.num;
}
} ';';
clientitems: clientitem clientitems | clientitem;
-clientitem: clienthost | clientclass | clientpass | clientip;
+clientitem: clienthost | clientclass | clientpass | clientip | error;
clientip: IP '=' QSTRING ';'
{
MyFree(aconf->host);
}
} ';';
killitems: killitem killitems | killitem;
-killitem: killuhost | killreal | killreasonfile | killreason;
+killitem: killuhost | killreal | killreasonfile | killreason | error;
killuhost: HOST '=' QSTRING ';'
{
char *u, *h;
} ';';
cruleitems: cruleitem cruleitems | cruleitem;
-cruleitem: cruleserver | crulerule | cruleall;
+cruleitem: cruleserver | crulerule | cruleall | error;
cruleserver: SERVER '=' QSTRING ';'
{
} ';';
motditems: motditem motditems | motditem;
-motditem: motdhost | motdfile;
+motditem: motdhost | motdfile | error;
motdhost: HOST '=' QSTRING ';'
{
DupString(host, yylval.text);
{
DupString(qconf->reason, yylval.text);
};
+
+pseudoblock: PSEUDO QSTRING '{'
+{
+ smap = MyCalloc(1, sizeof(struct s_map));
+ DupString(smap->command, $2);
+}
+pseudoitems '}' ';'
+{
+ if (!smap->name || !smap->services)
+ {
+ log_write(LS_CONFIG, L_ERROR, 0, "pseudo commands need a service name and list of target nicks.");
+ return 0;
+ }
+ if (register_mapping(smap))
+ {
+ smap->next = GlobalServiceMapList;
+ GlobalServiceMapList = smap;
+ }
+ else
+ {
+ struct nick_host *nh, *next;
+ for (nh = smap->services; nh; nh = next)
+ {
+ next = nh->next;
+ MyFree(nh);
+ }
+ MyFree(smap->name);
+ MyFree(smap->command);
+ MyFree(smap->prepend);
+ MyFree(smap);
+ }
+ smap = NULL;
+};
+
+pseudoitems: pseudoitem pseudoitems | pseudoitem;
+pseudoitem: pseudoname | pseudoprepend | pseudonick | error;
+pseudoname: NAME '=' QSTRING ';'
+{
+ DupString(smap->name, yylval.text);
+};
+pseudoprepend: PREPEND '=' QSTRING ';'
+{
+ DupString(smap->prepend, yylval.text);
+};
+pseudonick: NICK '=' QSTRING ';'
+{
+ char *sep = strchr(yylval.text, '@');
+
+ if (sep != NULL) {
+ size_t slen = strlen(yylval.text);
+ struct nick_host *nh = MyMalloc(sizeof(*nh) + slen);
+ memcpy(nh->nick, yylval.text, slen + 1);
+ nh->nicklen = sep - yylval.text;
+ nh->next = smap->services;
+ smap->services = nh;
+ }
+};