void avfilter_free(AVFilterContext *filter) { int i; if (filter->graph) ff_filter_graph_remove_filter(filter->graph, filter); if (filter->filter->uninit) filter->filter->uninit(filter); for (i = 0; i < filter->nb_inputs; i++) { free_link(filter->inputs[i]); } for (i = 0; i < filter->nb_outputs; i++) { free_link(filter->outputs[i]); } if (filter->filter->priv_class) av_opt_free(filter->priv); av_buffer_unref(&filter->hw_device_ctx); av_freep(&filter->name); av_freep(&filter->input_pads); av_freep(&filter->output_pads); av_freep(&filter->inputs); av_freep(&filter->outputs); av_freep(&filter->priv); av_freep(&filter->internal); av_free(filter); }
/** Disassociate configuration from the client. * @param cptr Client to operate on. * @param aconf ConfItem to detach. */ static void detach_conf(struct Client* cptr, struct ConfItem* aconf) { struct SLink** lp; struct SLink* tmp; assert(0 != aconf); assert(0 != cptr); assert(0 < aconf->clients); lp = &(cli_confs(cptr)); while (*lp) { if ((*lp)->value.aconf == aconf) { if (aconf->conn_class && (aconf->status & CONF_CLIENT_MASK) && ConfLinks(aconf) > 0) --ConfLinks(aconf); assert(0 < aconf->clients); if (0 == --aconf->clients && IsIllegal(aconf)) free_conf(aconf); tmp = *lp; *lp = tmp->next; free_link(tmp); return; } lp = &((*lp)->next); } }
/** * Removes a link from the list. This is a constant-time operation. * * @param list address of the list head. * @param link the list link to remove. */ void _dbus_list_remove_link (DBusList **list, DBusList *link) { _dbus_list_unlink (list, link); free_link (link); }
int main(int argc, char *argv[]) { pnode_t phead = NULL; int choice = 0; phead = create_link(); #ifndef __NDEBUG__ print_link(phead); #endif while (1) { #ifdef __NDEBUG__ system("clear"); #endif choice = menu(); if (choice == SEARCH_WORD) search_for_word(phead); else if (choice == ADD_WORD) phead = add_word(phead); else if (choice == EXIT_DICT) break; } free_link(phead); return 0; }
EXPORT_C #endif void _dbus_list_free_link (DBusList *link) { free_link (link); }
int del_dccallow(aClient *sptr, aClient *optr) { Link **lpp, *lp; int found = 0; for (lpp = &(sptr->user->dccallow); *lpp; lpp=&((*lpp)->next)) { if ((*lpp)->flags != DCC_LINK_ME) continue; if ((*lpp)->value.cptr == optr) { lp = *lpp; *lpp = lp->next; free_link(lp); found++; break; } } if (!found) { sendto_one(sptr, ":%s %d %s :%s is not in your DCC allow list", me.name, RPL_DCCINFO, sptr->name, optr->name); return 0; } for (found = 0, lpp = &(optr->user->dccallow); *lpp; lpp=&((*lpp)->next)) { if ((*lpp)->flags != DCC_LINK_REMOTE) continue; if ((*lpp)->value.cptr == sptr) { lp = *lpp; *lpp = lp->next; free_link(lp); found++; break; } } if (!found) sendto_realops("[BUG!] %s was in dccallowme list of %s but not in dccallowrem list!", optr->name, sptr->name); sendto_one(sptr, rpl_str(RPL_DCCSTATUS), me.name, sptr->name, optr->name, "removed from"); return 0; }
static int fuse_follow_link(struct dentry *dentry, struct nameidata *nd) { int ret; char *link; link = read_link(dentry); ret = vfs_follow_link(nd, link); free_link(link); return ret; }
int remove_dcc_references(aClient *sptr) { aClient *acptr; Link *lp, *nextlp; Link **lpp, *tmp; int found; lp = sptr->user->dccallow; while(lp) { nextlp = lp->next; acptr = lp->value.cptr; for(found = 0, lpp = &(acptr->user->dccallow); *lpp; lpp=&((*lpp)->next)) { if(lp->flags == (*lpp)->flags) continue; /* match only opposite types for sanity */ if((*lpp)->value.cptr == sptr) { if((*lpp)->flags == DCC_LINK_ME) { sendto_one(&me, acptr, ":%s %d %s :%s has been removed from " "your DCC allow list for signing off", me.name, RPL_DCCINFO, acptr->name, sptr->name); } tmp = *lpp; *lpp = tmp->next; free_link(tmp); found++; break; } } if(!found) sendto_realops_lev(DEBUG_LEV, "rdr(): %s was in dccallowme " "list[%d] of %s but not in dccallowrem list!", acptr->name, lp->flags, sptr->name); free_link(lp); lp = nextlp; } return 0; }
static int fuse_readlink(struct dentry *dentry, char __user *buffer, int buflen) { int ret; char *link; link = read_link(dentry); ret = vfs_readlink(dentry, buffer, buflen, link); free_link(link); return ret; }
/* * Delete Invite block from channel invite list and client invite list */ void del_invite(aClient *cptr, aChannel *chptr) { Link **inv, *tmp; for (inv = &(chptr->invites); (tmp = *inv); inv = &tmp->next) if (tmp->value.cptr == cptr) { *inv = tmp->next; free_link(tmp); break; } for (inv = &(cptr->user->invited); (tmp = *inv); inv = &tmp->next) if (tmp->value.chptr == chptr) { *inv = tmp->next; free_link(tmp); break; } }
void avfilter_free(AVFilterContext *filter) { int i; if (!filter) return; if (filter->graph) ff_filter_graph_remove_filter(filter->graph, filter); if (filter->filter->uninit) filter->filter->uninit(filter); for (i = 0; i < filter->nb_inputs; i++) { free_link(filter->inputs[i]); } for (i = 0; i < filter->nb_outputs; i++) { free_link(filter->outputs[i]); } if (filter->filter->priv_class) av_opt_free(filter->priv); av_buffer_unref(&filter->hw_device_ctx); av_freep(&filter->name); av_freep(&filter->input_pads); av_freep(&filter->output_pads); av_freep(&filter->inputs); av_freep(&filter->outputs); av_freep(&filter->priv); while(filter->command_queue){ ff_command_queue_pop(filter); } av_opt_free(filter); av_expr_free(filter->enable); filter->enable = NULL; av_freep(&filter->var_values); av_freep(&filter->internal); av_free(filter); }
int del_marks(struct Client* sptr) { int count = 0; struct SLink **lp; struct SLink *tmp; for (lp = &(cli_marks(sptr)); *lp;) { tmp = *lp; *lp = tmp->next; MyFree(tmp->value.cp); free_link(tmp); count++; } return count; }
/** * Frees all links in the list and sets the list head to #NULL. Does * not free the data in each link, for obvious reasons. This is a * linear-time operation. * * @param list address of the list head. */ void _dbus_list_clear (DBusList **list) { DBusList *link; link = *list; while (link != NULL) { DBusList *next = _dbus_list_get_next_link (list, link); free_link (link); link = next; } *list = NULL; }
/* ** off_history ** This must be called when the client structure is about to ** be released. History mechanism keeps pointers to client ** structures and it must know when they cease to exist. This ** also implicitly calls AddHistory. */ void off_history(aClient *cptr) { Reg Link *uwas; /* ** If the client has uwas entry/ies, there are also entries in ** the whowas array which point back to it. ** They have to be removed, by pairs */ while ((uwas = cptr->user->uwas)) { if (was[uwas->value.i].ww_online != cptr) #ifdef DEBUGMODE dumpcore("was[%d]: %#x != %#x", uwas->value.i, was[uwas->value.i].ww_online, cptr); #else sendto_flag(SCH_ERROR, "was[%d]: %#x != %#x", uwas->value.i, was[uwas->value.i].ww_online, cptr); #endif /* ** using &me to make ww_online non NULL (nicknames to be ** locked). &me can safely be used, it is constant. */ was[uwas->value.i].ww_online = &me; cptr->user->uwas = uwas->next; free_link(uwas); istat.is_wwuwas--; } istat.is_wwusers++; if (cptr->user->away) { istat.is_wwaways++; istat.is_wwawaysmem += strlen(cptr->user->away) + 1; } return; }
int main(int argc, char **argv) { link_t *link; if(argc != 2) { fprintf(stderr,"Usage:%s hostname\n",argv[0]); exit(1); } /* 初始化spider */ init_spider(argv[1]); /* 处理开始,直到队列为空 */ while (!g_queue_is_empty(link_que)) { link = g_queue_pop_head(link_que); printf("#dealing %s: %s ...\n", link->host, link->link); deal_page(link); printf("#dealed %s: %s\n", link->host, link->link); free_link(link); } quit_spider(); return 0; }
static void fuse_put_link(struct dentry *dentry, struct nameidata *nd, void *c) { free_link(nd_get_link(nd)); }
void deal_page(link_t *link) { int sockfd; char *host, *url; requset_t *req; host = link->host; url = link->link; if (NULL == (req = get_with_host_url(host, url))) { quit_spider(); exit(1); } sockfd = get_fd_from_host(host); if (0 > sockfd) { /* 负数表示没有打开过 */ printf("connecting to %s ...\n", host); if (-1 == (sockfd = create_connect(host, PORT))) { fprintf(stderr, "%s: Open host error with port %d!\n", host, PORT); quit_spider(); exit(1); } printf("connected to %s!!\n", host); if (0 != add_to_sers(host, sockfd)) { fprintf(stderr, "Error: `SERVERS` is too small\n"); quit_spider(); exit(1); } } /* * 0x1: 发送一个http请求 */ printf("writing...\n"); printf("writed. totle %lu\n", write(sockfd, req->re, req->len)); /* * 0x2: 处理应答,重点 */ int readlen; int crlf_offset; char buffer[BUF_SIZE], downlink[512]; char *href; char *tag_a_href; char savesour[100]; int sour_type; link_t *curr_link; int tmp_hash; int filesize, readed; printf("reading...\n"); readlen = read(sockfd, buffer, BUF_SIZE); crlf_offset = strstr(buffer, CRLFEND)-buffer+4; /* 计算实际数据的偏移量 */ readed = readlen-crlf_offset; filesize = file_size(buffer); #ifdef DEBUG printf("%s", buffer); #endif printf("readed. %d/%d: %.2f%%\n", readed, filesize, (float)readed/filesize*100); for (;;) { /* 处理一次读取 */ while (NULL != (href = get_next_href(buffer+crlf_offset))) { tag_a_href = get_link(href); /* 没有找到,或链接有错,或已经存在了的链接 */ /* NOTE 暂时修改下is_good_link来只读取.htm文档 */ if (!is_good_link(tag_a_href) || is_exist_hash(link_hash, tmp_hash = hash_value(tag_a_href))) continue; printf("-find link '%s', nice\n", tag_a_href); insert_hash(link_hash, tmp_hash); curr_link = calloc(sizeof(link_t), 1); if (NULL == curr_link) { quit_spider(); exit(1); } if (is_this_server_link(tag_a_href)) curr_link->host = strdup(link->host); else curr_link->host = get_host_from_link(tag_a_href); curr_link->link = get_url_from_link(tag_a_href); if (NULL == curr_link->link || NULL == curr_link->host) free_link(curr_link); #ifdef DEBUG else printf("成功构造:%s %s\n", curr_link->host, curr_link->link); #endif /* 判断是不是资源文件 */ sour_type = sources_type(tag_a_href); if (sour_type >= 0) { /* TODO 添加自动建立目录函数 */ char *tmp; /* 构造下载链接和保存名字 */ strcpy(downlink, curr_link->host); strcat(downlink, curr_link->link); strcpy(savesour, SAVEPATH); tmp = get_name_from_link(downlink); strcat(savesour, tmp); free(tmp); printf("%s: downloading...\n", downlink); switch (imbed_download(downlink, savesour)) { case -1: printf("%s: 连接服务器失败\n", curr_link->host); break; case -2: printf("写到文件失败\n"); break; case -3: printf("%s: 资源链接错误\n", curr_link->link); break; default: printf("%s: 下载成功(%d)\n", savesour, filesize); } free_link(curr_link); } else { g_queue_push_tail(link_que, (gpointer)curr_link); } free(tag_a_href); } crlf_offset = 0; /* 以后都不会有偏移量了 */ if (readed >= filesize) break; printf("reading...\n"); readlen = read(sockfd, buffer, BUF_SIZE); readed += readlen; printf("readed. %d/%d: %.2f%%\n", readed, filesize, (float)readed/filesize*100); #ifdef DEBUG printf("%s", buffer); #endif } sleep(1); /* 处于人道化考虑,暂停2s */ }
/** * Frees a linked list node allocated with _dbus_list_alloc_link. * Does not free the data in the node. * * @param link the list node */ void _dbus_list_free_link (DBusList *link) { free_link (link); }
/* ** add_history ** Add the currently defined name of the client to history. ** usually called before changing to a new name (nick). ** Client must be a fully registered user (specifically, ** the user structure must have been allocated). ** if nodelay is NULL, then the nickname will be subject to NickDelay */ void add_history(aClient *cptr, aClient *nodelay) { Reg aName *np; Reg Link *uwas; cptr->user->refcnt++; np = &was[ww_index]; if ((np->ww_online && (np->ww_online != &me)) && !(np->ww_user && np->ww_user->uwas)) #ifdef DEBUGMODE dumpcore("whowas[%d] %#x %#x %#x", ww_index, np->ww_online, np->ww_user, np->ww_user->uwas); #else sendto_flag(SCH_ERROR, "whowas[%d] %#x %#x %#x", ww_index, np->ww_online, np->ww_user, np->ww_user->uwas); #endif /* ** The entry to be overwritten in was[] is still online. ** its uwas has to be updated */ if (np->ww_online && (np->ww_online != &me)) { Reg Link **old_uwas; old_uwas = &(np->ww_user->uwas); /* (*old_uwas) should NEVER happen to be NULL. -krys */ while ((*old_uwas)->value.i != ww_index) old_uwas = &((*old_uwas)->next); uwas = *old_uwas; *old_uwas = uwas->next; free_link(uwas); free_user(np->ww_user); istat.is_wwuwas--; } else if (np->ww_user) { /* ** Testing refcnt here is quite ugly, and unexact. ** Nonetheless, the result is almost correct, and another ** ugly thing in free_server() shoud make it exact. ** The problem is that 1 anUser structure might be ** referenced several times from whowas[] but is only counted ** once. One knows when to add, not when to substract - krys */ if (np->ww_user->refcnt == 1) { istat.is_wwusers--; if (np->ww_user->away) { istat.is_wwaways--; istat.is_wwawaysmem -=strlen(np->ww_user->away) + 1; } } free_user(np->ww_user); } if (np->ww_logout != 0) { int elapsed = timeofday - np->ww_logout; /* some stats */ ircstp->is_wwcnt++; ircstp->is_wwt += elapsed; if (elapsed < ircstp->is_wwmt) ircstp->is_wwmt = elapsed; if (elapsed > ircstp->is_wwMt) ircstp->is_wwMt = elapsed; if (np->ww_online == NULL) { if (locked[lk_index].logout) { elapsed = timeofday - locked[lk_index].logout; /* some stats first */ ircstp->is_lkcnt++; ircstp->is_lkt += elapsed; if (elapsed < ircstp->is_lkmt) ircstp->is_lkmt = elapsed; if (elapsed > ircstp->is_lkMt) ircstp->is_lkMt = elapsed; } /* ** This nickname has to be locked, thus copy it to the ** lock[] array. */ strcpy(locked[lk_index].nick, np->ww_nick); locked[lk_index++].logout = np->ww_logout; if ((lk_index == lk_size) && (lk_size != ww_size)) { grow_locked(); } if (lk_index >= lk_size) lk_index = 0; } } if (nodelay == cptr) /* &me is NOT a valid value, see off_history() */ { /* ** The client is online, np->ww_online is going to point to ** it. The client user struct has to point to this entry ** as well for faster off_history() ** this uwas, and the ww_online form a pair. */ uwas = make_link(); istat.is_wwuwas++; /* ** because of reallocs, one can not store a pointer inside ** the array. store the index instead. */ uwas->value.i = ww_index; uwas->flags = timeofday; uwas->next = cptr->user->uwas; cptr->user->uwas = uwas; } np->ww_logout = timeofday; np->ww_user = cptr->user; np->ww_online = (nodelay != NULL) ? nodelay : NULL; strncpyzt(np->ww_nick, cptr->name, NICKLEN+1); strncpyzt(np->ww_info, cptr->info, REALLEN+1); ww_index++; if ((ww_index == ww_size) && (numclients > ww_size)) grow_whowas(); if (ww_index >= ww_size) ww_index = 0; return; }
/* * exit_client * This is old "m_bye". Name changed, because this is not a * protocol function, but a general server utility function. * * This function exits a client of *any* type (user, server, etc) * from this server. Also, this generates all necessary prototol * messages that this exit may cause. * * 1) If the client is a local client, then this implicitly exits * all other clients depending on this connection (e.g. remote * clients having 'from'-field that points to this. * * 2) If the client is a remote client, then only this is exited. * * For convenience, this function returns a suitable value for * m_function return value: * * FLUSH_BUFFER if (cptr == sptr) * 0 if (cptr != sptr) */ int exit_client(aClient *cptr, aClient *sptr, aClient *from, char *comment) { #ifdef FNAME_USERLOG time_t on_for; #endif if (MyConnect(sptr)) { call_hooks(CHOOK_SIGNOFF, sptr); if (IsUnknown(sptr)) Count.unknown--; if (IsAnOper(sptr)) remove_from_list(&oper_list, sptr, NULL); if (sptr->flags & FLAGS_HAVERECVQ) { /* mark invalid, will be deleted in do_recvqs() */ DLink *lp = find_dlink(recvq_clients, sptr); if (lp) lp->flags = -1; } if (IsClient(sptr)) Count.local--; if (IsNegoServer(sptr)) sendto_realops("Lost server %s during negotiation: %s", sptr->name, comment); if (IsServer(sptr)) { Count.myserver--; if (IsULine(sptr)) Count.myulined--; remove_from_list(&server_list, sptr, NULL); if (server_list == NULL) server_was_split = YES; } sptr->flags |= FLAGS_CLOSING; if (IsPerson(sptr)) { Link *lp, *next; LOpts *lopt = sptr->user->lopt; /* poof goes their watchlist! */ hash_del_watch_list(sptr); /* if they have listopts, axe those, too */ if(lopt != NULL) { remove_from_list(&listing_clients, sptr, NULL); for (lp = lopt->yeslist; lp; lp = next) { next = lp->next; MyFree(lp->value.cp); free_link(lp); } for (lp = lopt->nolist; lp; lp = next) { next = lp->next; MyFree(lp->value.cp); free_link(lp); } MyFree(sptr->user->lopt); sptr->user->lopt = NULL; } sendto_realops_lev(CCONN_LEV, "Client exiting: %s (%s@%s) [%s] [%s]", sptr->name, sptr->user->username, sptr->user->host, (sptr->flags & FLAGS_NORMALEX) ? "Client Quit" : comment, sptr->hostip); } #ifdef FNAME_USERLOG on_for = timeofday - sptr->firsttime; #endif #if defined(USE_SYSLOG) && defined(SYSLOG_USERS) if (IsPerson(sptr)) syslog(LOG_NOTICE, "%s (%3d:%02d:%02d): %s!%s@%s %d/%d\n", myctime(sptr->firsttime), on_for / 3600, (on_for % 3600) / 60, on_for % 60, sptr->name, sptr->user->username, sptr->user->host, sptr->sendK, sptr->receiveK); #endif #if defined(FNAME_USERLOG) { char linebuf[300]; static int logfile = -1; static long lasttime; /* * This conditional makes the logfile active only after it's * been created - thus logging can be turned off by removing * the file. * * stop NFS hangs...most systems should be able to open a file in * 3 seconds. -avalon (curtesy of wumpus) * * Keep the logfile open, syncing it every 10 seconds -Taner */ if (IsPerson(sptr)) { if (logfile == -1) { alarm(3); logfile = open(FNAME_USERLOG, O_WRONLY | O_APPEND); alarm(0); } ircsprintf(linebuf, "%s (%3d:%02d:%02d): %s!%s@%s %d/%d\n", myctime(sptr->firsttime), on_for / 3600, (on_for % 3600) / 60, on_for % 60, sptr->name, sptr->user->username, sptr->user->host, sptr->sendK, sptr->receiveK); alarm(3); write(logfile, linebuf, strlen(linebuf)); alarm(0); /* Resync the file evey 10 seconds*/ if (timeofday - lasttime > 10) { alarm(3); close(logfile); alarm(0); logfile = -1; lasttime = timeofday; } } } #endif if (sptr->fd >= 0) { if (cptr != NULL && sptr != cptr) sendto_one(&me, sptr, "ERROR :Closing Link: %s %s (%s)", IsPerson(sptr) ? sptr->sockhost : "0.0.0.0", sptr->name, comment); else sendto_one(&me, sptr, "ERROR :Closing Link: %s (%s)", IsPerson(sptr) ? sptr->sockhost : "0.0.0.0", comment); } /* * * Currently only server connections can have * depending * remote clients here, but it does no * harm to check for all * local clients. In * future some other clients than servers * might * have remotes too... * * * Close the Client connection first and mark it * so that no * messages are attempted to send to it. *, The following *must* * make MyConnect(sptr) == FALSE!). * It also makes sptr->from == * NULL, thus it's unnecessary * to test whether "sptr != acptr" * in the following loops. */ if (IsServer(sptr)) { sendto_ops("%s was connected for %lu seconds. %lu/%lu " "sendK/recvK.", sptr->name, (long)(timeofday - sptr->firsttime), sptr->sendK, sptr->receiveK); #ifdef USE_SYSLOG syslog(LOG_NOTICE, "%s was connected for %lu seconds. %lu/%lu " "sendK/recvK.", sptr->name, (u_long) timeofday - sptr->firsttime, sptr->sendK, sptr->receiveK); #endif close_connection(sptr); sptr->sockerr = 0; sptr->flags |= FLAGS_DEADSOCKET; } else { close_connection(sptr); sptr->sockerr = 0; sptr->flags |= FLAGS_DEADSOCKET; } } exit_one_client(cptr, sptr, from, comment); return cptr == sptr ? FLUSH_BUFFER : 0; }
/* * ms_burst - server message handler * * -- by Run [email protected] december 1995 till march 1997 * * parv[0] = sender prefix * parv[1] = channel name * parv[2] = channel timestamp * The meaning of the following parv[]'s depend on their first character: * If parv[n] starts with a '+': * Net burst, additive modes * parv[n] = <mode> * parv[n+1] = <param> (optional) * parv[n+2] = <param> (optional) * If parv[n] starts with a '%', then n will be parc-1: * parv[n] = %<ban> <ban> <ban> ... * If parv[n] starts with another character: * parv[n] = <nick>[:<mode>],<nick>[:<mode>],... * where <mode> is the channel mode (ov) of nick and all following nicks. * * Example: * "S BURST #channel 87654321 +ntkl key 123 AAA,AAB:o,BAA,BAB:ov :%ban1 ban2" * * Anti net.ride code. * * When the channel already exist, and its TS is larger then * the TS in the BURST message, then we cancel all existing modes. * If its is smaller then the received BURST message is ignored. * If it's equal, then the received modes are just added. */ int ms_burst(struct Client *cptr, struct Client *sptr, int parc, char *parv[]) { struct ModeBuf modebuf, *mbuf = 0; struct Channel *chptr; time_t timestamp; struct Membership *member, *nmember; struct SLink *lp, **lp_p; unsigned int parse_flags = (MODE_PARSE_FORCE | MODE_PARSE_BURST); int param, nickpos = 0, banpos = 0; char modestr[BUFSIZE], nickstr[BUFSIZE], banstr[BUFSIZE]; if (parc < 3) return protocol_violation(sptr,"Too few parameters for BURST"); if (!IsBurst(sptr)) /* don't allow BURST outside of burst */ return exit_client_msg(cptr, cptr, &me, "HACK: BURST message outside " "net.burst from %s", cli_name(sptr)); if (!(chptr = get_channel(sptr, parv[1], CGT_CREATE))) return 0; /* can't create the channel? */ timestamp = atoi(parv[2]); if (!chptr->creationtime || chptr->creationtime > timestamp) { /* * Kick local members if channel is +i or +k and our TS was larger * than the burst TS (anti net.ride). The modes hack is here because * we have to do this before mode_parse, as chptr may go away. */ for (param = 3; param < parc; param++) { if (parv[param][0] != '+') continue; if (strchr(parv[param], 'i') || strchr(parv[param], 'k')) { /* Clear any outstanding rogue invites */ mode_invite_clear(chptr); for (member = chptr->members; member; member = nmember) { nmember=member->next_member; if (!MyUser(member->user) || IsZombie(member)) continue; sendcmdto_serv_butone(&me, CMD_KICK, NULL, "%H %C :Net Rider", chptr, member->user); sendcmdto_channel_butserv_butone(&me, CMD_KICK, chptr, NULL, "%H %C :Net Rider", chptr, member->user); make_zombie(member, member->user, &me, &me, chptr); } } break; } /* If the channel had only locals, it went away by now. */ if (!(chptr = get_channel(sptr, parv[1], CGT_CREATE))) return 0; /* can't create the channel? */ } /* turn off burst joined flag */ for (member = chptr->members; member; member = member->next_member) member->status &= ~CHFL_BURST_JOINED; if (!chptr->creationtime) /* mark channel as created during BURST */ chptr->mode.mode |= MODE_BURSTADDED; /* new channel or an older one */ if (!chptr->creationtime || chptr->creationtime > timestamp) { chptr->creationtime = timestamp; modebuf_init(mbuf = &modebuf, &me, cptr, chptr, MODEBUF_DEST_CHANNEL | MODEBUF_DEST_NOKEY); modebuf_mode(mbuf, MODE_DEL | chptr->mode.mode); /* wipeout modes */ chptr->mode.mode &= ~(MODE_ADD | MODE_DEL | MODE_PRIVATE | MODE_SECRET | MODE_MODERATED | MODE_TOPICLIMIT | MODE_INVITEONLY | MODE_NOPRIVMSGS); parse_flags |= (MODE_PARSE_SET | MODE_PARSE_WIPEOUT); /* wipeout keys */ /* mark bans for wipeout */ for (lp = chptr->banlist; lp; lp = lp->next) lp->flags |= CHFL_BURST_BAN_WIPEOUT; /* clear topic set by netrider (if set) */ if (*chptr->topic) { *chptr->topic = '\0'; *chptr->topic_nick = '\0'; chptr->topic_time = 0; sendcmdto_channel_butserv_butone(&me, CMD_TOPIC, chptr, NULL, "%H :%s", chptr, chptr->topic); } } else if (chptr->creationtime == timestamp) { modebuf_init(mbuf = &modebuf, &me, cptr, chptr, MODEBUF_DEST_CHANNEL | MODEBUF_DEST_NOKEY); parse_flags |= MODE_PARSE_SET; /* set new modes */ } param = 3; /* parse parameters */ while (param < parc) { switch (*parv[param]) { case '+': /* parameter introduces a mode string */ param += mode_parse(mbuf, cptr, sptr, chptr, parc - param, parv + param, parse_flags); break; case '%': /* parameter contains bans */ if (parse_flags & MODE_PARSE_SET) { char *banlist = parv[param] + 1, *p = 0, *ban, *ptr; struct SLink *newban; for (ban = ircd_strtok(&p, banlist, " "); ban; ban = ircd_strtok(&p, 0, " ")) { ban = collapse(pretty_mask(ban)); /* * Yeah, we should probably do this elsewhere, and make it better * and more general; this will hold until we get there, though. * I dislike the current add_banid API... -Kev * * I wish there were a better algo. for this than the n^2 one * shown below *sigh* */ for (lp = chptr->banlist; lp; lp = lp->next) { if (!ircd_strcmp(lp->value.ban.banstr, ban)) { ban = 0; /* don't add ban */ lp->flags &= ~CHFL_BURST_BAN_WIPEOUT; /* not wiping out */ break; /* new ban already existed; don't even repropagate */ } else if (!(lp->flags & CHFL_BURST_BAN_WIPEOUT) && !mmatch(lp->value.ban.banstr, ban)) { ban = 0; /* don't add ban unless wiping out bans */ break; /* new ban is encompassed by an existing one; drop */ } else if (!mmatch(ban, lp->value.ban.banstr)) lp->flags |= CHFL_BAN_OVERLAPPED; /* remove overlapping ban */ if (!lp->next) break; } if (ban) { /* add the new ban to the end of the list */ /* Build ban buffer */ if (!banpos) { banstr[banpos++] = ' '; banstr[banpos++] = ':'; banstr[banpos++] = '%'; } else banstr[banpos++] = ' '; for (ptr = ban; *ptr; ptr++) /* add ban to buffer */ banstr[banpos++] = *ptr; newban = make_link(); /* create new ban */ DupString(newban->value.ban.banstr, ban); DupString(newban->value.ban.who, cli_name(feature_bool(FEAT_HIS_BANWHO) ? &me : sptr)); newban->value.ban.when = TStime(); newban->flags = CHFL_BAN | CHFL_BURST_BAN; /* set flags */ if ((ptr = strrchr(ban, '@')) && check_if_ipmask(ptr + 1)) newban->flags |= CHFL_BAN_IPMASK; newban->next = 0; if (lp) lp->next = newban; /* link it in */ else chptr->banlist = newban; } } } param++; /* look at next param */ break; default: /* parameter contains clients */ { struct Client *acptr; char *nicklist = parv[param], *p = 0, *nick, *ptr; int default_mode = CHFL_DEOPPED | CHFL_BURST_JOINED; int last_mode = CHFL_DEOPPED | CHFL_BURST_JOINED; for (nick = ircd_strtok(&p, nicklist, ","); nick; nick = ircd_strtok(&p, 0, ",")) { if ((ptr = strchr(nick, ':'))) { /* new flags; deal */ *ptr++ = '\0'; if (parse_flags & MODE_PARSE_SET) { for (default_mode = CHFL_DEOPPED | CHFL_BURST_JOINED; *ptr; ptr++) { if (*ptr == 'o') /* has oper status */ default_mode = (default_mode & ~CHFL_DEOPPED) | CHFL_CHANOP; else if (*ptr == 'v') /* has voice status */ default_mode |= CHFL_VOICE; else /* I don't recognize that flag */ break; /* so stop processing */ } } } if (!(acptr = findNUser(nick)) || cli_from(acptr) != cptr) continue; /* ignore this client */ /* Build nick buffer */ nickstr[nickpos] = nickpos ? ',' : ' '; /* first char */ nickpos++; for (ptr = nick; *ptr; ptr++) /* store nick */ nickstr[nickpos++] = *ptr; if (default_mode != last_mode) { /* if mode changed... */ last_mode = default_mode; nickstr[nickpos++] = ':'; /* add a specifier */ if (default_mode & CHFL_CHANOP) nickstr[nickpos++] = 'o'; if (default_mode & CHFL_VOICE) nickstr[nickpos++] = 'v'; } add_user_to_channel(chptr, acptr, default_mode); sendcmdto_channel_butserv_butone(acptr, CMD_JOIN, chptr, NULL, "%H", chptr); } } param++; break; } /* switch (*parv[param]) { */ } /* while (param < parc) { */ nickstr[nickpos] = '\0'; banstr[banpos] = '\0'; if (parse_flags & MODE_PARSE_SET) { modebuf_extract(mbuf, modestr + 1); /* for sending BURST onward */ modestr[0] = modestr[1] ? ' ' : '\0'; } else modestr[0] = '\0'; sendcmdto_serv_butone(sptr, CMD_BURST, cptr, "%H %Tu%s%s%s", chptr, chptr->creationtime, modestr, nickstr, banstr); if (parse_flags & MODE_PARSE_WIPEOUT || banpos) mode_ban_invalidate(chptr); if (parse_flags & MODE_PARSE_SET) { /* any modes changed? */ /* first deal with channel members */ for (member = chptr->members; member; member = member->next_member) { if (member->status & CHFL_BURST_JOINED) { /* joined during burst */ if (member->status & CHFL_CHANOP) modebuf_mode_client(mbuf, MODE_ADD | CHFL_CHANOP, member->user); if (member->status & CHFL_VOICE) modebuf_mode_client(mbuf, MODE_ADD | CHFL_VOICE, member->user); } else if (parse_flags & MODE_PARSE_WIPEOUT) { /* wipeout old ops */ if (member->status & CHFL_CHANOP) modebuf_mode_client(mbuf, MODE_DEL | CHFL_CHANOP, member->user); if (member->status & CHFL_VOICE) modebuf_mode_client(mbuf, MODE_DEL | CHFL_VOICE, member->user); member->status = ((member->status & ~(CHFL_CHANOP | CHFL_VOICE)) | CHFL_DEOPPED); } } /* Now deal with channel bans */ lp_p = &chptr->banlist; while (*lp_p) { lp = *lp_p; /* remove ban from channel */ if (lp->flags & (CHFL_BAN_OVERLAPPED | CHFL_BURST_BAN_WIPEOUT)) { modebuf_mode_string(mbuf, MODE_DEL | MODE_BAN, lp->value.ban.banstr, 1); /* let it free banstr */ *lp_p = lp->next; /* clip out of list */ MyFree(lp->value.ban.who); /* free who */ free_link(lp); /* free ban */ continue; } else if (lp->flags & CHFL_BURST_BAN) /* add ban to channel */ modebuf_mode_string(mbuf, MODE_ADD | MODE_BAN, lp->value.ban.banstr, 0); /* don't free banstr */ lp->flags &= (CHFL_BAN | CHFL_BAN_IPMASK); /* reset the flag */ lp_p = &(*lp_p)->next; } } return mbuf ? modebuf_flush(mbuf) : 0; }