aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Czigler <37268479+mcpcpc@users.noreply.github.com>2020-09-07 14:04:26 -0400
committermcpcpc <michaelczigler@icloud.com>2020-09-09 22:25:03 -0400
commit5db8d0b6e3d8d924008eea25b7bd831ce3c53bea (patch)
tree72c9bba8ec100617f5f5d6717bc5498f4e342818
parentMerge pull request #11 from mcpcpc/0.0.7 (diff)
downloadkirc-5db8d0b6e3d8d924008eea25b7bd831ce3c53bea.tar.gz
kirc-5db8d0b6e3d8d924008eea25b7bd831ce3c53bea.tar.bz2
kirc-5db8d0b6e3d8d924008eea25b7bd831ce3c53bea.tar.xz
kirc-5db8d0b6e3d8d924008eea25b7bd831ce3c53bea.tar.zst
kirc-5db8d0b6e3d8d924008eea25b7bd831ce3c53bea.zip
Squash commits pertaining to 0.0.8 release
Update README cleanup cleanup fix int typecast in printw() fix int typecast for JOIN/QUIT add 'x' command to send direct messages to server Update README Update kirc.c remove annoying initial space char revert last commit to remove initial space revert last commit undo accidental commit apply fix for initial space char add NAMES command revamped README for readability in GitHub Rename README to README.md Update README.md Update README.md Update README.md Update README.md Update README.md Update README.md Update README.md Update README.md Update README.md Add files via upload Update README.md Update README.md Update README.md Update README.md Update README.md Update README.md Add files via upload Update README.md Update README.md Update README.md Update README.md Update README.md Update README.md Update README.md Add files via upload Update README.md Add files via upload Delete example_cropped.png Delete kirc.png Add files via upload Delete kirc.png Add files via upload Delete kirc.png Add files via upload Delete kirc.png Add files via upload Delete kirc.png Add files via upload Update README.md Add files via upload Delete example_cropped.JPG Update README.md Update README.md Update README.md Update README.md Update README.md
Diffstat (limited to '')
-rw-r--r--.github/kirc.pngbin0 -> 442070 bytes
-rw-r--r--README100
-rw-r--r--README.md89
-rw-r--r--kirc.c99
4 files changed, 137 insertions, 151 deletions
diff --git a/.github/kirc.png b/.github/kirc.png
new file mode 100644
index 0000000..52a6075
--- /dev/null
+++ b/.github/kirc.png
Binary files differ
diff --git a/README b/README
deleted file mode 100644
index 0d35f4f..0000000
--- a/README
+++ /dev/null
@@ -1,100 +0,0 @@
-kirc
-
-KISS for IRC, an IRC client written in POSIX C99.
-
-
-BACKGROUND
-----------
-
-After having tried multiple IRC clients, I decided to develope my own. The
-result is a portable application that has no dependencies other than a C99
-compiler.
-
-
-OBJECTIVES
-----------
-
-- Per the UNIX philosophy, "Do one thing and do it well" [3].
-- True to the KISS principle [4], the code-base is intentionally smaller
- than most IRC clients (<250 sloc). The benefits of a small code base
- reflects in the ability for kirc to be reviewed, understood and
- maintained by a single person. Therefore, all feature requests and
- commits shall be considered with respect to the readability and
- maintainance of the overall project.
-- Let's not "reinvent the wheel". Commands and functionality should
- feel familiar (e.g. vi command shortcuts) and accessable via a
- standard 104-key US QWERTY keyboard layout [5]. Where possible, the
- number of keystrokes shall be minimized per command.
-
-
-FEATURES
---------
-
-- automatic host PING response.
-- vi-like shortcuts:
-
- <message> send a message to the current channel
- /m <nick|channel> <message> send a message to a specified nick or channel
- /n <message> send a message to NickServ
- /j <channel> join a specified channel
- /p <channel> leave (part) a specified channel
- /Q <message> send a message and close the host connection
- /q close the host connection
-
-- automatic word wrapping using the greedy algorithm.
-- color scheme definition via ANSI 8-bit colors [1]. Therefore, one could
- theoretically achieve uniform color definition across all shell applications
- and tools.
-
-
-INSTALLATION
-------------
-
-Building and installing on KISS Linux using the Community repository [2]:
-
- kiss b kirc
- kiss i kirc
-
-Building and installing on Arch Linux using the AUR [6]:
-
- git clone https://aur.archlinux.org/kirc-git.git
- cd kirc
- makepkg -si
-
-Building and installing from source:
-
- git clone https://github.com/mcpcpc/kirc.git
- cd kirc
- make
- make install
-
-
-USAGE
------
-
-usage: kirc [-s hostname] [-p port] [-c channel] [-n nick] [-r real name]
-[-u username] [-k password] [-w columns] [-W columns] [-o path] [-v|V]
--s server address (default: 'irc.freenode.org')
--p server port (default: '6667')
--c channel name (default: '#kisslinux')
--n nickname (required)
--u server username (optional)
--k server password (optional)
--r real name (optional)
--v version information
--V verbose output (e.g. raw stream)
--o output path to log irc stream
--w maximum width of the printed left column (default: '10')
--W maximum width of the entire printed stream (default '80')
-
-
-REFERENCES
-----------
-
-[0] https://tools.ietf.org/html/rfc2812
-[1] https://en.wikipedia.org/wiki/ANSI_escape_code
-[2] https://github.com/kisslinux/community
-[3] https://en.wikipedia.org/wiki/Unix_philosophy
-[4] https://en.wikipedia.org/wiki/KISS_principle
-[5] https://en.wikipedia.org/wiki/Keyboard_layout
-[6] https://aur.archlinux.org/packages/kirc-git/
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..1e6d703
--- /dev/null
+++ b/README.md
@@ -0,0 +1,89 @@
+<h3 align="center"><img src="https://raw.githubusercontent.com/mcpcpc/kirc/master/.github/kirc.png" alt="logo" height="170px"></h3>
+<p align="center">KISS for IRC, a tiny IRC client written in POSIX C99.</p>
+<p align="center">
+<a href="./LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg"></a>
+<a href="https://github.com/mcpcpc/kirc/releases"><img src="https://img.shields.io/github/v/release/mcpcpc/kirc.svg"></a>
+<a href="https://repology.org/metapackage/kirc"><img src="https://repology.org/badge/tiny-repos/kirc.svg" alt="Packaging status"></a>
+</p>
+
+
+## Objectives
+
+*"Do one thing and do it well"* — Per the [Unix philosophy](https://en.wikipedia.org/wiki/Unix_philosophy), emphasis was placed on building simple, short, clear, modular, and extensible code that can be easily maintained and repurposed.
+
+*Portability* — [POSIX](https://en.wikipedia.org/wiki/POSIX) compliance ensures seamless compatibility and interoperability between variants of Unix and other operating systems.
+
+*Usability* — Commands and shortcuts should feel natural and accessible using a [standard 104-key US keyboard layout](https://en.wikipedia.org/wiki/Keyboard_layout). Where possible, the number of keystrokes shall be minimized.
+
+Usage
+-----
+
+```shell
+usage: kirc [-s hostname] [-p port] [-c channel] [-n nick] [-r real name] [-u username] [-k password] [-w columns] [-W columns] [-o path] [-v|V]
+-s server address (default: 'irc.freenode.org')
+-p server port (default: '6667')
+-c channel name (default: '#kisslinux')
+-n nickname (required)
+-u server username (optional)
+-k server password (optional)
+-r real name (optional)
+-v version information
+-V verbose output (e.g. raw stream)
+-o output path to log irc stream
+-w maximum width of the printed left column (default: '10')
+-W maximum width of the entire printed stream (default '80')
+```
+
+Features
+--------
+
+- No dependencies other than a [C99 compiler](https://gcc.gnu.org/).
+- Automatic server *PING* response.
+- Complies with [RFC 2812](https://tools.ietf.org/html/rfc2812) standard.
+- vi-like command shortcuts:
+
+```shell
+<message> Send a message to the current channel.
+/m <nick|channel> <message> Send a message to a specified channel or nick.
+/M <message> Send a message to NickServ.
+/Q <message> Send a message and close the host connection.
+/x <message> Send a message directly to the server.
+/j <channel> Join a specified channel.
+/p <channel> Leave (part) a specified channel.
+/n List all users on the current channel.
+/q Close the host connection.
+```
+
+- Color scheme definition via [ANSI 8-bit colors](https://en.wikipedia.org/wiki/ANSI_escape_code). Therefore, one could theoretically achieve uniform color definition across all shell applications and tools.
+
+Screenshots
+-----------
+
+![Screenshot 1](/.github/example.png)
+
+Installation
+------------
+
+Building and installing on **KISS Linux** using the Community repository:
+
+```shell
+kiss b kirc
+kiss i kirc
+```
+
+Building and installing on **Arch Linux** or **Manjaro** using the Arch AUR:
+
+```shell
+git clone https://aur.archlinux.org/kirc-git.git
+cd kirc
+makepkg -si
+```
+
+Building and installing from source (works on **Rasbian**, **Debian**, **Ubuntu** and many other distributions):
+
+```shell
+git clone https://github.com/mcpcpc/kirc.git
+cd kirc
+make
+make install
+```
diff --git a/kirc.c b/kirc.c
index 3e03cef..fe3279d 100644
--- a/kirc.c
+++ b/kirc.c
@@ -16,9 +16,9 @@
#define CHA_MAX 200 /* gauranteed max channel length */
static int conn; /* connection socket */
-static size_t verb = 0; /* verbose output (e.g. raw stream) */
-static size_t cmax = 80; /* max number of chars per line */
-static size_t gutl = 10; /* max char width of left column */
+static size_t verb = 0; /* verbose output (e.g. raw stream) */
+static size_t cmax = 80; /* max number of chars per line */
+static size_t gutl = 10; /* max char width of left column */
static char * host = "irc.freenode.org"; /* irc host address */
static char * chan = "kisslinux"; /* channel */
static char * port = "6667"; /* server port */
@@ -77,13 +77,6 @@ irc_init() {
getaddrinfo(host, port, &hints, &res);
conn = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
connect(conn, res->ai_addr, res->ai_addrlen);
-
- if (nick) raw("NICK %s\r\n", nick);
- if (user && real) raw("USER %s - - :%s\r\n", user, real);
- if (user && !real && nick) raw("USER %s - - :%s\r\n", user, nick);
- if (!user && !real && nick) raw("USER %s - - :%s\r\n", nick, nick);
- if (pass) raw("PASS %s\r\n", pass);
-
fcntl(conn, F_SETFL, O_NONBLOCK);
}
@@ -100,47 +93,45 @@ printw(const char *format, ...) {
if (olog) printa(line);
- for (i = 0; isspace(line[i]); i++) printf("%c", line[i]);
+ for (i = 0; isspace(line[i]); i++) putchar(line[i]);
spaceleft = cmax + gutl - (i - 1);
for(tok = strtok(&line[i], " "); tok != NULL; tok = strtok(NULL, " ")) {
wordwidth = strlen(tok);
if ((wordwidth + spacewidth) > spaceleft) {
- printf("\n%*.s%s", (int) gutl + 2, "", tok);
- spaceleft = cmax - (gutl + 2 + wordwidth);
+ printf("\n%*.s%s ", (int) gutl + 1, "", tok);
+ spaceleft = cmax - (gutl + 1 + wordwidth);
} else {
- printf(" %s", tok);
+ printf("%s ", tok);
spaceleft = spaceleft - (wordwidth + spacewidth);
}
}
+ printf("\n");
}
static void
-raw_parser(char *in) {
- if (verb) printf(">> %s\n", in);
- if (!strncmp(in, "PING", 4)) {
- in[1] = 'O';
- raw("%s\r\n", in);
- } else if (in[0] == ':') {
- char *prefix = strtok(in, " ") + 1;
- char *suffix = strtok(NULL, ":");
- char *message = strtok(NULL, "\r");
- char *nickname = strtok(prefix, "!"); /* , *usr = strtok(NULL, "@"), *hos = prefix; */
- char *command = strtok(suffix, "#& "), *channel = strtok(NULL, " ");
+raw_parser(char *usrin) {
+ if (verb) printf(">> %s\n", usrin);
+ if (!strncmp(usrin, "PING", 4)) {
+ usrin[1] = 'O';
+ raw("%s\r\n", usrin);
+ } else if (usrin[0] == ':') {
+ char *prefix = strtok(usrin, " ") + 1, *suffix = strtok(NULL, ":"),
+ *message = strtok(NULL, "\r"), *nickname = strtok(prefix, "!"),
+ *command = strtok(suffix, "#& "), *channel = strtok(NULL, " ");
if (!strncmp(command, "001", 3)) raw("JOIN #%s\r\n", chan);
else if (!strncmp(command, "QUIT", 4)) {
- printw("%*s \x1b[34;1m%s\x1b[0m\n", gutl, "<--", nickname);
+ printw("%*s \x1b[34;1m%s\x1b[0m", (int)gutl, "<--", nickname);
} else if (!strncmp(command, "JOIN", 4)) {
- printw("%*s \x1b[32;1m%s\x1b[0m\n", gutl, "-->", nickname);
- } else if (!strncmp(command, "PRIVMSG", 7) && !strncmp(channel, nick, strlen(nick))) {
- size_t len = strlen(nickname);
- printw("%*s\x1b[43;1m%-.*s\x1b[0m %s\n", \
- gutl-(len <= gutl ? len : gutl), "", gutl, nickname, message);
+ printw("%*s \x1b[32;1m%s\x1b[0m", (int)gutl, "-->", nickname);
+ } else if (!strncmp(command, "PRIVMSG", 7) &&
+ !strncmp(channel, nick, strlen(nick))) {
+ int s = gutl - (strlen(nickname) <= gutl ? strlen(nickname) : gutl);
+ printw("%*s\x1b[43;1m%-.*s\x1b[0m %s", s, "", (int)gutl, nickname, message);
} else {
- size_t len = strlen(nickname);
- printw("%*s\x1b[33;1m%-.*s\x1b[0m %s\n", \
- gutl-(len <= gutl ? len : gutl), "", gutl, nickname, message);
+ int s = gutl - (strlen(nickname) <= gutl ? strlen(nickname) : gutl);
+ printw("%*s\x1b[33;1m%-.*s\x1b[0m %s", s, "", (int)gutl, nickname, message);
}
}
}
@@ -168,7 +159,7 @@ main(int argc, char **argv) {
}
}
- if (nick == NULL) {
+ if (!nick) {
fprintf(stderr, "nick not specified\n");
return 1;
}
@@ -186,6 +177,12 @@ main(int argc, char **argv) {
irc_init();
+ if (nick) raw("NICK %s\r\n", nick);
+ if (user && real) raw("USER %s - - :%s\r\n", user, real);
+ if (user && !real && nick) raw("USER %s - - :%s\r\n", user, nick);
+ if (!user && !real && nick) raw("USER %s - - :%s\r\n", nick, nick);
+ if (pass) raw("PASS %s\r\n", pass);
+
while ((sl = read(conn, &s, 1))) {
if (sl > 0) b[o] = s;
@@ -204,33 +201,33 @@ main(int argc, char **argv) {
else {
char usrin[MSG_MAX], v1[MSG_MAX - CHA_MAX], v2[CHA_MAX], c1;
struct termios tp, save;
+
tcgetattr(STDIN_FILENO, &tp);
save = tp;
tp.c_cc[VERASE] = 127;
+ if (tcsetattr(STDIN_FILENO, TCSANOW, &tp) < 0) return 2;
while (waitpid(pid, NULL, WNOHANG) == 0) {
if (!kbhit()) dprintf(fd[1], "/\n");
- else {
- tcsetattr(STDIN_FILENO, TCSANOW, &tp);
- if (fgets(usrin, MSG_MAX, stdin) == NULL) return 1;
- tcsetattr(STDIN_FILENO, TCSANOW, &save);
-
- if (sscanf(usrin, "/%[m] %s %[^\n]\n", &c1, v2, v1) == 3 ||
- sscanf(usrin, "/%[Qnjp] %[^\n]\n", &c1, v1) == 2 ||
- sscanf(usrin, "/%[q]\n", &c1) == 1) {
+ else if (fgets(usrin, MSG_MAX, stdin) != NULL) {
+ if (sscanf(usrin, "/%[m] %s %[^\n]\n", &c1, v2, v1) > 2 ||
+ sscanf(usrin, "/%[xMQqnjp] %[^\n]\n", &c1, v1) > 0) {
switch (c1) {
- case 'q': dprintf(fd[1], "quit\n"); break;
- case 'Q': dprintf(fd[1], "quit %s\n", v1); break;
- case 'j': dprintf(fd[1], "join %s\n", v1); break;
- case 'p': dprintf(fd[1], "part %s\n", v1); break;
- case 'n': dprintf(fd[1], "privmsg nickserv :%s\n", v1); break;
- case 'm': dprintf(fd[1], "privmsg %s :%s\n", v2, v1); break;
+ case 'x': dprintf(fd[1], "%s\n", v1); break;
+ case 'q': dprintf(fd[1], "quit\n"); break;
+ case 'Q': dprintf(fd[1], "quit %s\n", v1); break;
+ case 'j': dprintf(fd[1], "join %s\n", v1); break;
+ case 'p': dprintf(fd[1], "part %s\n", v1); break;
+ case 'n': dprintf(fd[1], "names #%s\n", chan); break;
+ case 'M': dprintf(fd[1], "privmsg nickserv :%s\n", v1); break;
+ case 'm': dprintf(fd[1], "privmsg %s :%s\n", v2, v1); break;
}
- } else dprintf(fd[1], "privmsg #%s :%s", chan, usrin);
+ } else dprintf(fd[1], "privmsg #%s :%s", chan, usrin);
}
}
- fprintf(stderr, "<< irc server connection closed\n");
+ if (tcsetattr(STDIN_FILENO, TCSANOW, &save) < 0) return 2;
+ puts("<< connection closed");
}
return 0;
}