diff --git a/.gitignore b/.gitignore index b1c04eb..fbd9d52 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,8 @@ kirc *.a *.o *.txt +tags +*.out +*.log +*.diff +.*.swp diff --git a/kirc.c b/kirc.c index 6f1f943..8e7dfde 100644 --- a/kirc.c +++ b/kirc.c @@ -23,22 +23,25 @@ #define CHA_MAX 200 #define NIC_MAX 26 #define HIS_MAX 100 +#define CBUF_SIZ 1024 -static char cdef[MSG_MAX] = "?"; /* default PRIVMSG channel */ -static int conn; /* connection socket */ -static int verb = 0; /* verbose output */ -static int sasl = 0; /* SASL method */ -static int isu8 = 0; /* UTF-8 flag */ -static char *host = "irc.libera.chat"; /* host address */ -static char *port = "6667"; /* port */ -static char *chan = NULL; /* channel(s) */ -static char *nick = NULL; /* nickname */ -static char *pass = NULL; /* password */ -static char *user = NULL; /* user name */ -static char *auth = NULL; /* PLAIN SASL token */ -static char *real = NULL; /* real name */ -static char *olog = NULL; /* chat log path*/ -static char *inic = NULL; /* additional server command */ +static char cdef[MSG_MAX] = "?"; /* default PRIVMSG channel */ +static int conn; /* connection socket */ +static int verb = 0; /* verbose output */ +static int sasl = 0; /* SASL method */ +static int isu8 = 0; /* UTF-8 flag */ +static char *host = "irc.libera.chat"; /* host address */ +static char *port = "6667"; /* port */ +static char *chan = NULL; /* channel(s) */ +static char *nick = NULL; /* nickname */ +static char *pass = NULL; /* password */ +static char *user = NULL; /* user name */ +static char *auth = NULL; /* PLAIN SASL token */ +static char *real = NULL; /* real name */ +static char *olog = NULL; /* chat log path*/ +static char *inic = NULL; /* additional server command */ +static int cmds = 0; /* indicates additional server commands */ +static char cbuf[CBUF_SIZ]; /* additional stdin server commands */ struct Param { char *prefix; @@ -53,6 +56,7 @@ struct Param { int nicklen; }; +static int ttyinfd = STDIN_FILENO; static struct termios orig; static int rawmode = 0; static int atexit_registered = 0; @@ -92,14 +96,14 @@ static void freeHistory(void) { } static void disableRawMode(void) { - if (rawmode && tcsetattr(STDIN_FILENO,TCSAFLUSH,&orig) != -1) { + if (rawmode && tcsetattr(ttyinfd,TCSAFLUSH,&orig) != -1) { rawmode = 0; } freeHistory(); } static int enableRawMode(int fd) { - if (!isatty(STDIN_FILENO)) { + if (!isatty(ttyinfd)) { goto fatal; } if (!atexit_registered) { @@ -297,7 +301,7 @@ static void refreshLine(struct State *l) { size_t posu8 = l->posu8; size_t ch = plenu8, txtlenb = 0; struct abuf ab; - l->cols = getColumns(STDIN_FILENO, STDOUT_FILENO); + l->cols = getColumns(ttyinfd, STDOUT_FILENO); while ((plenu8 + posu8) >= l->cols) { buf += u8Next(buf, 0); posu8--; @@ -510,12 +514,12 @@ static void editEnter(void) { } static void editEscSequence(struct State *l, char seq[3]) { - if (read(STDIN_FILENO, seq, 1) == -1) return; - if (read(STDIN_FILENO, seq + 1, 1) == -1) return; + if (read(ttyinfd, seq, 1) == -1) return; + if (read(ttyinfd, seq + 1, 1) == -1) return; if (seq[0] == '[') { /* ESC [ sequences. */ if ((seq[1] >= '0') && (seq[1] <= '9')) { /* Extended escape, read additional byte. */ - if (read(STDIN_FILENO, seq + 2, 1) == -1) { + if (read(ttyinfd, seq + 2, 1) == -1) { return; } if ((seq[2] == '~') && (seq[1] == 3)) { @@ -542,7 +546,7 @@ static void editEscSequence(struct State *l, char seq[3]) { static int edit(struct State *l) { char c, seq[3]; int ret = 0; - ssize_t nread = read(STDIN_FILENO, &c, 1); + ssize_t nread = read(ttyinfd, &c, 1); if (nread <= 0) { ret = 1; } else { @@ -577,7 +581,7 @@ static int edit(struct State *l) { aux[0] = c; int size = u8CharSize(c); for (int i = 1; i < size; i++) { - nread = read(STDIN_FILENO, aux + i, 1); + nread = read(ttyinfd, aux + i, 1); if ((aux[i] & 0xC0) != 0x80) { break; } @@ -803,7 +807,7 @@ static void rawParser(char *string) { p.command = strtok(p.suffix, "#& "); p.channel = strtok(NULL, " \r"); p.params = strtok(NULL, ":\r"); - p.maxcols = getColumns(STDIN_FILENO, STDOUT_FILENO); + p.maxcols = getColumns(ttyinfd, STDOUT_FILENO); p.nicklen = (p.maxcols / 3 > NIC_MAX ? NIC_MAX : p.maxcols / 3); p.offset = 0; if (!strncmp(p.command, "001", 3) && chan != NULL) { @@ -922,26 +926,41 @@ static void version(void) { exit(0); } +static void opentty() +{ + if ((ttyinfd = open("/dev/tty", 0)) == -1) { + perror("failed to open /dev/tty"); + exit(1); + } +} + int main(int argc, char **argv) { + opentty(); int cval; - while ((cval = getopt(argc, argv, "s:p:o:n:k:c:u:r:x:a:evV")) != -1) { + while ((cval = getopt(argc, argv, "s:p:o:n:k:c:u:r:a:exvV")) != -1) { switch (cval) { - case 'v' : version(); break; - case 'V' : ++verb; break; - case 'e' : ++sasl; break; - case 's' : host = optarg; break; - case 'p' : port = optarg; break; - case 'r' : real = optarg; break; - case 'u' : user = optarg; break; - case 'a' : auth = optarg; break; - case 'o' : olog = optarg; break; - case 'n' : nick = optarg; break; - case 'k' : pass = optarg; break; - case 'c' : chan = optarg; break; - case 'x' : inic = optarg; break; + case 'v' : version(); break; + case 'V' : ++verb; break; + case 'e' : ++sasl; break; + case 's' : host = optarg; break; + case 'p' : port = optarg; break; + case 'r' : real = optarg; break; + case 'u' : user = optarg; break; + case 'a' : auth = optarg; break; + case 'o' : olog = optarg; break; + case 'n' : nick = optarg; break; + case 'k' : pass = optarg; break; + case 'c' : chan = optarg; break; + case 'x' : cmds = 1; inic = argv[optind]; break; case '?' : usage(); break; } } + if (cmds > 0) { + int flag = 0; + for (int i = 0; i < CBUF_SIZ && flag > -1; i++) { + flag = read(STDIN_FILENO, &cbuf[i], 1); + } + } if (!nick) { fputs("Nick not specified\n", stderr); usage(); @@ -961,11 +980,16 @@ int main(int argc, char **argv) { if (pass) { raw("PASS %s\r\n", pass); } - if (inic) { - raw("%s\r\n", inic); + if (cmds > 0) { + for (char *tok = strtok(cbuf, "\n"); tok; tok = strtok(NULL, "\n")) { + raw("%s\r\n", tok); + } + if (inic) { + raw("%s\r\n", inic); + } } struct pollfd fds[2]; - fds[0].fd = STDIN_FILENO; + fds[0].fd = ttyinfd; fds[1].fd = conn; fds[0].events = POLLIN; fds[1].events = POLLIN; @@ -976,10 +1000,10 @@ int main(int argc, char **argv) { l.prompt = cdef; stateReset(&l); int rc, editReturnFlag = 0; - if (enableRawMode(STDIN_FILENO) == -1) { + if (enableRawMode(ttyinfd) == -1) { return 1; } - if (setIsu8_C(STDIN_FILENO, STDOUT_FILENO) == -1) { + if (setIsu8_C(ttyinfd, STDOUT_FILENO) == -1) { return 1; } for (;;) {