+static int
+trace_mark_func(struct userNode *match, void *extra)
+{
+ struct discrim_and_source *das = extra;
+ char *mark = das->discrim->mark;
+
+ if(!mark)
+ return 1;
+ irc_mark(match, mark);
+ return 0;
+}
+
+static int
+trace_svsjoin_func(struct userNode *match, void *extra)
+{
+ struct discrim_and_source *das = extra;
+
+ char *channame = das->discrim->chantarget;
+ int checkrestrictions = das->discrim->checkrestrictions;
+ struct chanNode *channel;
+
+ if(!channame || !IsChannelName(channame)) {
+ //reply("MSG_NOT_CHANNEL_NAME");
+ return 1;
+ }
+
+ if (!(channel = GetChannel(channame))) {
+ channel = AddChannel(channame, now, NULL, NULL, NULL);
+ }
+
+ if (checkrestrictions) {
+ if (trace_check_bans(match, channel) == 1) {
+ return 1; /* found on lamer list */
+ }
+
+ if (channel->modes & MODE_INVITEONLY) {
+ return 1; /* channel is invite only */
+ }
+
+ if (channel->limit > 0) {
+ if (channel->members.used >= channel->limit) {
+ return 1; /* channel is invite on */
+ }
+ }
+
+ if (*channel->key) {
+ return 1; /* channel is password protected */
+ }
+ }
+
+ if (GetUserMode(channel, match)) {
+// reply("OSMSG_ALREADY_THERE", channel->name);
+ return 1;
+ }
+ irc_svsjoin(opserv, match, channel);
+ // reply("OSMSG_SVSJOIN_SENT");
+ return 0;
+}
+
+static int
+trace_svspart_func(struct userNode *match, void *extra)
+{
+ struct discrim_and_source *das = extra;
+ char *channame = das->discrim->chantarget;
+ struct chanNode *channel;
+
+ if(!channame || !IsChannelName(channame))
+ return 1;
+
+ if (!(channel = GetChannel(channame)))
+ return 1;
+
+ if (!GetUserMode(channel, match))
+ return 1;
+
+ irc_svspart(opserv, match, channel);
+ return 0;
+}
+
+static int
+trace_version_func(struct userNode *match, UNUSED_ARG(void *extra))
+{
+ irc_version_user(opserv, match);
+ return 0;
+}
+