sites

public wiki contents of suckless.org
git clone git://git.suckless.org/sites
Log | Files | Refs

ii-1.8-usernames.diff (6438B)


      1 diff --git a/ii.c b/ii.c
      2 index 6583792..f5ed614 100644
      3 --- a/ii.c
      4 +++ b/ii.c
      5 @@ -33,15 +33,23 @@ size_t strlcpy(char *, const char *, size_t);
      6  
      7  enum { TOK_NICKSRV = 0, TOK_USER, TOK_CMD, TOK_CHAN, TOK_ARG, TOK_TEXT, TOK_LAST };
      8  
      9 +typedef struct Nick Nick;
     10 +struct Nick {
     11 +	char name[32];
     12 +	Nick *next;
     13 +};
     14 +
     15  typedef struct Channel Channel;
     16  struct Channel {
     17  	int fdin;
     18  	char name[IRC_CHANNEL_MAX]; /* channel name (normalized) */
     19  	char inpath[PATH_MAX];      /* input path */
     20  	char outpath[PATH_MAX];     /* output path */
     21 +	Nick *nicks;
     22  	Channel *next;
     23  };
     24  
     25 +static void      add_name(Channel *, const char *);
     26  static Channel * channel_add(const char *);
     27  static Channel * channel_find(const char *);
     28  static Channel * channel_join(const char *);
     29 @@ -61,10 +69,14 @@ static void      handle_server_output(int);
     30  static int       isnumeric(const char *);
     31  static void      loginkey(int, const char *);
     32  static void      loginuser(int, const char *, const char *);
     33 +static void      nick_name(const char *, const char *);
     34  static void      proc_channels_input(int, Channel *, char *);
     35  static void      proc_channels_privmsg(int, Channel *, char *);
     36 +static void      proc_names(Channel *, char *);
     37  static void      proc_server_cmd(int, char *);
     38 +static void      quit_name(const char *, const char *, const char *);
     39  static int       read_line(int, char *, size_t);
     40 +static int       rm_name(Channel *, const char *);
     41  static void      run(int, const char *);
     42  static void      setup(void);
     43  static void      sighandler(int);
     44 @@ -236,6 +248,7 @@ channel_new(const char *name)
     45  	c->next = NULL;
     46  	strlcpy(c->name, name, sizeof(c->name));
     47  	channel_normalize_name(c->name);
     48 +	c->nicks = NULL;
     49  
     50  	create_filepath(c->inpath, sizeof(c->inpath), ircpath,
     51  	                channelpath, "in");
     52 @@ -294,6 +307,7 @@ static void
     53  channel_rm(Channel *c)
     54  {
     55  	Channel *p;
     56 +	Nick *n, *nn;
     57  
     58  	if (channels == c) {
     59  		channels = channels->next;
     60 @@ -303,6 +317,10 @@ channel_rm(Channel *c)
     61  		if (p && p->next == c)
     62  			p->next = c->next;
     63  	}
     64 +	for (n = c->nicks; n; n = nn) {
     65 +		nn = n->next;
     66 +		free(n);
     67 +	}
     68  	free(c);
     69  }
     70  
     71 @@ -318,6 +336,70 @@ channel_leave(Channel *c)
     72  	channel_rm(c);
     73  }
     74  
     75 +static void
     76 +add_name(Channel *c, const char *name) {
     77 +	Nick *n;
     78 +	for (n = c->nicks; n; n = n->next)
     79 +		if (!strcmp(name, n->name)) return;
     80 +	if (!(n = calloc(1, sizeof(Nick)))) {
     81 +		fprintf(stderr, "%s: calloc: %s\n", argv0, strerror(errno));
     82 +		exit(1);
     83 +	}
     84 +	strlcpy(n->name, name, sizeof(n->name));
     85 +	n->next = c->nicks;
     86 +	c->nicks = n;
     87 +}
     88 +
     89 +static int
     90 +rm_name(Channel *c, const char *name) {
     91 +	Nick *n, *pn = NULL;
     92 +	for (n = c->nicks; n; pn = n, n = n->next) {
     93 +		if (!strcmp(name, n->name)) {
     94 +			if (pn)
     95 +				pn->next = n->next;
     96 +			else
     97 +				c->nicks = n->next;
     98 +			free(n);
     99 +			return 1;
    100 +		}
    101 +	}
    102 +	return 0;
    103 +}
    104 +
    105 +static void
    106 +proc_names(Channel *c, char *names) {
    107 +	char *p;
    108 +	if (!(p = strtok(names," "))) return;
    109 +	do {
    110 +		if (*p == '@' || *p == '+')
    111 +			p++;
    112 +		add_name(c,p);
    113 +	} while ((p = strtok(NULL," ")));
    114 +}
    115 +
    116 +static void
    117 +quit_name(const char *name, const char *user, const char *text) {
    118 +	Channel *c;
    119 +	for (c = channels; c; c = c->next) {
    120 +		if (rm_name(c, name)) {
    121 +			snprintf(msg, PIPE_BUF, "-!- %s(%s) has quit \"%s\"", name, user, text ? text : "");
    122 +			channel_print(c, msg);
    123 +		}
    124 +	}
    125 +}
    126 +
    127 +static void
    128 +nick_name(const char *old, const char *new) {
    129 +	Channel *c;
    130 +	for (c = channels; c; c = c->next) {
    131 +		if (rm_name(c, old)) {
    132 +			add_name(c, new);
    133 +			snprintf(msg, PIPE_BUF, "-!- %s changed nick to \"%s\"", old, new);
    134 +			channel_print(c, msg);
    135 +		}
    136 +	}
    137 +}
    138 +
    139  static void
    140  loginkey(int ircfd, const char *key)
    141  {
    142 @@ -590,6 +672,15 @@ proc_server_cmd(int fd, char *buf)
    143  		snprintf(msg, sizeof(msg), "PONG %s\r\n", argv[TOK_TEXT]);
    144  		ewritestr(fd, msg);
    145  		return;
    146 +	} else if (!strcmp("353", argv[TOK_CMD])) {
    147 +		p = strtok(argv[TOK_ARG]," ");
    148 +		if (!(p = strtok(NULL," ")))
    149 +			return;
    150 +		snprintf(msg, PIPE_BUF, "%s%s", argv[TOK_ARG] ? argv[TOK_ARG] : "", argv[TOK_TEXT] ? argv[TOK_TEXT] : "");
    151 +		channel_print(channelmaster, msg);
    152 +		if ((c = channel_find(p)))
    153 +			proc_names(c, argv[TOK_TEXT]);
    154 +		return;
    155  	} else if (!argv[TOK_NICKSRV] || !argv[TOK_USER]) {
    156  		/* server command */
    157  		snprintf(msg, sizeof(msg), "%s%s",
    158 @@ -605,9 +696,13 @@ proc_server_cmd(int fd, char *buf)
    159  			argv[TOK_CHAN] = argv[TOK_TEXT];
    160  		snprintf(msg, sizeof(msg), "-!- %s(%s) has joined %s",
    161  				argv[TOK_NICKSRV], argv[TOK_USER], argv[TOK_CHAN]);
    162 +		if ((c = channel_find(argv[TOK_CHAN])))
    163 +			add_name(c, argv[TOK_NICKSRV]);
    164  	} else if (!strcmp("PART", argv[TOK_CMD]) && argv[TOK_CHAN]) {
    165  		snprintf(msg, sizeof(msg), "-!- %s(%s) has left %s",
    166  				argv[TOK_NICKSRV], argv[TOK_USER], argv[TOK_CHAN]);
    167 +		if ((c = channel_find(argv[TOK_CHAN])))
    168 +			rm_name(c, argv[TOK_NICKSRV]);
    169  		/* if user itself leaves, don't write to channel (don't reopen channel). */
    170  		if (!strcmp(argv[TOK_NICKSRV], nick))
    171  			return;
    172 @@ -618,17 +713,18 @@ proc_server_cmd(int fd, char *buf)
    173  				argv[TOK_ARG]  ? argv[TOK_ARG] : "",
    174  				argv[TOK_TEXT] ? argv[TOK_TEXT] : "");
    175  	} else if (!strcmp("QUIT", argv[TOK_CMD])) {
    176 -		snprintf(msg, sizeof(msg), "-!- %s(%s) has quit \"%s\"",
    177 -				argv[TOK_NICKSRV], argv[TOK_USER],
    178 -				argv[TOK_TEXT] ? argv[TOK_TEXT] : "");
    179 +		quit_name(argv[TOK_NICKSRV], argv[TOK_USER], argv[TOK_TEXT]);
    180 +		return;
    181  	} else if (!strncmp("NICK", argv[TOK_CMD], 5) && argv[TOK_TEXT] &&
    182  	          !strcmp(_nick, argv[TOK_TEXT])) {
    183  		strlcpy(nick, _nick, sizeof(nick));
    184  		snprintf(msg, sizeof(msg), "-!- changed nick to \"%s\"", nick);
    185  		channel_print(channelmaster, msg);
    186 +		nick_name(argv[TOK_NICKSRV], argv[TOK_TEXT]);
    187 +		return;
    188  	} else if (!strcmp("NICK", argv[TOK_CMD]) && argv[TOK_TEXT]) {
    189 -		snprintf(msg, sizeof(msg), "-!- %s changed nick to %s",
    190 -				argv[TOK_NICKSRV], argv[TOK_TEXT]);
    191 +		nick_name(argv[TOK_NICKSRV], argv[TOK_TEXT]);
    192 +		return;
    193  	} else if (!strcmp("TOPIC", argv[TOK_CMD])) {
    194  		snprintf(msg, sizeof(msg), "-!- %s changed topic to \"%s\"",
    195  				argv[TOK_NICKSRV],
    196 @@ -637,6 +733,8 @@ proc_server_cmd(int fd, char *buf)
    197  		snprintf(msg, sizeof(msg), "-!- %s kicked %s (\"%s\")",
    198  				argv[TOK_NICKSRV], argv[TOK_ARG],
    199  				argv[TOK_TEXT] ? argv[TOK_TEXT] : "");
    200 +		if ((c = channel_find(argv[TOK_CHAN])))
    201 +			rm_name(c, argv[TOK_ARG]);
    202  	} else if (!strcmp("NOTICE", argv[TOK_CMD])) {
    203  		snprintf(msg, sizeof(msg), "-!- \"%s\")",
    204  				argv[TOK_TEXT] ? argv[TOK_TEXT] : "");