/* remove_unknown() * * inputs - * output - * side effects - */ static void parse_remove_unknown(struct Client *client_p, const char *lsender, char *lbuffer) { /* * Do kill if it came from a server because it means there is a ghost * user on the other server which needs to be removed. -avalon * Tell opers about this. -Taner */ /* * '[0-9]something' is an ID (KILL/SQUIT depending on its length) * 'nodots' is a nickname (KILL) * 'no.dot.at.start' is a server (SQUIT) */ if ((IsDigit(*lsender) && strlen(lsender) <= IRC_MAXSID) || strchr(lsender, '.')) { sendto_realops_flags(UMODE_DEBUG, L_ADMIN, SEND_NOTICE, "Unknown prefix (%s) from %s, Squitting %s", lbuffer, client_get_name(client_p, SHOW_IP), lsender); sendto_realops_flags(UMODE_DEBUG, L_OPER, SEND_NOTICE, "Unknown prefix (%s) from %s, Squitting %s", lbuffer, client_get_name(client_p, MASK_IP), lsender); sendto_one(client_p, ":%s SQUIT %s :(Unknown prefix (%s) from %s)", me.id, lsender, lbuffer, client_p->name); } else sendto_one(client_p, ":%s KILL %s :%s (Unknown Client)", me.id, lsender, me.name); }
/** PropertyNotify handle event * \param ev XPropertyEvent pointer */ static void propertynotify(XPropertyEvent *ev) { Client *c; Systray *s; Window trans; XWMHints *h; if(ev->state == PropertyDelete) return; if((s = systray_find(ev->window))) { systray_state(s); systray_update(); } if((c = client_gb_win(ev->window))) { switch(ev->atom) { case XA_WM_TRANSIENT_FOR: XGetTransientForHint(dpy, c->win, &trans); if((c->flags & TileFlag || c->flags & MaxFlag)) if(((c->flags & HintFlag && (client_gb_win(trans) != NULL))) || (!(c->flags & HintFlag && (client_gb_win(trans) != NULL)))) arrange(c->screen, True); break; case XA_WM_NORMAL_HINTS: client_size_hints(c); break; case XA_WM_HINTS: if((h = XGetWMHints(dpy, c->win)) && (h->flags & XUrgencyHint) && c != sel) { client_urgent(c, True); XFree(h); } break; case XA_WM_NAME: client_get_name(c); break; default: if(ev->atom == net_atom[net_wm_name]) client_get_name(c); break; } } return; }
static void event_propertynotify(XEvent *e) { XPropertyEvent *ev = &e->xproperty; XWMHints *h; struct client *c; struct _systray *s; if(ev->state == PropertyDelete) return; if((c = client_gb_win(ev->window))) { switch(ev->atom) { case XA_WM_TRANSIENT_FOR: break; case XA_WM_NORMAL_HINTS: client_get_sizeh(c); break; case XA_WM_HINTS: if((h = XGetWMHints(EVDPY(e), c->win)) && (h->flags & XUrgencyHint) && c->tag != W->screen->seltag) { c->tag->flags |= TAG_URGENT; infobar_elem_screen_update(c->screen, ElemTag); XFree(h); } break; default: if(ev->atom == XA_WM_NAME || ev->atom == W->net_atom[net_wm_name]) client_get_name(c); break; } } else if((s = systray_find(ev->window))) { systray_state(s); systray_update(); } }
/* * parse a buffer. * * NOTE: parse() should not be called recusively by any other functions! */ void parse(struct Client *client_p, char *pbuffer, char *bufend) { struct Client *from = client_p; struct Message *message = NULL; char *para[MAXPARA + 2]; /* <command> + <parameters> + NULL */ char *ch = NULL; char *s = NULL; unsigned int numeric = 0; unsigned int parc = 0; unsigned int paramcount; if (IsDead(client_p)) return; assert(client_p->connection); assert(client_p->connection->fd); assert(client_p->connection->fd->flags.open); assert((bufend - pbuffer) < IRCD_BUFSIZE); for (ch = pbuffer; *ch == ' '; ++ch) /* Skip spaces */ ; if (*ch == ':') { /* * Copy the prefix to 'sender' assuming it terminates * with SPACE (or NULL, which is an error, though). */ const char *const sender = ++ch; if ((s = strchr(ch, ' '))) { *s = '\0'; ch = ++s; } if (*sender && IsServer(client_p)) { if ((from = hash_find_id(sender)) == NULL) from = hash_find_client(sender); /* * Hmm! If the client corresponding to the prefix is not found--what is * the correct action??? Now, I will ignore the message (old IRC just * let it through as if the prefix just wasn't there...) --msa */ if (from == NULL) { ++ServerStats.is_unpf; parse_remove_unknown(client_p, sender, pbuffer); return; } if (from->from != client_p) { ++ServerStats.is_wrdi; sendto_realops_flags(UMODE_DEBUG, L_ADMIN, SEND_NOTICE, "Fake direction: dropped message from %s[%s] via %s", from->name, from->from->name, client_get_name(client_p, SHOW_IP)); sendto_realops_flags(UMODE_DEBUG, L_OPER, SEND_NOTICE, "Fake direction: dropped message from %s[%s] via %s", from->name, from->from->name, client_get_name(client_p, MASK_IP)); return; } } while (*ch == ' ') ++ch; } if (*ch == '\0') { ++ServerStats.is_empt; return; } /* * Extract the command code from the packet. Point s to the end * of the command code and calculate the length using pointer * arithmetic. Note: only need length for numerics and *all* * numerics must have parameters and thus a space after the command * code. -avalon */ /* EOB is 3 characters long but is not a numeric */ if (*(ch + 3) == ' ' && /* Ok, let's see if it's a possible numeric */ IsDigit(*ch) && IsDigit(*(ch + 1)) && IsDigit(*(ch + 2))) { numeric = (*ch - '0') * 100 + (*(ch + 1) - '0') * 10 + (*(ch + 2) - '0'); paramcount = 2; /* Destination, and the rest of it */ ++ServerStats.is_num; s = ch + 3; /* I know this is ' ' from above if */ *s++ = '\0'; /* Blow away the ' ', and point s to next part */ } else { if ((s = strchr(ch, ' '))) *s++ = '\0'; if ((message = find_command(ch)) == NULL) { /* * Note: Give error message *only* to recognized * persons. It's a nightmare situation to have * two programs sending "Unknown command"'s or * equivalent to each other at full blast.... * If it has got to person state, it at least * seems to be well behaving. Perhaps this message * should never be generated, though... --msa * Hm, when is the buffer empty -- if a command * code has been found ?? -Armin */ if (*pbuffer) if (IsClient(from)) sendto_one_numeric(from, &me, ERR_UNKNOWNCOMMAND, ch); ++ServerStats.is_unco; return; } assert(message->cmd); paramcount = message->args_max; size_t length = bufend - ((s) ? s : ch); message->bytes += length; } /* * Must the following loop really be so devious? On surface it * splits the message to parameters from blank spaces. But, if * paramcount has been reached, the rest of the message goes into * this last parameter (about same effect as ":" has...) --msa */ /* Note initially true: s == NULL || *(s - 1) == '\0' !! */ para[parc] = ch; if (message && (message->flags & MFLG_EXTRA)) { /* * XXX: This will have to go away after the command handler rewrite */ para[++parc] = message->extra; } if (s) { if (paramcount > MAXPARA) paramcount = MAXPARA; while (true) { while (*s == ' ') *s++ = '\0'; if (*s == '\0') break; if (*s == ':') { /* The rest is single parameter--can include blanks also. */ para[++parc] = s + (numeric == 0); /* Keep the colon if it's a numeric */ break; } para[++parc] = s; if (parc >= paramcount) break; while (*s && *s != ' ') ++s; } } para[++parc] = NULL; if (message) parse_handle_command(message, from, parc, para); else parse_handle_numeric(numeric, from, parc, para); }