Skip to content

Commit

Permalink
Allow the option of parsing multiple post-connection commands. (#125)
Browse files Browse the repository at this point in the history
* Allow the option of parsing multiple post-connection commands.

* Initial change for multiple commands via stdin

* Use MSG_MAX as the max length of additional commands

* Include + 1 to MSG_MAX to account for newline characters

* Rework loop to process commands to avoid seg fault, use strnlen

* Remove swap file

* Restore previous formatting, restore man description for -x for now

* Enable additional commands via both stdin and option argument

* Move misplaced malloc check to where it belongs

* Simplify logic to read commands from stdin

* Retain functionality to accept server command as option argument

* Maintain same functionality as before when sending inic
  • Loading branch information
Cristian Canedo authored Feb 15, 2022
1 parent 7ebf6b9 commit 5f8bab4
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 43 deletions.
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,8 @@ kirc
*.a
*.o
*.txt
tags
*.out
*.log
*.diff
.*.swp
110 changes: 67 additions & 43 deletions kirc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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--;
Expand Down Expand Up @@ -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)) {
Expand All @@ -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 {
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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();
Expand All @@ -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;
Expand All @@ -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 (;;) {
Expand Down

0 comments on commit 5f8bab4

Please sign in to comment.