Skip to content

Allow the option of parsing multiple post-connection commands. #125

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Feb 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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