2015-08-13 03:01:57 +03:00
|
|
|
|
/* vim: ts=4 sw=4 noexpandtab
|
|
|
|
|
* This file is part of ToaruOS and is released under the terms
|
|
|
|
|
* of the NCSA / University of Illinois License - see LICENSE.md
|
|
|
|
|
* Copyright (C) 2015 Kevin Lange
|
|
|
|
|
*
|
|
|
|
|
* irc - Curses IRC client.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <getopt.h>
|
|
|
|
|
#include <locale.h>
|
2016-01-07 06:00:57 +03:00
|
|
|
|
#include <signal.h>
|
2015-08-13 03:01:57 +03:00
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <time.h>
|
2015-08-13 06:36:41 +03:00
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
|
2015-08-13 03:01:57 +03:00
|
|
|
|
#include <ncurses.h>
|
2016-01-07 08:22:19 +03:00
|
|
|
|
#ifndef A_ITALIC
|
|
|
|
|
#define A_ITALIC A_REVERSE
|
|
|
|
|
#endif
|
2015-08-13 03:01:57 +03:00
|
|
|
|
|
|
|
|
|
#include "lib/pthread.h"
|
2015-08-13 06:36:41 +03:00
|
|
|
|
#include "lib/spinlock.h"
|
2015-08-13 03:01:57 +03:00
|
|
|
|
|
|
|
|
|
#define _ITALIC "\033[3m"
|
|
|
|
|
#define _END "\033[0m\n"
|
|
|
|
|
|
2016-01-07 06:00:57 +03:00
|
|
|
|
#define VERSION_STRING "0.2.0"
|
|
|
|
|
|
2015-08-13 03:01:57 +03:00
|
|
|
|
static char * nick = "toaru-user";
|
|
|
|
|
static char * host = NULL;
|
|
|
|
|
static unsigned short port = 6667;
|
|
|
|
|
static pthread_t read_thread;
|
|
|
|
|
|
|
|
|
|
static char * channel = NULL;
|
|
|
|
|
|
|
|
|
|
static WINDOW * main_win;
|
2016-01-07 06:00:57 +03:00
|
|
|
|
static WINDOW * topic_win;
|
2015-08-13 03:01:57 +03:00
|
|
|
|
static WINDOW * body_win;
|
|
|
|
|
static WINDOW * status_win;
|
|
|
|
|
static WINDOW * input_win;
|
|
|
|
|
|
|
|
|
|
static FILE * sock;
|
2015-08-13 06:36:41 +03:00
|
|
|
|
static FILE * sockb;
|
2015-08-13 03:01:57 +03:00
|
|
|
|
|
2016-01-07 08:22:19 +03:00
|
|
|
|
#define TIME_FMT "%02d:%02d:%02d"
|
|
|
|
|
#define TIME_ARGS hr, min, sec
|
|
|
|
|
|
2015-08-13 03:01:57 +03:00
|
|
|
|
static volatile int c_lock;
|
|
|
|
|
|
|
|
|
|
void show_usage(int argc, char * argv[]) {
|
|
|
|
|
fprintf(stderr,
|
|
|
|
|
"irc - Curses IRC client.\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"usage: %s [-h] [-p port] [-n nick] host\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" -p port " _ITALIC "Specify port to connect to" _END
|
|
|
|
|
" -n nick " _ITALIC "Specify a nick to use" _END
|
|
|
|
|
" -h " _ITALIC "Print this help message" _END
|
|
|
|
|
"\n", argv[0]);
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-07 06:00:57 +03:00
|
|
|
|
int user_color(char * user) {
|
|
|
|
|
int i = 0;
|
|
|
|
|
while (*user) {
|
|
|
|
|
i += *user;
|
|
|
|
|
user++;
|
|
|
|
|
}
|
|
|
|
|
i = i % 5;
|
|
|
|
|
switch (i) {
|
|
|
|
|
case 0: return 2;
|
|
|
|
|
case 1: return 3;
|
|
|
|
|
case 2: return 4;
|
|
|
|
|
case 3: return 6;
|
|
|
|
|
case 4: return 10;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int irc_color_to_pair(int fg, int bg) {
|
|
|
|
|
int _fg = 0;
|
|
|
|
|
int _bg = 0;
|
2016-01-07 07:35:41 +03:00
|
|
|
|
if (fg == -1) {
|
|
|
|
|
if (bg == -1) {
|
|
|
|
|
_fg = 0;
|
|
|
|
|
} else {
|
|
|
|
|
_fg = COLOR_WHITE;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
fg = fg % 16;
|
|
|
|
|
switch (fg) {
|
|
|
|
|
case 0: _fg = COLOR_WHITE + 8; break;
|
|
|
|
|
case 1: _fg = COLOR_BLACK; break;
|
|
|
|
|
case 2: _fg = COLOR_BLUE; break;
|
|
|
|
|
case 3: _fg = COLOR_GREEN; break;
|
|
|
|
|
case 4: _fg = COLOR_RED + 8; break;
|
|
|
|
|
case 5: _fg = COLOR_RED; break;
|
|
|
|
|
case 6: _fg = COLOR_MAGENTA; break;
|
|
|
|
|
case 7: _fg = COLOR_YELLOW; break;
|
|
|
|
|
case 8: _fg = COLOR_YELLOW + 8; break;
|
|
|
|
|
case 9: _fg = COLOR_GREEN + 8; break;
|
|
|
|
|
case 10: _fg = COLOR_CYAN; break;
|
|
|
|
|
case 11: _fg = COLOR_CYAN + 8; break;
|
|
|
|
|
case 12: _fg = COLOR_BLUE + 8; break;
|
|
|
|
|
case 13: _fg = COLOR_MAGENTA + 8; break;
|
|
|
|
|
case 14: _fg = COLOR_BLACK + 8; break;
|
|
|
|
|
case 15: _fg = COLOR_WHITE; break;
|
|
|
|
|
}
|
2016-01-07 06:00:57 +03:00
|
|
|
|
}
|
2016-01-07 07:35:41 +03:00
|
|
|
|
if (bg == -1) {
|
|
|
|
|
_bg = 0;
|
|
|
|
|
} else {
|
|
|
|
|
bg = bg % 16;
|
|
|
|
|
switch (bg) {
|
|
|
|
|
case 0: _bg = COLOR_WHITE + 8; break;
|
|
|
|
|
case 1: _bg = COLOR_BLACK; break;
|
|
|
|
|
case 2: _bg = COLOR_BLUE; break;
|
|
|
|
|
case 3: _bg = COLOR_GREEN; break;
|
|
|
|
|
case 4: _bg = COLOR_RED + 8; break;
|
|
|
|
|
case 5: _bg = COLOR_RED; break;
|
|
|
|
|
case 6: _bg = COLOR_MAGENTA; break;
|
|
|
|
|
case 7: _bg = COLOR_YELLOW; break;
|
|
|
|
|
case 8: _bg = COLOR_YELLOW + 8; break;
|
|
|
|
|
case 9: _bg = COLOR_GREEN + 8; break;
|
|
|
|
|
case 10: _bg = COLOR_CYAN; break;
|
|
|
|
|
case 11: _bg = COLOR_CYAN + 8; break;
|
|
|
|
|
case 12: _bg = COLOR_BLUE + 8; break;
|
|
|
|
|
case 13: _bg = COLOR_MAGENTA + 8; break;
|
|
|
|
|
case 14: _bg = COLOR_BLACK + 8; break;
|
|
|
|
|
case 15: _bg = COLOR_WHITE; break;
|
|
|
|
|
}
|
2016-01-07 06:00:57 +03:00
|
|
|
|
}
|
|
|
|
|
return _fg + _bg * 16;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WRITE(const char *fmt, ...) {
|
|
|
|
|
|
|
|
|
|
static int line_feed_pending = 0;
|
|
|
|
|
|
|
|
|
|
int last_color = 0xFFFFFFFF;
|
|
|
|
|
int bold_on = 0;
|
2016-01-07 08:22:19 +03:00
|
|
|
|
int italic_on = 0;
|
2016-01-07 06:00:57 +03:00
|
|
|
|
|
|
|
|
|
va_list args;
|
|
|
|
|
va_start(args, fmt);
|
|
|
|
|
char * tmp;
|
|
|
|
|
vasprintf(&tmp, fmt, args);
|
|
|
|
|
va_end(args);
|
|
|
|
|
|
|
|
|
|
spin_lock(&c_lock);
|
|
|
|
|
char * c = tmp;
|
|
|
|
|
while (*c) {
|
|
|
|
|
if (*c == '\n') {
|
|
|
|
|
if (line_feed_pending) {
|
|
|
|
|
wprintw(body_win, "\n");
|
|
|
|
|
}
|
|
|
|
|
line_feed_pending = 1;
|
|
|
|
|
c++;
|
|
|
|
|
continue;
|
|
|
|
|
} else {
|
|
|
|
|
if (line_feed_pending) {
|
|
|
|
|
line_feed_pending = 0;
|
|
|
|
|
wprintw(body_win, "\n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (*c == 0x03) {
|
|
|
|
|
c++;
|
|
|
|
|
int i = -1;
|
|
|
|
|
int j = -1;
|
|
|
|
|
if (*c >= '0' && *c <= '9') {
|
|
|
|
|
i = (*c - '0');
|
|
|
|
|
c++;
|
|
|
|
|
}
|
|
|
|
|
if (*c >= '0' && *c <= '9') {
|
|
|
|
|
i *= 10;
|
|
|
|
|
i += (*c - '0');
|
|
|
|
|
c++;
|
|
|
|
|
}
|
|
|
|
|
if (*c == ',') {
|
2016-01-07 07:35:41 +03:00
|
|
|
|
c++;
|
2016-01-07 06:00:57 +03:00
|
|
|
|
if (*c >= '0' && *c <= '9') {
|
|
|
|
|
j = (*c - '0');
|
|
|
|
|
c++;
|
|
|
|
|
}
|
|
|
|
|
if (*c >= '0' && *c <= '9') {
|
|
|
|
|
j *= 10;
|
|
|
|
|
j += (*c - '0');
|
|
|
|
|
c++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
int t = irc_color_to_pair(i,j);
|
|
|
|
|
if (t != last_color && last_color != 0xFFFFFFFF) {
|
|
|
|
|
wattroff(body_win, COLOR_PAIR(last_color));
|
|
|
|
|
}
|
|
|
|
|
if (i != -1) {
|
|
|
|
|
wattron(body_win, COLOR_PAIR(t));
|
|
|
|
|
last_color = t;
|
|
|
|
|
}
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (*c == 0x02) {
|
|
|
|
|
if (bold_on) {
|
|
|
|
|
wattroff(body_win, A_BOLD);
|
|
|
|
|
bold_on = 0;
|
|
|
|
|
} else {
|
|
|
|
|
wattron(body_win, A_BOLD);
|
|
|
|
|
bold_on = 1;
|
|
|
|
|
}
|
|
|
|
|
c++;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2016-01-07 08:22:19 +03:00
|
|
|
|
if (*c == 0x16) {
|
|
|
|
|
if (italic_on) {
|
|
|
|
|
wattroff(body_win, A_ITALIC);
|
|
|
|
|
italic_on = 0;
|
|
|
|
|
} else {
|
|
|
|
|
wattron(body_win, A_ITALIC);
|
|
|
|
|
italic_on = 1;
|
|
|
|
|
}
|
|
|
|
|
c++;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2016-01-07 06:00:57 +03:00
|
|
|
|
if (*c == 0x0f) {
|
|
|
|
|
if (last_color != 0xFFFFFFFF) {
|
|
|
|
|
wattroff(body_win, COLOR_PAIR(last_color));
|
|
|
|
|
last_color = 0xFFFFFFFF;
|
|
|
|
|
}
|
|
|
|
|
bold_on = 0;
|
|
|
|
|
wattroff(body_win, A_BOLD);
|
|
|
|
|
c++;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
wprintw(body_win, "%c", *c);
|
|
|
|
|
c++;
|
|
|
|
|
}
|
|
|
|
|
wattroff(body_win, COLOR_PAIR(last_color));
|
|
|
|
|
wattroff(body_win, A_BOLD);
|
2016-01-07 08:22:19 +03:00
|
|
|
|
wattroff(body_win, A_ITALIC);
|
2016-01-07 06:00:57 +03:00
|
|
|
|
free(tmp);
|
|
|
|
|
wrefresh(body_win);
|
|
|
|
|
spin_unlock(&c_lock);
|
|
|
|
|
}
|
2015-08-13 03:01:57 +03:00
|
|
|
|
|
2016-01-11 21:07:08 +03:00
|
|
|
|
void redraw_status(void) {
|
|
|
|
|
|
|
|
|
|
spin_lock(&c_lock);
|
|
|
|
|
wclear(status_win);
|
|
|
|
|
wmove(status_win, 0, 0);
|
|
|
|
|
wprintw(status_win, "[%s] ", nick);
|
|
|
|
|
spin_unlock(&c_lock);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-13 03:01:57 +03:00
|
|
|
|
void refresh_all(void) {
|
|
|
|
|
|
2016-01-07 06:00:57 +03:00
|
|
|
|
wrefresh(topic_win);
|
2015-08-13 03:01:57 +03:00
|
|
|
|
wrefresh(body_win);
|
|
|
|
|
wrefresh(status_win);
|
|
|
|
|
wrefresh(input_win);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void get_time(int * h, int * m, int * s) {
|
|
|
|
|
time_t rawtime;
|
|
|
|
|
time(&rawtime);
|
|
|
|
|
struct tm *tm_struct = localtime(&rawtime);
|
|
|
|
|
|
|
|
|
|
*h = tm_struct->tm_hour;
|
|
|
|
|
*m = tm_struct->tm_min;
|
|
|
|
|
*s = tm_struct->tm_sec;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void handle(char * line) {
|
|
|
|
|
char * c = line;
|
|
|
|
|
|
|
|
|
|
while (c < line + strlen(line)) {
|
|
|
|
|
char * e = strstr(c, "\r\n");
|
|
|
|
|
if (e > line + strlen(line)) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!e) {
|
|
|
|
|
WRITE(c);
|
|
|
|
|
goto next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*e = '\0';
|
|
|
|
|
|
|
|
|
|
if (strstr(c, "PING") == c) {
|
|
|
|
|
char tmp[100];
|
|
|
|
|
char * t = strstr(c, ":");
|
2015-08-13 06:36:41 +03:00
|
|
|
|
fprintf(sock, "PONG %s\r\n", t);
|
|
|
|
|
fflush(sock);
|
2015-08-13 03:01:57 +03:00
|
|
|
|
goto next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char * user;
|
|
|
|
|
char * command;
|
|
|
|
|
char * channel;
|
|
|
|
|
char * message;
|
|
|
|
|
|
|
|
|
|
user = c;
|
2016-01-07 08:22:19 +03:00
|
|
|
|
if (user[0] == ':') { user++; }
|
2015-08-13 03:01:57 +03:00
|
|
|
|
|
|
|
|
|
command = strstr(user, " ");
|
|
|
|
|
if (!command) {
|
|
|
|
|
WRITE("%s\n", user);
|
|
|
|
|
goto next;
|
|
|
|
|
}
|
|
|
|
|
command[0] = '\0';
|
|
|
|
|
command++;
|
|
|
|
|
|
|
|
|
|
channel = strstr(command, " ");
|
|
|
|
|
if (!channel) {
|
|
|
|
|
WRITE("%s %s\n", user, command);
|
|
|
|
|
goto next;
|
|
|
|
|
}
|
|
|
|
|
channel[0] = '\0';
|
|
|
|
|
channel++;
|
|
|
|
|
|
2016-01-07 08:22:19 +03:00
|
|
|
|
message = strstr(channel, " ");
|
|
|
|
|
if (message) {
|
2015-08-13 03:01:57 +03:00
|
|
|
|
message[0] = '\0';
|
|
|
|
|
message++;
|
|
|
|
|
if (message[0] == ':') { message++; }
|
2016-01-07 08:22:19 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int hr, min, sec;
|
|
|
|
|
get_time(&hr, &min, &sec);
|
|
|
|
|
|
|
|
|
|
if (!strcmp(command, "PRIVMSG")) {
|
|
|
|
|
if (!message) continue;
|
2015-08-13 03:01:57 +03:00
|
|
|
|
char * t = strstr(user, "!");
|
|
|
|
|
if (t) { t[0] = '\0'; }
|
|
|
|
|
t = strstr(user, "@");
|
|
|
|
|
if (t) { t[0] = '\0'; }
|
|
|
|
|
|
|
|
|
|
if (strstr(message, "\001ACTION ") == message) {
|
|
|
|
|
message = message + 8;
|
|
|
|
|
char * x = strstr(message, "\001");
|
|
|
|
|
if (x) *x = '\0';
|
2016-01-07 08:22:19 +03:00
|
|
|
|
WRITE(TIME_FMT " * %d%s %s\n", TIME_ARGS, user_color(user), user, message);
|
2015-08-13 03:01:57 +03:00
|
|
|
|
} else {
|
2016-01-07 08:22:19 +03:00
|
|
|
|
WRITE(TIME_FMT " 14<%d%s14> %s\n", TIME_ARGS, user_color(user), user, message);
|
2016-01-07 06:00:57 +03:00
|
|
|
|
}
|
|
|
|
|
} else if (!strcmp(command, "332")) {
|
|
|
|
|
if (!message) {
|
2016-01-07 08:22:19 +03:00
|
|
|
|
continue;
|
2015-08-13 03:01:57 +03:00
|
|
|
|
}
|
2016-01-07 06:00:57 +03:00
|
|
|
|
spin_lock(&c_lock);
|
|
|
|
|
wmove(topic_win, 0, 0);
|
|
|
|
|
wprintw(topic_win, " %s", message);
|
|
|
|
|
wrefresh(topic_win);
|
|
|
|
|
spin_unlock(&c_lock);
|
2016-01-07 08:22:19 +03:00
|
|
|
|
} else if (!strcmp(command, "JOIN")) {
|
|
|
|
|
char * t = strstr(user, "!");
|
|
|
|
|
if (t) { t[0] = '\0'; }
|
|
|
|
|
t = strstr(user, "@");
|
|
|
|
|
if (t) { t[0] = '\0'; }
|
|
|
|
|
if (channel[0] == ':') { channel++; }
|
|
|
|
|
|
|
|
|
|
WRITE(TIME_FMT " 12-!12-11 %s has joined %s\n", TIME_ARGS, user, channel);
|
|
|
|
|
} else if (!strcmp(command, "PART")) {
|
|
|
|
|
char * t = strstr(user, "!");
|
|
|
|
|
if (t) { t[0] = '\0'; }
|
|
|
|
|
t = strstr(user, "@");
|
|
|
|
|
if (t) { t[0] = '\0'; }
|
|
|
|
|
if (channel[0] == ':') { channel++; }
|
|
|
|
|
|
|
|
|
|
WRITE(TIME_FMT " 12-!12-10 %s has left %s\n", TIME_ARGS, user, channel);
|
|
|
|
|
} else if (!strcmp(command,"372")) {
|
|
|
|
|
WRITE(TIME_FMT " 14%s %s\n", TIME_ARGS, user, message ? message : "");
|
|
|
|
|
} else if (!strcmp(command,"376")) {
|
|
|
|
|
WRITE(TIME_FMT " 14%s (end of MOTD)\n", TIME_ARGS, user);
|
2015-08-13 03:01:57 +03:00
|
|
|
|
} else {
|
2016-01-07 08:22:19 +03:00
|
|
|
|
WRITE(TIME_FMT " 10%s %s %s %s\n", TIME_ARGS, user, command, channel, message ? message : "");
|
2015-08-13 03:01:57 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
next:
|
|
|
|
|
if (!e) break;
|
|
|
|
|
c = e + 2;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void * irc_read_thread(void * garbage) {
|
|
|
|
|
|
2015-08-13 06:36:41 +03:00
|
|
|
|
char * line = malloc(1024);
|
2015-08-13 03:01:57 +03:00
|
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
|
memset(line, 0, 1024);
|
2015-08-13 06:36:41 +03:00
|
|
|
|
fgets(line, 1024, sockb);
|
2015-08-13 03:01:57 +03:00
|
|
|
|
handle(line);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void do_thing(char * thing) {
|
|
|
|
|
if (!strcmp(thing, "/help")) {
|
|
|
|
|
WRITE("[help] Herp derp you asked for help, silly you, there is none!\n");
|
2016-01-07 07:15:43 +03:00
|
|
|
|
} else if (!strcmp(thing, "/quit") || strstr(thing,"/quit ") == thing) {
|
2016-01-07 06:00:57 +03:00
|
|
|
|
char * m = strstr(thing, " "); if (m) m++;
|
2015-08-13 03:01:57 +03:00
|
|
|
|
endwin();
|
2016-01-07 06:00:57 +03:00
|
|
|
|
fprintf(sock,"QUIT :%s\r\n", m ? m : "http://toaruos.org/");
|
|
|
|
|
fflush(sock);
|
2016-09-10 15:01:54 +03:00
|
|
|
|
pthread_kill(read_thread, SIGQUIT);
|
2015-08-13 03:01:57 +03:00
|
|
|
|
exit(0);
|
2016-01-07 07:15:43 +03:00
|
|
|
|
} else if (!strcmp(thing, "/part") || strstr(thing,"/part ") == thing) {
|
2016-01-07 06:00:57 +03:00
|
|
|
|
char * m = strstr(thing, " "); if (m) m++;
|
|
|
|
|
fprintf(sock,"PART %s%s%s\r\n",channel,m?" :":"",m?m:"");
|
|
|
|
|
fflush(sock);
|
|
|
|
|
free(channel);
|
2015-08-13 03:01:57 +03:00
|
|
|
|
} else if (strstr(thing, "/join ") == thing) {
|
|
|
|
|
char * m = strstr(thing, " ");
|
|
|
|
|
m++;
|
|
|
|
|
fprintf(sock, "JOIN %s\r\n", m);
|
|
|
|
|
fflush(sock);
|
|
|
|
|
channel = strdup(m);
|
2016-01-11 21:07:08 +03:00
|
|
|
|
} else if (strstr(thing, "/nick ") == thing) {
|
|
|
|
|
char * m = strstr(thing, " ");
|
|
|
|
|
m++;
|
|
|
|
|
fprintf(sock, "NICK %s\r\n", m);
|
|
|
|
|
fflush(sock);
|
|
|
|
|
/* We should totally free that, but whatever. */
|
|
|
|
|
nick = strdup(m);
|
|
|
|
|
redraw_status();
|
|
|
|
|
refresh_all();
|
2016-01-07 08:22:19 +03:00
|
|
|
|
} else if (strstr(thing, "/me ") == thing) {
|
|
|
|
|
char * m = strstr(thing, " ");
|
|
|
|
|
m++;
|
|
|
|
|
int hr, min, sec;
|
|
|
|
|
get_time(&hr, &min, &sec);
|
|
|
|
|
WRITE("%02d:%02d:%02d * %s %s\n", hr, min, sec, nick, m);
|
|
|
|
|
fprintf(sock, "PRIVMSG %s :\001ACTION %s\001\r\n", channel, m);
|
|
|
|
|
fflush(sock);
|
2016-01-11 21:07:08 +03:00
|
|
|
|
} else if (strstr(thing, "/quote ") == thing) {
|
|
|
|
|
char * m = strstr(thing, " ");
|
|
|
|
|
m++;
|
|
|
|
|
fprintf(sock, "%s\r\n", m);
|
|
|
|
|
fflush(sock);
|
2015-08-13 03:01:57 +03:00
|
|
|
|
} else if (strlen(thing) > 0 && thing[0] == '/') {
|
|
|
|
|
WRITE("[system] Unknown command: %s\n", thing);
|
2016-01-07 06:00:57 +03:00
|
|
|
|
} else if (strlen(thing) > 0) {
|
2015-08-13 03:01:57 +03:00
|
|
|
|
if (!channel) {
|
|
|
|
|
WRITE("[system] Not in a channel.\n");
|
|
|
|
|
} else {
|
|
|
|
|
int hr, min, sec;
|
|
|
|
|
get_time(&hr, &min, &sec);
|
2016-01-07 08:22:19 +03:00
|
|
|
|
WRITE("%02d:%02d:%02d 14<%s14> %s\n", hr, min, sec, nick, thing);
|
2015-08-13 03:01:57 +03:00
|
|
|
|
fprintf(sock, "PRIVMSG %s :%s\r\n", channel, thing);
|
|
|
|
|
fflush(sock);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-07 06:00:57 +03:00
|
|
|
|
void SIGWINCH_handler(int sig) {
|
|
|
|
|
(void)sig;
|
|
|
|
|
|
|
|
|
|
spin_lock(&c_lock);
|
|
|
|
|
|
|
|
|
|
endwin();
|
|
|
|
|
|
|
|
|
|
refresh();
|
|
|
|
|
clear();
|
|
|
|
|
|
|
|
|
|
int w = COLS;
|
|
|
|
|
int h = LINES;
|
|
|
|
|
|
|
|
|
|
/* Move */
|
|
|
|
|
mvwin(topic_win,0,0);
|
|
|
|
|
mvwin(body_win,1,0);
|
|
|
|
|
mvwin(status_win,h-2,0);
|
|
|
|
|
mvwin(input_win,h-1,0);
|
|
|
|
|
|
|
|
|
|
/* Resize */
|
|
|
|
|
wresize(topic_win,1,w);
|
|
|
|
|
wresize(body_win,h-3,w);
|
|
|
|
|
wresize(status_win,1,w);
|
|
|
|
|
wresize(input_win,1,w);
|
|
|
|
|
|
|
|
|
|
refresh_all();
|
|
|
|
|
|
|
|
|
|
spin_unlock(&c_lock);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2015-08-13 03:01:57 +03:00
|
|
|
|
int main(int argc, char * argv[]) {
|
|
|
|
|
|
|
|
|
|
int c;
|
|
|
|
|
|
|
|
|
|
while ((c = getopt(argc, argv, "hp:n:")) != -1) {
|
|
|
|
|
switch (c) {
|
|
|
|
|
|
|
|
|
|
case 'n':
|
|
|
|
|
nick = optarg;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'p':
|
|
|
|
|
port = atoi(optarg);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'h':
|
|
|
|
|
default:
|
|
|
|
|
show_usage(argc,argv);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (optind >= argc) {
|
|
|
|
|
show_usage(argc,argv);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
setlocale (LC_ALL, "");
|
|
|
|
|
|
|
|
|
|
host = argv[optind];
|
|
|
|
|
|
|
|
|
|
char tmphost[512];
|
|
|
|
|
sprintf(tmphost, "/dev/net/%s:%d", host, port);
|
2015-08-13 06:36:41 +03:00
|
|
|
|
int sockfd = open(tmphost, O_RDWR);
|
|
|
|
|
sock = fdopen(sockfd, "w");
|
|
|
|
|
sockb = fdopen(sockfd, "r");
|
2015-08-13 03:01:57 +03:00
|
|
|
|
|
|
|
|
|
if (!sock) {
|
|
|
|
|
fprintf(stderr, "%s: Connection failed or network not available.\n", argv[0]);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
main_win = initscr();
|
|
|
|
|
start_color();
|
2016-01-07 06:00:57 +03:00
|
|
|
|
use_default_colors();
|
|
|
|
|
assume_default_colors(-1,-1);
|
|
|
|
|
|
2016-01-07 07:15:43 +03:00
|
|
|
|
for (int bg = 1; bg < 16; ++bg) {
|
2016-01-07 07:35:41 +03:00
|
|
|
|
for (int fg = 0; fg < 16; ++fg) {
|
|
|
|
|
init_pair(fg+bg*16, fg, bg);
|
2016-01-07 06:00:57 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
2015-08-13 03:01:57 +03:00
|
|
|
|
|
2016-01-07 07:15:43 +03:00
|
|
|
|
for (int fg = 1; fg < 16; ++fg) {
|
|
|
|
|
init_pair(fg, fg, -1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2015-08-13 03:01:57 +03:00
|
|
|
|
int w, h;
|
|
|
|
|
getmaxyx(main_win, h, w);
|
|
|
|
|
|
2016-01-07 06:00:57 +03:00
|
|
|
|
topic_win = newwin(1, w, 0, 0);
|
|
|
|
|
body_win = newwin(h-3, w, 1, 0);
|
2015-08-13 03:01:57 +03:00
|
|
|
|
status_win = newwin(1, w, h-2, 0);
|
|
|
|
|
input_win = newwin(1, w, h-1, 0);
|
|
|
|
|
|
2016-01-07 06:00:57 +03:00
|
|
|
|
signal(SIGWINCH, SIGWINCH_handler);
|
|
|
|
|
|
2015-08-13 03:01:57 +03:00
|
|
|
|
scrollok(body_win, TRUE);
|
|
|
|
|
|
2016-01-07 06:00:57 +03:00
|
|
|
|
wbkgd(topic_win, COLOR_PAIR(COLOR_WHITE+COLOR_BLUE*16));
|
|
|
|
|
wbkgd(body_win, COLOR_PAIR(0));
|
|
|
|
|
wbkgd(status_win, COLOR_PAIR(COLOR_WHITE+COLOR_BLUE*16));
|
|
|
|
|
wbkgd(input_win, COLOR_PAIR(0));
|
2015-08-13 03:01:57 +03:00
|
|
|
|
|
|
|
|
|
/* Write the welcome thing to the body */
|
|
|
|
|
wprintw(body_win, " - Toaru IRC v. %s - \n", VERSION_STRING);
|
|
|
|
|
wprintw(body_win, " Copyright 2015 Kevin Lange\n");
|
|
|
|
|
wprintw(body_win, " http://toaruos.org - http://github.com/klange/toaruos\n");
|
|
|
|
|
wprintw(body_win, "\n");
|
|
|
|
|
wprintw(body_win, " For help, type /help.\n");
|
|
|
|
|
|
2016-01-07 06:00:57 +03:00
|
|
|
|
wmove(topic_win, 0, 0);
|
|
|
|
|
wprintw(topic_win, " Toaru IRC v. %s", VERSION_STRING);
|
|
|
|
|
|
2015-08-13 03:01:57 +03:00
|
|
|
|
/* Update status */
|
2015-08-14 05:49:32 +03:00
|
|
|
|
wmove(status_win, 0, 0);
|
|
|
|
|
wprintw(status_win, "[%s] ", nick);
|
2015-08-13 03:01:57 +03:00
|
|
|
|
|
|
|
|
|
refresh_all();
|
|
|
|
|
|
|
|
|
|
pthread_create(&read_thread, NULL, irc_read_thread, NULL);
|
|
|
|
|
|
|
|
|
|
fprintf(sock, "NICK %s\r\nUSER %s * 0 :%s\r\n", nick, nick, nick);
|
|
|
|
|
fflush(sock);
|
|
|
|
|
|
2015-08-13 06:36:41 +03:00
|
|
|
|
char * buf = malloc(1024);
|
|
|
|
|
|
2015-08-13 03:01:57 +03:00
|
|
|
|
while (1) {
|
|
|
|
|
spin_lock(&c_lock);
|
|
|
|
|
wmove(input_win, 0, 0);
|
|
|
|
|
wprintw(input_win, "[%s] ", channel ? channel : "(none)");
|
2015-08-13 06:36:41 +03:00
|
|
|
|
memset(buf, 0, sizeof(buf));
|
2015-08-13 03:01:57 +03:00
|
|
|
|
spin_unlock(&c_lock);
|
|
|
|
|
wgetstr(input_win, buf);
|
2016-01-07 06:00:57 +03:00
|
|
|
|
|
2015-08-13 03:01:57 +03:00
|
|
|
|
do_thing(buf);
|
2016-01-07 06:00:57 +03:00
|
|
|
|
|
|
|
|
|
spin_lock(&c_lock);
|
2015-08-13 03:01:57 +03:00
|
|
|
|
wclear(input_win);
|
|
|
|
|
wrefresh(input_win);
|
2016-01-07 06:00:57 +03:00
|
|
|
|
spin_unlock(&c_lock);
|
2015-08-13 03:01:57 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
endwin();
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|