--- CHANGES | 15 ++ ii.1 | 6 +- ii.c | 489 ++++++++++++++++++++++++++++++++++++------------------------= ---- 3 files changed, 297 insertions(+), 213 deletions(-) diff --git a/CHANGES b/CHANGES index 3baaca2..5931c62 100644 --- a/CHANGES +++ b/CHANGES _AT_@ -1,3 +1,18 @@ +1.8 (2014-??-??) + - server host (-s) doesn't default to irc.freenode and is now a requir= ed + parameter. + - remove "in" file when leaving a channel (enabled commented code). + - use IRC_MAX (512), instead of PIPE_BUF (4096) on most systems. + - use C99 and -D_POSIX_C_SOURCE=3D200809L. + - cleanup: + - use arg.h + - use sbase util functions (estrtol, eprintf). + - use OpenBSD strlcpy(). + - style: + - linewrap to 79 characters. + - coding style fixes. + - non-roman numerals for LICENSE period. + 1.7 (2013-01-05) - -k now specifies an environment variable that contains the server key. This behaviour has been changed in order to not diff --git a/ii.1 b/ii.1 index f094cd5..f5d1e61 100644 --- a/ii.1 +++ b/ii.1 _AT_@ -21,8 +21,8 @@ For example if you will join a channel just do echo "/j #= channel" > in and ii creates a new channel directory with in and out file. .SH SYNOPSIS .B ii -.RB [ \-s -.IR servername ] +.RB < \-s +.IR servername > .RB [ \-p .IR port ] .RB [ \-k _AT_@ -37,7 +37,7 @@ and ii creates a new channel directory with in and out fi= le. .SH OPTIONS .TP .BI \-s " servername" -lets you override the default servername (irc.freenode.net) +server to connect to, for example: irc.freenode.net .TP .BI \-p " port" lets you override the default port (6667) diff --git a/ii.c b/ii.c index b710145..e5c80e7 100644 --- a/ii.c +++ b/ii.c _AT_@ -2,15 +2,15 @@ #include <errno.h> #include <netdb.h> #include <sys/types.h> -#include <sys/stat.h> #include <sys/socket.h> #include <sys/select.h> +#include <sys/stat.h> #include <netinet/in.h> +#include <string.h> #include <stdio.h> #include <stdlib.h> #include <limits.h> #include <fcntl.h> -#include <string.h> #include <pwd.h> #include <signal.h> #include <ctype.h> _AT_@ -18,11 +18,12 @@ #include <unistd.h> =20 #include "util.h" -#ifndef PIPE_BUF /* FreeBSD don't know PIPE_BUF */ -#define PIPE_BUF 4096 -#endif -#define PING_TIMEOUT 300 -#define SERVER_PORT 6667 + +#define IRC_CHANNEL_MAX 50 +#define IRC_MSG_MAX 512 +#define PING_TIMEOUT 300 +#define SERVER_PORT 6667 + enum { TOK_NICKSRV =3D 0, TOK_USER, TOK_CMD, TOK_CHAN, TOK_ARG, TOK_TEXT, = TOK_LAST }; =20 typedef struct Channel Channel; _AT_@ -32,39 +33,40 @@ struct Channel { Channel *next; }; =20 -static int irc; -static time_t last_response; +static time_t last_response =3D 0; static Channel *channels =3D NULL; -static char *host =3D "irc.freenode.net"; -static char nick[32]; /* might change while running */ -static char path[_POSIX_PATH_MAX]; -static char message[PIPE_BUF]; /* message buf used for communication */ - -static void usage() { - fputs("ii - irc it - " VERSION "\n" - "(C)opyright MMV-MMVI Anselm R. Garbe\n" - "(C)opyright MMV-MMXI Nico Golde\n" - "usage: ii [-i <irc dir>] [-s <host>] [-p <port>]\n" - " [-n <nick>] [-k <password>] [-f <fullname>]\n", stderr); - exit(EXIT_FAILURE); +static char nick[32] =3D ""; /* might change while running */ +static char path[_POSIX_PATH_MAX] =3D ""; /* irc dir (-i) */ +static char msg[IRC_MSG_MAX] =3D ""; /* message buf used for communication= */ + +static void +usage(void) { + eprintf("ii-" VERSION ", =C2=A9 2005-2014 ii engineers, see LICENSE for d= etails\n" + "usage: %s <-s host> [-i <irc dir>] [-p <port>]\n" + " [-n <nick>] [-k <password>] [-f <fullname>]\n", argv0); } =20 -static char *striplower(char *s) { +static char * +striplower(char *s) { char *p =3D NULL; + for(p =3D s; p && *p; p++) { - if(*p =3D=3D '/') *p =3D ','; + if(*p =3D=3D '/') + *p =3D ','; *p =3D tolower(*p); } return s; } =20 /* creates directories top-down, if necessary */ -static void create_dirtree(const char *dir) { - char tmp[256]; +static void +create_dirtree(const char *dir) { + char tmp[_POSIX_PATH_MAX]; char *p =3D NULL; size_t len; - snprintf(tmp, sizeof(tmp),"%s",dir); - len =3D strlen(tmp); + + strlcpy(tmp, dir, sizeof(tmp)); + len =3D strnlen(tmp, sizeof(tmp)); if(tmp[len - 1] =3D=3D '/') tmp[len - 1] =3D 0; for(p =3D tmp + 1; *p; p++) _AT_@ -76,9 +78,11 @@ static void create_dirtree(const char *dir) { mkdir(tmp, S_IRWXU); } =20 -static int get_filepath(char *filepath, size_t len, char *channel, char *f= ile) { +/* TODO: dont call create_dirtree() in get_filepath() ? */ +static int +get_filepath(char *filepath, size_t len, char *channel, char *file) { if(channel) { - if(!snprintf(filepath, len, "%s/%s", path, channel)) + if(snprintf(filepath, len, "%s/%s", path, channel) <=3D 0) return 0; create_dirtree(filepath); return snprintf(filepath, len, "%s/%s/%s", path, channel, file); _AT_@ -86,22 +90,24 @@ static int get_filepath(char *filepath, size_t len, cha= r *channel, char *file) { return snprintf(filepath, len, "%s/%s", path, file); } =20 -static void create_filepath(char *filepath, size_t len, char *channel, cha= r *suffix) { - if(!get_filepath(filepath, len, striplower(channel), suffix)) { - fputs("ii: path to irc directory too long\n", stderr); - exit(EXIT_FAILURE); - } +static void +create_filepath(char *filepath, size_t len, char *channel, char *suffix) { + if(get_filepath(filepath, len, striplower(channel), suffix) <=3D 0) + eprintf("path to irc directory too long"); } =20 -static int open_channel(char *name) { - static char infile[256]; +static int +open_channel(char *name) { + char infile[_POSIX_PATH_MAX]; + create_filepath(infile, sizeof(infile), name, "in"); if(access(infile, F_OK) =3D=3D -1) mkfifo(infile, S_IRWXU); return open(infile, O_RDONLY | O_NONBLOCK, 0); } =20 -static void add_channel(char *cname) { +static void +add_channel(char *cname) { Channel *c; int fd; char *name =3D striplower(cname); _AT_@ -111,16 +117,14 @@ static void add_channel(char *cname) { return; /* already handled */ =20 fd =3D open_channel(name); - if(fd =3D=3D -1) { - printf("ii: exiting, cannot create in channel: %s\n", name); - exit(EXIT_FAILURE); - } - c =3D calloc(1, sizeof(Channel)); - if(!c) { - perror("ii: cannot allocate memory"); - exit(EXIT_FAILURE); - } - if(!channels) channels =3D c; + if(fd =3D=3D -1) + eprintf("exiting, cannot create in channel: %s:", name); + + if(!(c =3D calloc(1, sizeof(Channel)))) + eprintf("cannot allocate memory:"); + + if(!channels) + channels =3D c; else { c->next =3D channels; channels =3D c; _AT_@ -129,63 +133,70 @@ static void add_channel(char *cname) { c->name =3D strdup(name); } =20 -static void rm_channel(Channel *c) { +static void +rm_channel(Channel *c) { Channel *p; - if(channels =3D=3D c) channels =3D channels->next; + + if(channels =3D=3D c) + channels =3D channels->next; else { for(p =3D channels; p && p->next !=3D c; p =3D p->next); if(p->next =3D=3D c) p->next =3D c->next; } free(c->name); + c->name =3D NULL; free(c); } =20 -static void login(char *key, char *fullname) { - if(key) snprintf(message, PIPE_BUF, - "PASS %s\r\nNICK %s\r\nUSER %s localhost %s :%s\r\n", key, - nick, nick, host, fullname ? fullname : nick); - else snprintf(message, PIPE_BUF, "NICK %s\r\nUSER %s localhost %s :%s\r\n= ", - nick, nick, host, fullname ? fullname : nick); - write(irc, message, strlen(message)); /* login */ +static void +login(int fd, char *host, char *key, char *fullname) { + if(key) + snprintf(msg, sizeof(msg), + "PASS %s\r\nNICK %s\r\nUSER %s localhost %s :%s\r\n", key, + nick, nick, host, fullname); + else + snprintf(msg, sizeof(msg), "NICK %s\r\nUSER %s localhost %s :%s\r\n", + nick, nick, host, fullname); + write(fd, msg, strnlen(msg, sizeof(msg))); } =20 -static int tcpopen(unsigned short port) { +static int +tcpopen(const char *host, unsigned short port) { int fd; struct sockaddr_in sin; - struct hostent *hp =3D gethostbyname(host); + struct hostent *hp; =20 + if(!(hp =3D gethostbyname(host))) + eprintf("cannot retrieve host information:"); memset(&sin, 0, sizeof(struct sockaddr_in)); - if(!hp) { - perror("ii: cannot retrieve host information"); - exit(EXIT_FAILURE); - } sin.sin_family =3D AF_INET; - memcpy(&sin.sin_addr, hp->h_addr, hp->h_length); + /* TODO: don't use h_addr or h_addr_list here, but getaddrinfo() */ + memcpy(&sin.sin_addr, hp->h_addr_list[0], hp->h_length); sin.sin_port =3D htons(port); - if((fd =3D socket(AF_INET, SOCK_STREAM, 0)) < 0) { - perror("ii: cannot create socket"); - exit(EXIT_FAILURE); - } - if(connect(fd, (const struct sockaddr *) &sin, sizeof(sin)) < 0) { - perror("ii: cannot connect to host"); - exit(EXIT_FAILURE); - } + if((fd =3D socket(AF_INET, SOCK_STREAM, 0)) < 0) + eprintf("cannot create socket:"); + + if(connect(fd, (const struct sockaddr *) &sin, sizeof(sin)) < 0) + eprintf("cannot connect to host:"); + return fd; } =20 -static size_t tokenize(char **result, size_t reslen, char *str, char delim= ) { +static size_t +tokenize(char **result, size_t reslen, char *str, char delim) { char *p =3D NULL, *n =3D NULL; - size_t i; + size_t i =3D 0; =20 if(!str) return 0; for(n =3D str; *n =3D=3D ' '; n++); p =3D n; - for(i =3D 0; *n !=3D 0;) { - if(i =3D=3D reslen) + while(*n !=3D 0) { + if(i >=3D reslen) return 0; - if(i > TOK_CHAN - TOK_CMD && strtol(result[0], NULL, 10) > 0) delim=3D':= '; /* workaround non-RFC compliant messages */ + if(i > TOK_CHAN - TOK_CMD && strtol(result[0], NULL, 10) > 0) + delim =3D ':'; /* workaround non-RFC compliant messages */ if(*n =3D=3D delim) { *n =3D 0; result[i++] =3D p; _AT_@ -193,124 +204,138 @@ static size_t tokenize(char **result, size_t reslen= , char *str, char delim) { } else n++; } - if(i<reslen && p < n && strlen(p)) + if(i < reslen && p < n && p && *p) result[i++] =3D p; - return i; /* number of tokens */ + return i; /* number of tokens */ } =20 -static void print_out(char *channel, char *buf) { - static char outfile[256], server[256], buft[18]; +static void +print_out(char *channel, char *buf) { + char outfile[_POSIX_PATH_MAX], server[IRC_CHANNEL_MAX + 6], buft[18]; FILE *out =3D NULL; - time_t t =3D time(0); + time_t t =3D time(NULL); =20 - if(channel) snprintf(server, sizeof(server), "-!- %s", channel); - if(strstr(buf, server)) channel=3D""; + if(channel) + snprintf(server, sizeof(server), "-!- %s", channel); + if(strstr(buf, server)) + channel =3D ""; create_filepath(outfile, sizeof(outfile), channel, "out"); - if(!(out =3D fopen(outfile, "a"))) return; - if(channel && channel[0]) add_channel(channel); + if(!(out =3D fopen(outfile, "a"))) + return; + if(channel && channel[0]) + add_channel(channel); =20 strftime(buft, sizeof(buft), "%F %R", localtime(&t)); fprintf(out, "%s %s\n", buft, buf); fclose(out); } =20 -static void proc_channels_privmsg(char *channel, char *buf) { - snprintf(message, PIPE_BUF, "<%s> %s", nick, buf); - print_out(channel, message); - snprintf(message, PIPE_BUF, "PRIVMSG %s :%s\r\n", channel, buf); - write(irc, message, strlen(message)); +static void +proc_channels_privmsg(int fd, char *channel, char *buf) { + snprintf(msg, sizeof(msg), "<%s> %s", nick, buf); + print_out(channel, msg); + snprintf(msg, sizeof(msg), "PRIVMSG %s :%s\r\n", channel, buf); + write(fd, msg, strnlen(msg, sizeof(msg))); } =20 -static void proc_channels_input(Channel *c, char *buf) { - /* static char infile[256]; */ +static void +proc_channels_input(Channel *c, char *buf) { + char infile[_POSIX_PATH_MAX]; char *p =3D NULL; + size_t buflen; =20 if(buf[0] !=3D '/' && buf[0] !=3D 0) { - proc_channels_privmsg(c->name, buf); + proc_channels_privmsg(c->fd, c->name, buf); return; } - message[0] =3D '\0'; - if(buf[2] =3D=3D ' ' || buf[2] =3D=3D '\0') switch (buf[1]) { + msg[0] =3D '\0'; + if(buf[2] =3D=3D ' ' || buf[2] =3D=3D '\0') { + buflen =3D strlen(buf); + switch(buf[1]) { case 'j': p =3D strchr(&buf[3], ' '); - if(p) *p =3D 0; - if((buf[3]=3D=3D'#')||(buf[3]=3D=3D'&')||(buf[3]=3D=3D'+')||(buf[3]=3D= =3D'!')){ - if(p) snprintf(message, PIPE_BUF, "JOIN %s %s\r\n", &buf[3], p + 1); /= * password protected channel */ - else snprintf(message, PIPE_BUF, "JOIN %s\r\n", &buf[3]); + if(p) + *p =3D 0; + if((buf[3] =3D=3D '#') || (buf[3] =3D=3D '&') || (buf[3] =3D=3D '+') || + (buf[3] =3D=3D '!')) + { + /* password protected channel */ + if(p) + snprintf(msg, sizeof(msg), "JOIN %s %s\r\n", &buf[3], p + 1); + else + snprintf(msg, sizeof(msg), "JOIN %s\r\n", &buf[3]); add_channel(&buf[3]); } - else if(p){ + else if(p) { add_channel(&buf[3]); - proc_channels_privmsg(&buf[3], p + 1); + proc_channels_privmsg(c->fd, &buf[3], p + 1); return; } break; case 't': - if(strlen(buf)>=3D3) snprintf(message, PIPE_BUF, "TOPIC %s :%s\r\n", c-= >name, &buf[3]); + if(buflen >=3D 3) + snprintf(msg, sizeof(msg), "TOPIC %s :%s\r\n", c->name, &buf[3]); break; case 'a': - if(strlen(buf)>=3D3){ - snprintf(message, PIPE_BUF, "-!- %s is away \"%s\"", nick, &buf[3]); - print_out(c->name, message); + if(buflen >=3D 3) { + snprintf(msg, sizeof(msg), "-!- %s is away \"%s\"", nick, &buf[3]); + print_out(c->name, msg); } - if(buf[2] =3D=3D 0 || strlen(buf)<3) /* or used to make else part safe = */ - snprintf(message, PIPE_BUF, "AWAY\r\n"); + if(buflen < 3) + snprintf(msg, sizeof(msg), "AWAY\r\n"); else - snprintf(message, PIPE_BUF, "AWAY :%s\r\n", &buf[3]); + snprintf(msg, sizeof(msg), "AWAY :%s\r\n", &buf[3]); break; case 'n': - if(strlen(buf)>=3D3){ - snprintf(nick, sizeof(nick),"%s", &buf[3]); - snprintf(message, PIPE_BUF, "NICK %s\r\n", &buf[3]); + if(buflen >=3D 3) { + strlcpy(nick, &buf[3], sizeof(nick)); + snprintf(msg, sizeof(msg), "NICK %s\r\n", &buf[3]); } break; case 'l': if(c->name[0] =3D=3D 0) return; - if(buf[2] =3D=3D ' ' && strlen(buf)>=3D3) - snprintf(message, PIPE_BUF, "PART %s :%s\r\n", c->name, &buf[3]); + if(buf[2] =3D=3D ' ' && buflen >=3D 3) + snprintf(msg, sizeof(msg), "PART %s :%s\r\n", c->name, &buf[3]); else - snprintf(message, PIPE_BUF, - "PART %s :ii - 500 SLOC are too much\r\n", c->name); - write(irc, message, strlen(message)); + snprintf(msg, sizeof(msg), + "PART %s :ii - 500 SLOC are too much\r\n", c->name); + write(c->fd, msg, strnlen(msg, sizeof(msg))); close(c->fd); - /*create_filepath(infile, sizeof(infile), c->name, "in"); - unlink(infile); */ + /* TODO: dont create directory before deleting in file + * just try to delete it immediately */ + create_filepath(infile, sizeof(infile), c->name, "in"); + unlink(infile); rm_channel(c); return; break; default: - snprintf(message, PIPE_BUF, "%s\r\n", &buf[1]); + snprintf(msg, sizeof(msg), "%s\r\n", &buf[1]); break; } + } else - snprintf(message, PIPE_BUF, "%s\r\n", &buf[1]); + snprintf(msg, sizeof(msg), "%s\r\n", &buf[1]); =20 - if (message[0] !=3D '\0') - write(irc, message, strlen(message)); + if(msg[0] !=3D '\0') + write(c->fd, msg, strnlen(msg, sizeof(msg))); } =20 -static void proc_server_cmd(char *buf) { +static void +proc_server_cmd(int fd, char *buf) { char *argv[TOK_LAST], *cmd =3D NULL, *p =3D NULL; - int i; + unsigned int i; =20 - if(!buf || *buf=3D=3D'\0') + if(!buf || *buf =3D=3D '\0') return; =20 for(i =3D 0; i < TOK_LAST; i++) argv[i] =3D NULL; - /* <message> ::=3D [':' <prefix> <SPACE> ] <command> <params> <crlf> - <prefix> ::=3D <servername> | <nick> [ '!' <user> ] [ '_AT_' <host> ] - <command> ::=3D <letter> { <letter> } | <number> <number> <number> - <SPACE> ::=3D ' ' { ' ' } - <params> ::=3D <SPACE> [ ':' <trailing> | <middle> <params> ] - <middle> ::=3D <Any *non-empty* sequence of octets not including SPA= CE - or NUL or CR or LF, the first of which may not be ':'> - <trailing> ::=3D <Any, possibly *empty*, sequence of octets not includ= ing NUL or CR or LF> - <crlf> ::=3D CR LF */ - - if(buf[0] =3D=3D ':') { /* check prefix */ - if (!(p =3D strchr(buf, ' '))) return; + + /* check prefix */ + if(buf[0] =3D=3D ':') { + if (!(p =3D strchr(buf, ' '))) + return; *p =3D 0; for(++p; *p =3D=3D ' '; p++); cmd =3D p; _AT_@ -337,59 +362,84 @@ static void proc_server_cmd(char *buf) { if(!argv[TOK_CMD] || !strncmp("PONG", argv[TOK_CMD], 5)) { return; } else if(!strncmp("PING", argv[TOK_CMD], 5)) { - snprintf(message, PIPE_BUF, "PONG %s\r\n", argv[TOK_TEXT]); - write(irc, message, strlen(message)); + snprintf(msg, sizeof(msg), "PONG %s\r\n", argv[TOK_TEXT]); + write(fd, msg, strnlen(msg, sizeof(msg))); return; - } else if(!argv[TOK_NICKSRV] || !argv[TOK_USER]) { /* server command */ - snprintf(message, PIPE_BUF, "%s%s", argv[TOK_ARG] ? argv[TOK_ARG] : "", = argv[TOK_TEXT] ? argv[TOK_TEXT] : ""); - print_out(0, message); + } else if(!argv[TOK_NICKSRV] || !argv[TOK_USER]) { + /* server command */ + snprintf(msg, sizeof(msg), "%s%s", + argv[TOK_ARG] ? argv[TOK_ARG] : "", + argv[TOK_TEXT] ? argv[TOK_TEXT] : ""); + print_out(0, msg); return; } else if(!strncmp("ERROR", argv[TOK_CMD], 6)) - snprintf(message, PIPE_BUF, "-!- error %s", argv[TOK_TEXT] ? argv[TOK_TE= XT] : "unknown"); + snprintf(msg, sizeof(msg), "-!- error %s", + argv[TOK_TEXT] ? argv[TOK_TEXT] : "unknown"); else if(!strncmp("JOIN", argv[TOK_CMD], 5)) { if (argv[TOK_TEXT] !=3D NULL) argv[TOK_CHAN] =3D argv[TOK_TEXT]; - snprintf(message, PIPE_BUF, "-!- %s(%s) has joined %s", argv[TOK_NICKSRV= ], argv[TOK_USER], argv[TOK_CHAN]); + snprintf(msg, sizeof(msg), "-!- %s(%s) has joined %s", + argv[TOK_NICKSRV],argv[TOK_USER], argv[TOK_CHAN]); } else if(!strncmp("PART", argv[TOK_CMD], 5)) { - snprintf(message, PIPE_BUF, "-!- %s(%s) has left %s", argv[TOK_NICKSRV],= argv[TOK_USER], argv[TOK_CHAN]); + snprintf(msg, sizeof(msg), "-!- %s(%s) has left %s", + argv[TOK_NICKSRV], argv[TOK_USER], argv[TOK_CHAN]); } else if(!strncmp("MODE", argv[TOK_CMD], 5)) - snprintf(message, PIPE_BUF, "-!- %s changed mode/%s -> %s %s", argv[TOK_= NICKSRV], argv[TOK_CMD + 1] ? argv[TOK_CMD + 1] : "" , argv[TOK_CMD + 2]? a= rgv[TOK_CMD + 2] : "", argv[TOK_CMD + 3] ? argv[TOK_CMD + 3] : ""); + snprintf(msg, sizeof(msg), "-!- %s changed mode/%s -> %s %s", + argv[TOK_NICKSRV], + argv[TOK_CMD + 1] ? argv[TOK_CMD + 1] : "", + argv[TOK_CMD + 2] ? argv[TOK_CMD + 2] : "", + argv[TOK_CMD + 3] ? argv[TOK_CMD + 3] : ""); else if(!strncmp("QUIT", argv[TOK_CMD], 5)) - snprintf(message, PIPE_BUF, "-!- %s(%s) has quit \"%s\"", argv[TOK_NICKS= RV], argv[TOK_USER], argv[TOK_TEXT] ? argv[TOK_TEXT] : ""); + snprintf(msg, sizeof(msg), "-!- %s(%s) has quit \"%s\"", + argv[TOK_NICKSRV], argv[TOK_USER], + argv[TOK_TEXT] ? argv[TOK_TEXT] : ""); else if(!strncmp("NICK", argv[TOK_CMD], 5)) - snprintf(message, PIPE_BUF, "-!- %s changed nick to %s", argv[TOK_NICKSR= V], argv[TOK_TEXT]); + snprintf(msg, sizeof(msg), "-!- %s changed nick to %s", + argv[TOK_NICKSRV], argv[TOK_TEXT]); else if(!strncmp("TOPIC", argv[TOK_CMD], 6)) - snprintf(message, PIPE_BUF, "-!- %s changed topic to \"%s\"", argv[TOK_N= ICKSRV], argv[TOK_TEXT] ? argv[TOK_TEXT] : ""); + snprintf(msg, sizeof(msg), "-!- %s changed topic to \"%s\"", + argv[TOK_NICKSRV], + argv[TOK_TEXT] ? argv[TOK_TEXT] : ""); else if(!strncmp("KICK", argv[TOK_CMD], 5)) - snprintf(message, PIPE_BUF, "-!- %s kicked %s (\"%s\")", argv[TOK_NICKSR= V], argv[TOK_ARG], argv[TOK_TEXT] ? argv[TOK_TEXT] : ""); + snprintf(msg, sizeof(msg), "-!- %s kicked %s (\"%s\")", + argv[TOK_NICKSRV], argv[TOK_ARG], + argv[TOK_TEXT] ? argv[TOK_TEXT] : ""); else if(!strncmp("NOTICE", argv[TOK_CMD], 7)) - snprintf(message, PIPE_BUF, "-!- \"%s\")", argv[TOK_TEXT] ? argv[TOK_TEX= T] : ""); + snprintf(msg, sizeof(msg), "-!- \"%s\")", + argv[TOK_TEXT] ? argv[TOK_TEXT] : ""); else if(!strncmp("PRIVMSG", argv[TOK_CMD], 8)) - snprintf(message, PIPE_BUF, "<%s> %s", argv[TOK_NICKSRV], argv[TOK_TEXT]= ? argv[TOK_TEXT] : ""); + snprintf(msg, sizeof(msg), "<%s> %s", argv[TOK_NICKSRV], + argv[TOK_TEXT] ? argv[TOK_TEXT] : ""); + if(!argv[TOK_CHAN] || !strncmp(argv[TOK_CHAN], nick, strlen(nick))) - print_out(argv[TOK_NICKSRV], message); + print_out(argv[TOK_NICKSRV], msg); else - print_out(argv[TOK_CHAN], message); + print_out(argv[TOK_CHAN], msg); } =20 -static int read_line(int fd, size_t res_len, char *buf) { +static int +read_line(int fd, char *buf, size_t bufsiz) { size_t i =3D 0; char c =3D 0; - do { + + for(i =3D 0; c !=3D '\n' && i < bufsiz; i++) { if(read(fd, &c, sizeof(char)) !=3D sizeof(char)) return -1; - buf[i++] =3D c; + buf[i] =3D c; } - while(c !=3D '\n' && i < res_len); - buf[i - 1] =3D 0; /* eliminates '\n' */ + if(i > 0 && i < bufsiz) + buf[i - 1] =3D 0; /* eliminates '\n' */ return 0; } =20 -static void handle_channels_input(Channel *c) { - static char buf[PIPE_BUF]; - if(read_line(c->fd, PIPE_BUF, buf) =3D=3D -1) { +static void +handle_channels_input(Channel *c) { + char buf[BUFSIZ] =3D ""; + int fd; + + if(read_line(c->fd, buf, sizeof(buf)) =3D=3D -1) { close(c->fd); - int fd =3D open_channel(c->name); + fd =3D open_channel(c->name); if(fd !=3D -1) c->fd =3D fd; else _AT_@ -399,27 +449,28 @@ static void handle_channels_input(Channel *c) { proc_channels_input(c, buf); } =20 -static void handle_server_output() { - static char buf[PIPE_BUF]; - if(read_line(irc, PIPE_BUF, buf) =3D=3D -1) { - perror("ii: remote host closed connection"); - exit(EXIT_FAILURE); - } - proc_server_cmd(buf); +static void +handle_server_output(int fd) { + char buf[BUFSIZ] =3D ""; + + if(read_line(fd, buf, sizeof(buf)) =3D=3D -1) + eprintf("remote host closed connection:"); + proc_server_cmd(fd, buf); } =20 -static void run() { +static void +run(int fd, char *host) { Channel *c; int r, maxfd; fd_set rd; struct timeval tv; - char ping_msg[512]; + char ping_msg[IRC_MSG_MAX]; =20 snprintf(ping_msg, sizeof(ping_msg), "PING %s\r\n", host); for(;;) { FD_ZERO(&rd); - maxfd =3D irc; - FD_SET(irc, &rd); + maxfd =3D fd; + FD_SET(fd, &rd); for(c =3D channels; c; c =3D c->next) { if(maxfd < c->fd) maxfd =3D c->fd; _AT_@ -432,18 +483,17 @@ static void run() { if(r < 0) { if(errno =3D=3D EINTR) continue; - perror("ii: error on select()"); - exit(EXIT_FAILURE); + eprintf("error on select():"); } else if(r =3D=3D 0) { if(time(NULL) - last_response >=3D PING_TIMEOUT) { print_out(NULL, "-!- ii shutting down: ping timeout"); exit(EXIT_FAILURE); } - write(irc, ping_msg, strlen(ping_msg)); + write(fd, ping_msg, strnlen(ping_msg, sizeof(ping_msg))); continue; } - if(FD_ISSET(irc, &rd)) { - handle_server_output(); + if(FD_ISSET(fd, &rd)) { + handle_server_output(fd); last_response =3D time(NULL); } for(c =3D channels; c; c =3D c->next) _AT_@ -452,42 +502,61 @@ static void run() { } } =20 -int main(int argc, char *argv[]) { - int i; - unsigned short port =3D SERVER_PORT; - struct passwd *spw =3D getpwuid(getuid()); - char *key =3D NULL, *fullname =3D NULL; +int +main(int argc, char *argv[]) { + struct passwd *spw; + long port =3D SERVER_PORT; + char *key =3D NULL, *fullname =3D NULL, *host =3D ""; char prefix[_POSIX_PATH_MAX]; + int ircfd; =20 - if(!spw) { - fputs("ii: getpwuid() failed\n", stderr); - exit(EXIT_FAILURE); - } - snprintf(nick, sizeof(nick), "%s", spw->pw_name); - snprintf(prefix, sizeof(prefix),"%s/irc", spw->pw_dir); - if (argc <=3D 1 || (argc =3D=3D 2 && argv[1][0] =3D=3D '-' && argv[1][1] = =3D=3D 'h')) usage(); - - for(i =3D 1; (i + 1 < argc) && (argv[i][0] =3D=3D '-'); i++) { - switch (argv[i][1]) { - case 'i': snprintf(prefix,sizeof(prefix),"%s", argv[++i]); break; - case 's': host =3D argv[++i]; break; - case 'p': port =3D strtol(argv[++i], NULL, 10); break; - case 'n': snprintf(nick,sizeof(nick),"%s", argv[++i]); break; - case 'k': key =3D getenv(argv[++i]); break; - case 'f': fullname =3D argv[++i]; break; - default: usage(); break; - } - } - irc =3D tcpopen(port); - if(!snprintf(path, sizeof(path), "%s/%s", prefix, host)) { - fputs("ii: path to irc directory too long\n", stderr); - exit(EXIT_FAILURE); - } + /* use nickname of user and homedir for irc running ii by default */ + if(!(spw =3D getpwuid(getuid()))) + eprintf("getpwuid() failed:"); + + strlcpy(nick, spw->pw_name, sizeof(nick)); + snprintf(prefix, sizeof(prefix), "%s/irc", spw->pw_dir); + + ARGBEGIN { + case 'h': + case 'v': + usage(); + break; + case 'i': + strlcpy(prefix, EARGF(usage()), sizeof(prefix)); + break; + case 's': + host =3D EARGF(usage()); + break; + case 'p': + port =3D estrtol(EARGF(usage()), 10); + break; + case 'n': + strlcpy(nick, EARGF(usage()), sizeof(nick)); + break; + case 'k': + if(!(key =3D getenv(EARGF(usage())))) + eprintf("can't get password from $%s", key); + break; + case 'f': + fullname =3D EARGF(usage()); + break; + default: + usage(); + break; + } ARGEND; + + if (argc < 1 || !*host) + usage(); + + ircfd =3D tcpopen(host, port); + if(snprintf(path, sizeof(path), "%s/%s", prefix, host) <=3D 0) + eprintf("path to irc directory too long"); create_dirtree(path); =20 add_channel(""); /* master channel */ - login(key, fullname); - run(); + login(ircfd, host, key, fullname ? fullname : nick); + run(ircfd, host); =20 return EXIT_SUCCESS; } --=20 2.4.10 --Multipart=_Mon__9_May_2016_17_21_10_+0200_I.6cpFVydhq75aaE Content-Type: text/x-diff; name="0009-check-if-fullname-is-set-and-non-empty.patch" Content-Disposition: attachment; filename="0009-check-if-fullname-is-set-and-non-empty.patch" Content-Transfer-Encoding: 7bitReceived on Mon Sep 17 2001 - 00:00:00 CEST
This archive was generated by hypermail 2.3.0 : Mon May 09 2016 - 17:24:22 CEST