From ce05175372a9ddca1a225db0765ace1127a39293 Mon Sep 17 00:00:00 2001 From: Nicholas Date: Fri, 12 Nov 2021 09:22:01 -0800 Subject: chore: simplified organizational structure --- sys/cmd/ic/LICENSE | 23 -- sys/cmd/ic/ic.1 | 100 ------ sys/cmd/ic/ic.c | 878 --------------------------------------------------- sys/cmd/ic/rules.mk | 14 - sys/cmd/ic/strlcpy.c | 32 -- 5 files changed, 1047 deletions(-) delete mode 100644 sys/cmd/ic/LICENSE delete mode 100644 sys/cmd/ic/ic.1 delete mode 100644 sys/cmd/ic/ic.c delete mode 100644 sys/cmd/ic/rules.mk delete mode 100644 sys/cmd/ic/strlcpy.c (limited to 'sys/cmd/ic') diff --git a/sys/cmd/ic/LICENSE b/sys/cmd/ic/LICENSE deleted file mode 100644 index a5816a8..0000000 --- a/sys/cmd/ic/LICENSE +++ /dev/null @@ -1,23 +0,0 @@ -MIT/X Consortium License - -(C)opyright 2014-2018 Hiltjo Posthuma -(C)opyright 2005-2006 Anselm R. Garbe -(C)opyright 2005-2011 Nico Golde - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the "Software"), -to deal in the Software without restriction, including without limitation -the rights to use, copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/sys/cmd/ic/ic.1 b/sys/cmd/ic/ic.1 deleted file mode 100644 index 3302dad..0000000 --- a/sys/cmd/ic/ic.1 +++ /dev/null @@ -1,100 +0,0 @@ -.TH II 1 ic\-VERSION -.SH NAME -ic \- irc it or irc improved -.SH DESCRIPTION -.B ic -is a minimalistic FIFO and filesystem based IRC client. -It creates an irc directory tree with server, channel and -nick name directories. -In every directory a FIFO file (in) and normal file (out) -is placed. This will be for example ~/irc/irc.freenode.net/. -The in file is used to communicate with the servers and the out -files includes the server messages. For every channel and every nick -name there will be new in and out files. -The basic idea of this is to be able to communicate with an IRC -server with basic command line tools. -For example if you will join a channel just do echo "/j #channel" > in -and ic creates a new channel directory with in and out file. -.SH SYNOPSIS -.B ic -.RB < \-s -.IR servername > -.RB [ \-p -.IR port ] -.RB [ \-k -.IR "environment variable" ] -.RB [ \-i -.IR prefix ] -.RB [ \-n -.IR nickname ] -.RB [ \-f -.IR realname ] -.RB < \-u -.IR sockname > -.SH OPTIONS -.TP -.BI \-s " servername" -server to connect to, for example: irc.freenode.net -.TP -.BI \-u " sockname" -connect to a UNIX domain socket instead of directly to a server. -.TP -.BI \-p " port" -lets you override the default port (6667) -.TP -.BI \-k " environment variable" -lets you specify an environment variable that contains your IRC password, e.g. IIPASS="foobar" ic -k IIPASS. -This is done in order to prevent other users from eavesdropping the server password via the process list. -.TP -.BI \-i " prefix" -lets you override the default irc path (~/irc) -.TP -.BI \-n " nickname" -lets you override the default nick ($USER) -.TP -.BI \-f " realname" -lets you specify your real name associated with your nick -.SH DIRECTORIES -.TP -.B ~/irc -In this directory the irc tree will be created. In this directory you -will find a directory for your server (default: irc.freenode.net) in -which the FIFO and the output file will be stored. -If you join a channel a new directory with the name of the channel -will be created in the ~/irc/$servername/ directory. -.SH COMMANDS -.TP -.BI /a " []" -mark yourself as away -.TP -.BI /j " #channel/nickname []" -join a channel or open private conversation with user -.TP -.BI /l " [reason]" -leave a channel or query -.TP -.BI /n " nick" -change the nick name -.TP -.BI /q " [reason]" -quit ic -.TP -.BI /t " topic" -set the topic of a channel -.SH RAW COMMANDS -.LP -Everything which is not a command will be posted into the channel or to the server. -So if you need /who just write /WHO as described in RFC#1459 to the server in FIFO. -.SH SSL PROTOCOL SUPPORT -.LP -For TLS/SSL protocol support you can connect to a local tunnel, for example with stunnel or socat. -.SH CONTACT -.LP -Subscribe to the mailinglist and write to dev (at) suckless (dot) org for suggestions, fixes, etc. -.SH AUTHORS -ic engineers, see LICENSE file -.SH SEE ALSO -.BR echo (1), -.BR tail (1) -.SH BUGS -Please report them! diff --git a/sys/cmd/ic/ic.c b/sys/cmd/ic/ic.c deleted file mode 100644 index 7fc37d8..0000000 --- a/sys/cmd/ic/ic.c +++ /dev/null @@ -1,878 +0,0 @@ -/* See LICENSE file for license details. */ -#include -#include - -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -size_t strlcpy(char *, const char *, size_t); - -#define IRC_CHANNEL_MAX 200 -#define IRC_MSG_MAX 512 /* guaranteed to be <= than PIPE_BUF */ -#define PING_TIMEOUT 300 - -enum { TOK_NICKSRV = 0, TOK_USER, TOK_CMD, TOK_CHAN, TOK_ARG, TOK_TEXT, TOK_LAST }; - -typedef struct Channel Channel; -struct Channel { - int fdin; - char name[IRC_CHANNEL_MAX]; /* channel name (normalized) */ - char inpath[PATH_MAX]; /* input path */ - char outpath[PATH_MAX]; /* output path */ - Channel *next; -}; - -static Channel * channel_add(const char *); -static Channel * channel_find(const char *); -static Channel * channel_join(const char *); -static void channel_leave(Channel *); -static Channel * channel_new(const char *); -static void channel_normalize_name(char *); -static void channel_normalize_path(char *); -static int channel_open(Channel *); -static void channel_print(Channel *, const char *); -static int channel_reopen(Channel *); -static void channel_rm(Channel *); - -static void create_dirtree(const char *); -static void create_filepath(char *, size_t, const char *, const char *, const char *); -static void ewritestr(int, const char *); -static void handle_channels_input(int, Channel *); -static void handle_server_output(int); -static int isnumeric(const char *); -static void loginkey(int, const char *); -static void loginuser(int, const char *, const char *); -static void proc_channels_input(int, Channel *, char *); -static void proc_channels_privmsg(int, Channel *, char *); -static void proc_server_cmd(int, char *); -static int read_line(int, char *, size_t); -static void run(int, const char *); -static void setup(void); -static void sighandler(int); -static int tcpopen(const char *, const char *); -static size_t tokenize(char **, size_t, char *, int); -static int udsopen(const char *); -static void usage(void); - -static int isrunning = 1; -static time_t last_response = 0; -static Channel *channels = nil; -static Channel *channelmaster = nil; -static char nick[32], _nick[arrlen(nick)]; /* active nickname at runtime */ -static char ircpath[PATH_MAX]; /* irc dir (-i) */ -static char msg[IRC_MSG_MAX]; /* message buf used for communication */ - -static -void -usage(void) -{ - fprintf(stderr, "usage: %s <-s host> [-i ] [-p ] " - "[-u ] [-n ] [-k ] " - "[-f ]\n", argv0); - exit(1); -} - -static -void -ewritestr(int fd, const char *s) -{ - size_t len, off = 0; - int w = -1; - - len = strlen(s); - for (off = 0; off < len; off += w) { - if ((w = write(fd, s + off, len - off)) == -1) - break; - off += w; - } - if (w == -1) { - fprintf(stderr, "%s: write: %s\n", argv0, strerror(errno)); - exit(1); - } -} - -/* creates directories bottom-up, if necessary */ -static -void -create_dirtree(const char *dir) -{ - char tmp[PATH_MAX], *p; - struct stat st; - size_t len; - - strlcpy(tmp, dir, sizeof(tmp)); - len = strlen(tmp); - if (len > 0 && tmp[len - 1] == '/') - tmp[len - 1] = '\0'; - - if ((stat(tmp, &st) != -1) && S_ISDIR(st.st_mode)) - return; /* dir exists */ - - for (p = tmp + 1; *p; p++) { - if (*p != '/') - continue; - *p = '\0'; - mkdir(tmp, S_IRWXU); - *p = '/'; - } - mkdir(tmp, S_IRWXU); -} - -static -void -channel_normalize_path(char *s) -{ - for (; *s; s++) { - if (isalpha((unsigned char)*s)) - *s = tolower((unsigned char)*s); - else if (!isdigit((unsigned char)*s) && !strchr(".#&+!-", *s)) - *s = '_'; - } -} - -static -void -channel_normalize_name(char *s) -{ - char *p; - - while (*s == '&' || *s == '#') - s++; - for (p = s; *s; s++) { - if (!strchr(" ,&#\x07", *s)) { - *p = *s; - p++; - } - } - *p = '\0'; -} - -static -void -create_filepath(char *filepath, size_t len, const char *path, - const char *channel, const char *suffix) -{ - int r; - - if (channel[0]) { - r = snprintf(filepath, len, "%s/%s", path, channel); - if (r < 0 || (size_t)r >= len) - goto error; - create_dirtree(filepath); - r = snprintf(filepath, len, "%s/%s/%s", path, channel, suffix); - if (r < 0 || (size_t)r >= len) - goto error; - } else { - r = snprintf(filepath, len, "%s/%s", path, suffix); - if (r < 0 || (size_t)r >= len) - goto error; - } - return; - -error: - fprintf(stderr, "%s: path to irc directory too long\n", argv0); - exit(1); -} - -static -int -channel_open(Channel *c) -{ - int fd; - struct stat st; - - /* make "in" fifo if it doesn't exist already. */ - if (lstat(c->inpath, &st) != -1) { - if (!(st.st_mode & S_IFIFO)) - return -1; - } else if (mkfifo(c->inpath, S_IRWXU)) { - return -1; - } - c->fdin = -1; - fd = open(c->inpath, O_RDONLY | O_NONBLOCK, 0); - if (fd == -1) - return -1; - c->fdin = fd; - - return 0; -} - -static -int -channel_reopen(Channel *c) -{ - if (c->fdin > 2) { - close(c->fdin); - c->fdin = -1; - } - return channel_open(c); -} - -static -Channel * -channel_new(const char *name) -{ - Channel *c; - char channelpath[PATH_MAX]; - - strlcpy(channelpath, name, sizeof(channelpath)); - channel_normalize_path(channelpath); - - if (!(c = calloc(1, sizeof(Channel)))) { - fprintf(stderr, "%s: calloc: %s\n", argv0, strerror(errno)); - exit(1); - } - - strlcpy(c->name, name, sizeof(c->name)); - channel_normalize_name(c->name); - - create_filepath(c->inpath, sizeof(c->inpath), ircpath, - channelpath, "in"); - create_filepath(c->outpath, sizeof(c->outpath), ircpath, - channelpath, "out"); - return c; -} - -static -Channel * -channel_find(const char *name) -{ - Channel *c; - char chan[IRC_CHANNEL_MAX]; - - strlcpy(chan, name, sizeof(chan)); - channel_normalize_name(chan); - for (c = channels; c; c = c->next) { - if (!strcmp(chan, c->name)) - return c; /* already handled */ - } - return nil; -} - -static -Channel * -channel_add(const char *name) -{ - Channel *c; - - c = channel_new(name); - if (channel_open(c) == -1) { - fprintf(stderr, "%s: cannot create channel: %s: %s\n", - argv0, name, strerror(errno)); - free(c); - return nil; - } - if (!channels) { - channels = c; - } else { - c->next = channels; - channels = c; - } - return c; -} - -static -Channel * -channel_join(const char *name) -{ - Channel *c; - - if (!(c = channel_find(name))) - c = channel_add(name); - return c; -} - -static -void -channel_rm(Channel *c) -{ - Channel *p; - - if (channels == c) { - channels = channels->next; - } else { - for (p = channels; p && p->next != c; p = p->next) - ; - if (p && p->next == c) - p->next = c->next; - } - free(c); -} - -static -void -channel_leave(Channel *c) -{ - if (c->fdin > 2) { - close(c->fdin); - c->fdin = -1; - } - /* remove "in" file on leaving the channel */ - unlink(c->inpath); - channel_rm(c); -} - -static -void -loginkey(int ircfd, const char *key) -{ - snprintf(msg, sizeof(msg), "PASS %s\r\n", key); - ewritestr(ircfd, msg); -} - -static -void -loginuser(int ircfd, const char *host, const char *fullname) -{ - snprintf(msg, sizeof(msg), "NICK %s\r\nUSER %s localhost %s :%s\r\n", - nick, nick, host, fullname); - puts(msg); - ewritestr(ircfd, msg); -} - -static -int -udsopen(const char *uds) -{ - struct sockaddr_un sun; - size_t len; - int fd; - - if((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { - fprintf(stderr, "%s: socket: %s\n", argv0, strerror(errno)); - exit(1); - } - - sun.sun_family = AF_UNIX; - if(strlcpy(sun.sun_path, uds, sizeof(sun.sun_path)) >= sizeof(sun.sun_path)) { - fprintf(stderr, "%s: UNIX domain socket path truncation\n", argv0); - exit(1); - } - len = strlen(sun.sun_path) + 1 + sizeof(sun.sun_family); - if (connect(fd, (struct sockaddr *)&sun, len) == -1) { - fprintf(stderr, "%s: connect: %s\n", argv0, strerror(errno)); - exit(1); - } - return fd; -} - -static -int -tcpopen(const char *host, const char *service) -{ - struct addrinfo hints, *res = nil, *rp; - int fd = -1, e; - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_UNSPEC; /* allow IPv4 or IPv6 */ - hints.ai_flags = AI_NUMERICSERV; /* avoid name lookup for port */ - hints.ai_socktype = SOCK_STREAM; - - if ((e = getaddrinfo(host, service, &hints, &res))) { - fprintf(stderr, "%s: getaddrinfo: %s\n", argv0, gai_strerror(e)); - exit(1); - } - - for (rp = res; rp; rp = rp->ai_next) { - fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); - if (fd == -1) - continue; - if (connect(fd, rp->ai_addr, rp->ai_addrlen) == -1) { - close(fd); - fd = -1; - continue; - } - break; /* success */ - } - if (fd == -1) { - fprintf(stderr, "%s: could not connect to %s:%s: %s\n", - argv0, host, service, strerror(errno)); - exit(1); - } - - freeaddrinfo(res); - return fd; -} - -static -int -isnumeric(const char *s) -{ - errno = 0; - strtol(s, nil, 10); - return errno == 0; -} - -static -size_t -tokenize(char **result, size_t reslen, char *str, int delim) -{ - char *p = nil, *n = nil; - size_t i = 0; - - for (n = str; *n == ' '; n++) - ; - p = n; - while (*n != '\0') { - if (i >= reslen) - return 0; - if (i > TOK_CHAN - TOK_CMD && result[0] && isnumeric(result[0])) - delim = ':'; /* workaround non-RFC compliant messages */ - if (*n == delim) { - *n = '\0'; - result[i++] = p; - p = ++n; - } else { - n++; - } - } - /* add last entry */ - if (i < reslen && p < n && p && *p) - result[i++] = p; - return i; /* number of tokens */ -} - -static -void -channel_print(Channel *c, const char *buf) -{ - FILE *fp = nil; - time_t t = time(nil); - - if (!(fp = fopen(c->outpath, "a"))) - return; - fprintf(fp, "%lu %s\n", (unsigned long)t, buf); - fclose(fp); -} - -static -void -proc_channels_privmsg(int ircfd, Channel *c, char *buf) -{ - snprintf(msg, sizeof(msg), "<%s> %s", nick, buf); - channel_print(c, msg); - snprintf(msg, sizeof(msg), "PRIVMSG %s :%s\r\n", c->name, buf); - ewritestr(ircfd, msg); -} - -static -void -proc_channels_input(int ircfd, Channel *c, char *buf) -{ - char *p = nil; - size_t buflen; - - if (buf[0] == '\0') - return; - if (buf[0] != '/') { - proc_channels_privmsg(ircfd, c, buf); - return; - } - - msg[0] = '\0'; - if ((buflen = strlen(buf)) < 2) - return; - if (buf[2] == ' ' || buf[2] == '\0') { - switch (buf[1]) { - case 'j': /* join */ - if (buflen < 3) - return; - if ((p = strchr(&buf[3], ' '))) /* password parameter */ - *p = '\0'; - if ((buf[3] == '#') || (buf[3] == '&') || (buf[3] == '+') || - (buf[3] == '!')) - { - /* 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]); - channel_join(&buf[3]); - } else if (p) { - if ((c = channel_join(&buf[3]))) - proc_channels_privmsg(ircfd, c, p + 1); - return; - } - break; - case 't': /* topic */ - if (buflen >= 3) - snprintf(msg, sizeof(msg), "TOPIC %s :%s\r\n", c->name, &buf[3]); - break; - case 'a': /* away */ - if (buflen >= 3) { - snprintf(msg, sizeof(msg), "-!- %s is away \"%s\"", nick, &buf[3]); - channel_print(c, msg); - } - if (buflen >= 3) - snprintf(msg, sizeof(msg), "AWAY :%s\r\n", &buf[3]); - else - snprintf(msg, sizeof(msg), "AWAY\r\n"); - break; - case 'n': /* change nick */ - if (buflen >= 3) { - strlcpy(_nick, &buf[3], sizeof(_nick)); - snprintf(msg, sizeof(msg), "NICK %s\r\n", &buf[3]); - } - break; - case 'l': /* leave */ - if (c == channelmaster) - return; - if (buflen >= 3) - snprintf(msg, sizeof(msg), "PART %s :%s\r\n", c->name, &buf[3]); - else - snprintf(msg, sizeof(msg), - "PART %s :leaving\r\n", c->name); - ewritestr(ircfd, msg); - channel_leave(c); - return; - break; - case 'q': /* quit */ - if (buflen >= 3) - snprintf(msg, sizeof(msg), "QUIT :%s\r\n", &buf[3]); - else - snprintf(msg, sizeof(msg), - "QUIT %s\r\n", "bye"); - ewritestr(ircfd, msg); - isrunning = 0; - return; - break; - default: /* raw IRC command */ - snprintf(msg, sizeof(msg), "%s\r\n", &buf[1]); - break; - } - } else { - /* raw IRC command */ - snprintf(msg, sizeof(msg), "%s\r\n", &buf[1]); - } - if (msg[0] != '\0') - ewritestr(ircfd, msg); -} - -static -void -proc_server_cmd(int fd, char *buf) -{ - Channel *c; - const char *channel; - char *argv[TOK_LAST], *cmd = nil, *p = nil; - unsigned int i; - - if (!buf || buf[0] == '\0') - return; - - /* clear tokens */ - for (i = 0; i < TOK_LAST; i++) - argv[i] = nil; - - /* check prefix */ - if (buf[0] == ':') { - if (!(p = strchr(buf, ' '))) - return; - *p = '\0'; - for (++p; *p == ' '; p++) - ; - cmd = p; - argv[TOK_NICKSRV] = &buf[1]; - if ((p = strchr(buf, '!'))) { - *p = '\0'; - argv[TOK_USER] = ++p; - } - } else { - cmd = buf; - } - - /* remove CRLFs */ - for (p = cmd; p && *p != '\0'; p++) { - if (*p == '\r' || *p == '\n') - *p = '\0'; - } - - if ((p = strchr(cmd, ':'))) { - *p = '\0'; - argv[TOK_TEXT] = ++p; - } - - tokenize(&argv[TOK_CMD], TOK_LAST - TOK_CMD, cmd, ' '); - - if (!argv[TOK_CMD] || !strcmp("PONG", argv[TOK_CMD])) { - return; - } else if (!strcmp("PING", argv[TOK_CMD])) { - snprintf(msg, sizeof(msg), "PONG %s\r\n", argv[TOK_TEXT]); - ewritestr(fd, msg); - return; - } 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] : ""); - channel_print(channelmaster, msg); - return; /* don't process further */ - } else if (!strcmp("ERROR", argv[TOK_CMD])) - snprintf(msg, sizeof(msg), "-!- error %s", - argv[TOK_TEXT] ? argv[TOK_TEXT] : "unknown"); - else if (!strcmp("JOIN", argv[TOK_CMD]) && (argv[TOK_CHAN] || argv[TOK_TEXT])) { - if (argv[TOK_TEXT]) - argv[TOK_CHAN] = argv[TOK_TEXT]; - snprintf(msg, sizeof(msg), "-!- %s(%s) has joined %s", - argv[TOK_NICKSRV], argv[TOK_USER], argv[TOK_CHAN]); - } else if (!strcmp("PART", argv[TOK_CMD]) && argv[TOK_CHAN]) { - snprintf(msg, sizeof(msg), "-!- %s(%s) has left %s", - argv[TOK_NICKSRV], argv[TOK_USER], argv[TOK_CHAN]); - /* if user itself leaves, don't write to channel (don't reopen channel). */ - if (!strcmp(argv[TOK_NICKSRV], nick)) - return; - } else if (!strcmp("MODE", argv[TOK_CMD])) { - snprintf(msg, sizeof(msg), "-!- %s changed mode/%s -> %s %s", - argv[TOK_NICKSRV], - argv[TOK_CHAN] ? argv[TOK_CHAN] : "", - argv[TOK_ARG] ? argv[TOK_ARG] : "", - argv[TOK_TEXT] ? argv[TOK_TEXT] : ""); - } else if (!strcmp("QUIT", argv[TOK_CMD])) { - 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) && argv[TOK_TEXT] && - !strcmp(_nick, argv[TOK_TEXT])) { - strlcpy(nick, _nick, sizeof(nick)); - snprintf(msg, sizeof(msg), "-!- changed nick to \"%s\"", nick); - channel_print(channelmaster, msg); - } else if (!strcmp("NICK", argv[TOK_CMD]) && argv[TOK_TEXT]) { - snprintf(msg, sizeof(msg), "-!- %s changed nick to %s", - argv[TOK_NICKSRV], argv[TOK_TEXT]); - } else if (!strcmp("TOPIC", argv[TOK_CMD])) { - snprintf(msg, sizeof(msg), "-!- %s changed topic to \"%s\"", - argv[TOK_NICKSRV], - argv[TOK_TEXT] ? argv[TOK_TEXT] : ""); - } else if (!strcmp("KICK", argv[TOK_CMD]) && argv[TOK_ARG]) { - snprintf(msg, sizeof(msg), "-!- %s kicked %s (\"%s\")", - argv[TOK_NICKSRV], argv[TOK_ARG], - argv[TOK_TEXT] ? argv[TOK_TEXT] : ""); - } else if (!strcmp("NOTICE", argv[TOK_CMD])) { - snprintf(msg, sizeof(msg), "-!- \"%s\"", - argv[TOK_TEXT] ? argv[TOK_TEXT] : ""); - } else if (!strcmp("PRIVMSG", argv[TOK_CMD])) { - snprintf(msg, sizeof(msg), "<%s> %s", argv[TOK_NICKSRV], - argv[TOK_TEXT] ? argv[TOK_TEXT] : ""); - } else { - return; /* can't read this message */ - } - if (argv[TOK_CHAN] && !strcmp(argv[TOK_CHAN], nick)) - channel = argv[TOK_NICKSRV]; - else - channel = argv[TOK_CHAN]; - - if (!channel || channel[0] == '\0') - c = channelmaster; - else - c = channel_join(channel); - if (c) - channel_print(c, msg); -} - -static -int -read_line(int fd, char *buf, size_t bufsiz) -{ - size_t i = 0; - char c = '\0'; - - do { - if (read(fd, &c, sizeof(char)) != sizeof(char)) - return -1; - buf[i++] = c; - } while (c != '\n' && i < bufsiz); - buf[i - 1] = '\0'; /* eliminates '\n' */ - return 0; -} - -static -void -handle_channels_input(int ircfd, Channel *c) -{ - char buf[IRC_MSG_MAX]; - - if(read_line(c->fdin, buf, sizeof(buf)) == -1) { - if(channel_reopen(c) == -1) - channel_rm(c); - return; - } - proc_channels_input(ircfd, c, buf); -} - -static -void -handle_server_output(int ircfd) -{ - char buf[IRC_MSG_MAX]; - - if (read_line(ircfd, buf, sizeof(buf)) == -1) { - fprintf(stderr, "%s: remote host closed connection: %s\n", - argv0, strerror(errno)); - exit(1); - } - fprintf(stdout, "%lu %s\n", (unsigned long)time(nil), buf); - fflush(stdout); - proc_server_cmd(ircfd, buf); -} - -static -void -sighandler(int sig) -{ - if (sig == SIGTERM || sig == SIGINT) - isrunning = 0; -} - -static -void -setup(void) -{ - struct sigaction sa; - - memset(&sa, 0, sizeof(sa)); - sa.sa_handler = sighandler; - sigaction(SIGTERM, &sa, nil); - sigaction(SIGINT, &sa, nil); -} - -static -void -run(int ircfd, const char *host) -{ - Channel *c, *tmp; - fd_set rdset; - struct timeval tv; - char ping_msg[IRC_MSG_MAX]; - int r, maxfd; - - snprintf(ping_msg, sizeof(ping_msg), "PING %s\r\n", host); - while(isrunning) { - maxfd = ircfd; - FD_ZERO(&rdset); - FD_SET(ircfd, &rdset); - for (c = channels; c; c = c->next) { - if (c->fdin > maxfd) - maxfd = c->fdin; - FD_SET(c->fdin, &rdset); - } - memset(&tv, 0, sizeof(tv)); - tv.tv_sec = 120; - r = select(maxfd + 1, &rdset, 0, 0, &tv); - if(r < 0){ - if (errno == EINTR) - continue; - fprintf(stderr, "%s: select: %s\n", argv0, strerror(errno)); - exit(1); - }else if(r == 0){ - if (time(nil) - last_response >= PING_TIMEOUT) { - channel_print(channelmaster, "-!- ii shutting down: ping timeout"); - exit(2); /* status code 2 for timeout */ - } - ewritestr(ircfd, ping_msg); - continue; - } - if(FD_ISSET(ircfd, &rdset)) { - handle_server_output(ircfd); - last_response = time(nil); - } - for(c = channels; c; c = tmp) { - tmp = c->next; - if (FD_ISSET(c->fdin, &rdset)) - handle_channels_input(ircfd, c); - } - } -} - -int -main(int argc, char *argv[]) -{ - Channel *c, *tmp; - struct passwd *spw; - const char *key = nil, *fullname = nil, *host = ""; - const char *uds = nil, *service = "6667"; - char prefix[PATH_MAX]; - int ircfd, r; - - /* use nickname and home dir of user by default */ - if(!(spw = getpwuid(getuid()))) { - fprintf(stderr, "%s: getpwuid: %s\n", argv0, strerror(errno)); - exit(1); - } - strlcpy(nick, spw->pw_name, sizeof(nick)); - snprintf(prefix, sizeof(prefix), "%s/irc", spw->pw_dir); - - ARGBEGIN { - case 'f': - fullname = EARGF(usage()); - break; - case 'i': - strlcpy(prefix, EARGF(usage()), sizeof(prefix)); - break; - case 'k': - key = getenv(EARGF(usage())); - break; - case 'n': - strlcpy(nick, EARGF(usage()), sizeof(nick)); - break; - case 'p': - service = EARGF(usage()); - break; - case 's': - host = EARGF(usage()); - break; - case 'u': - uds = EARGF(usage()); - break; - default: - usage(); - break; - } ARGEND - - if(!*host) - usage(); - - if(uds) - ircfd = udsopen(uds); - else - ircfd = tcpopen(host, service); - -#ifdef __OpenBSD__ - /* OpenBSD pledge(2) support */ - if (pledge("stdio rpath wpath cpath dpath", nil) == -1) { - fprintf(stderr, "%s: pledge: %s\n", argv0, strerror(errno)); - exit(1); - } -#endif - - r = snprintf(ircpath, sizeof(ircpath), "%s/%s", prefix, host); - if (r < 0 || (size_t)r >= sizeof(ircpath)) { - fprintf(stderr, "%s: path to irc directory too long\n", argv0); - exit(1); - } - create_dirtree(ircpath); - - channelmaster = channel_add(""); /* master channel */ - if(key) - loginkey(ircfd, key); - loginuser(ircfd, host, fullname && *fullname ? fullname : nick); - setup(); - run(ircfd, host); - if(channelmaster) - channel_leave(channelmaster); - - for(c = channels; c; c = tmp) { - tmp = c->next; - channel_leave(c); - } - - return 0; -} diff --git a/sys/cmd/ic/rules.mk b/sys/cmd/ic/rules.mk deleted file mode 100644 index 649c9ac..0000000 --- a/sys/cmd/ic/rules.mk +++ /dev/null @@ -1,14 +0,0 @@ -include share/push.mk -# Iterate through subdirectory tree - -# Local sources -SRCS_$(d) := $(d)/strlcpy.c $(d)/ic.c -BINS_$(d) := $(d)/ic - -include share/paths.mk - -# Local rules -$(BINS_$(d)): $(OBJS_$(d)) $(OBJ_DIR)/sys/base/base.a - $(COMPLINK) - -include share/pop.mk diff --git a/sys/cmd/ic/strlcpy.c b/sys/cmd/ic/strlcpy.c deleted file mode 100644 index 5af7906..0000000 --- a/sys/cmd/ic/strlcpy.c +++ /dev/null @@ -1,32 +0,0 @@ -/* Taken from OpenBSD */ -#include -#include - -/* - * Copy src to string dst of size siz. At most siz-1 characters - * will be copied. Always NUL terminates (unless siz == 0). - * Returns strlen(src); if retval >= siz, truncation occurred. - */ -size_t -strlcpy(char *dst, const char *src, size_t siz) -{ - char *d = dst; - const char *s = src; - size_t n = siz; - - /* Copy as many bytes as will fit */ - if(n != 0) { - while(--n != 0) { - if((*d++ = *s++) == '\0') - break; - } - } - /* Not enough room in dst, add NUL and traverse rest of src */ - if(n == 0) { - if(siz != 0) - *d = '\0'; /* NUL-terminate dst */ - while(*s++) - ; - } - return s - src - 1; /* count does not include NUL */ -} -- cgit v1.2.1