parent
ba524ed804
commit
b20be7cbad
38
chat.c
38
chat.c
|
@ -17,6 +17,7 @@
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <limits.h>
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
@ -39,7 +40,7 @@
|
||||||
static void genCert(const char *path) {
|
static void genCert(const char *path) {
|
||||||
const char *name = strrchr(path, '/');
|
const char *name = strrchr(path, '/');
|
||||||
name = (name ? &name[1] : path);
|
name = (name ? &name[1] : path);
|
||||||
char subj[256];
|
char subj[4 + NAME_MAX];
|
||||||
snprintf(subj, sizeof(subj), "/CN=%.*s", (int)strcspn(name, "."), name);
|
snprintf(subj, sizeof(subj), "/CN=%.*s", (int)strcspn(name, "."), name);
|
||||||
umask(0066);
|
umask(0066);
|
||||||
execlp(
|
execlp(
|
||||||
|
@ -56,13 +57,11 @@ char *idNames[IDCap] = {
|
||||||
[Debug] = "<debug>",
|
[Debug] = "<debug>",
|
||||||
[Network] = "<network>",
|
[Network] = "<network>",
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Color idColors[IDCap] = {
|
enum Color idColors[IDCap] = {
|
||||||
[None] = Black,
|
[None] = Black,
|
||||||
[Debug] = Green,
|
[Debug] = Green,
|
||||||
[Network] = Gray,
|
[Network] = Gray,
|
||||||
};
|
};
|
||||||
|
|
||||||
uint idNext = Network + 1;
|
uint idNext = Network + 1;
|
||||||
|
|
||||||
struct Network network;
|
struct Network network;
|
||||||
|
@ -79,21 +78,9 @@ static void exitSave(void) {
|
||||||
|
|
||||||
uint32_t hashInit;
|
uint32_t hashInit;
|
||||||
|
|
||||||
int utilPipe[2] = { -1, -1 };
|
uint execID;
|
||||||
int execPipe[2] = { -1, -1 };
|
int execPipe[2] = { -1, -1 };
|
||||||
|
int utilPipe[2] = { -1, -1 };
|
||||||
static void utilRead(void) {
|
|
||||||
char buf[1024];
|
|
||||||
ssize_t len = read(utilPipe[0], buf, sizeof(buf) - 1);
|
|
||||||
if (len < 0) err(EX_IOERR, "read");
|
|
||||||
if (!len) return;
|
|
||||||
buf[len] = '\0';
|
|
||||||
char *ptr = buf;
|
|
||||||
while (ptr) {
|
|
||||||
char *line = strsep(&ptr, "\n");
|
|
||||||
if (line[0]) uiFormat(Network, Warm, NULL, "%s", line);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void execRead(void) {
|
static void execRead(void) {
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
|
@ -108,6 +95,19 @@ static void execRead(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void utilRead(void) {
|
||||||
|
char buf[1024];
|
||||||
|
ssize_t len = read(utilPipe[0], buf, sizeof(buf) - 1);
|
||||||
|
if (len < 0) err(EX_IOERR, "read");
|
||||||
|
if (!len) return;
|
||||||
|
buf[len] = '\0';
|
||||||
|
char *ptr = buf;
|
||||||
|
while (ptr) {
|
||||||
|
char *line = strsep(&ptr, "\n");
|
||||||
|
if (line[0]) uiFormat(Network, Warm, NULL, "%s", line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static volatile sig_atomic_t signals[NSIG];
|
static volatile sig_atomic_t signals[NSIG];
|
||||||
static void signalHandler(int signal) {
|
static void signalHandler(int signal) {
|
||||||
signals[signal] = 1;
|
signals[signal] = 1;
|
||||||
|
@ -188,7 +188,7 @@ int main(int argc, char *argv[]) {
|
||||||
if (!user) user = nick;
|
if (!user) user = nick;
|
||||||
if (!real) real = nick;
|
if (!real) real = nick;
|
||||||
|
|
||||||
set(&network.name, host);
|
// Modes defined in RFC 1459:
|
||||||
set(&network.chanTypes, "#&");
|
set(&network.chanTypes, "#&");
|
||||||
set(&network.prefixes, "@+");
|
set(&network.prefixes, "@+");
|
||||||
set(&network.prefixModes, "ov");
|
set(&network.prefixModes, "ov");
|
||||||
|
@ -196,6 +196,8 @@ int main(int argc, char *argv[]) {
|
||||||
set(&network.paramModes, "k");
|
set(&network.paramModes, "k");
|
||||||
set(&network.setParamModes, "l");
|
set(&network.setParamModes, "l");
|
||||||
set(&network.channelModes, "imnpst");
|
set(&network.channelModes, "imnpst");
|
||||||
|
|
||||||
|
set(&network.name, host);
|
||||||
set(&self.nick, "*");
|
set(&self.nick, "*");
|
||||||
commandComplete();
|
commandComplete();
|
||||||
|
|
||||||
|
|
67
chat.h
67
chat.h
|
@ -65,8 +65,8 @@ static inline uint idFor(const char *name) {
|
||||||
if (id) return id;
|
if (id) return id;
|
||||||
if (idNext == IDCap) return Network;
|
if (idNext == IDCap) return Network;
|
||||||
idNames[idNext] = strdup(name);
|
idNames[idNext] = strdup(name);
|
||||||
if (!idNames[idNext]) err(EX_OSERR, "strdup");
|
|
||||||
idColors[idNext] = Default;
|
idColors[idNext] = Default;
|
||||||
|
if (!idNames[idNext]) err(EX_OSERR, "strdup");
|
||||||
return idNext++;
|
return idNext++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,9 +79,22 @@ static inline enum Color hash(const char *str) {
|
||||||
hash ^= *str;
|
hash ^= *str;
|
||||||
hash *= 0x27220A95;
|
hash *= 0x27220A95;
|
||||||
}
|
}
|
||||||
return 2 + hash % 74;
|
return Blue + hash % 74;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern struct Network {
|
||||||
|
char *name;
|
||||||
|
char *chanTypes;
|
||||||
|
char *prefixes;
|
||||||
|
char *prefixModes;
|
||||||
|
char *listModes;
|
||||||
|
char *paramModes;
|
||||||
|
char *setParamModes;
|
||||||
|
char *channelModes;
|
||||||
|
char excepts;
|
||||||
|
char invex;
|
||||||
|
} network;
|
||||||
|
|
||||||
#define ENUM_CAP \
|
#define ENUM_CAP \
|
||||||
X("extended-join", CapExtendedJoin) \
|
X("extended-join", CapExtendedJoin) \
|
||||||
X("invite-notify", CapInviteNotify) \
|
X("invite-notify", CapInviteNotify) \
|
||||||
|
@ -96,25 +109,12 @@ enum Cap {
|
||||||
#undef X
|
#undef X
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct Network {
|
|
||||||
char *name;
|
|
||||||
char *chanTypes;
|
|
||||||
char *prefixes;
|
|
||||||
char *prefixModes;
|
|
||||||
char *listModes;
|
|
||||||
char *paramModes;
|
|
||||||
char *setParamModes;
|
|
||||||
char *channelModes;
|
|
||||||
char excepts;
|
|
||||||
char invex;
|
|
||||||
} network;
|
|
||||||
|
|
||||||
extern struct Self {
|
extern struct Self {
|
||||||
bool debug;
|
bool debug;
|
||||||
bool restricted;
|
bool restricted;
|
||||||
char *plain;
|
|
||||||
const char *join;
|
|
||||||
enum Cap caps;
|
enum Cap caps;
|
||||||
|
char *plain;
|
||||||
|
char *join;
|
||||||
char *nick;
|
char *nick;
|
||||||
char *user;
|
char *user;
|
||||||
enum Color color;
|
enum Color color;
|
||||||
|
@ -155,25 +155,8 @@ void ircFormat(const char *format, ...)
|
||||||
__attribute__((format(printf, 1, 2)));
|
__attribute__((format(printf, 1, 2)));
|
||||||
void ircClose(void);
|
void ircClose(void);
|
||||||
|
|
||||||
extern struct Replies {
|
|
||||||
uint away;
|
|
||||||
uint join;
|
|
||||||
uint list;
|
|
||||||
uint names;
|
|
||||||
uint topic;
|
|
||||||
uint whois;
|
|
||||||
} replies;
|
|
||||||
|
|
||||||
uint execID;
|
uint execID;
|
||||||
int execPipe[2];
|
int execPipe[2];
|
||||||
|
|
||||||
void handle(struct Message msg);
|
|
||||||
void command(uint id, char *input);
|
|
||||||
const char *commandIsPrivmsg(uint id, const char *input);
|
|
||||||
const char *commandIsNotice(uint id, const char *input);
|
|
||||||
const char *commandIsAction(uint id, const char *input);
|
|
||||||
void commandComplete(void);
|
|
||||||
|
|
||||||
int utilPipe[2];
|
int utilPipe[2];
|
||||||
|
|
||||||
enum { UtilCap = 16 };
|
enum { UtilCap = 16 };
|
||||||
|
@ -190,6 +173,22 @@ static inline void utilPush(struct Util *util, const char *arg) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern struct Replies {
|
||||||
|
uint away;
|
||||||
|
uint join;
|
||||||
|
uint list;
|
||||||
|
uint names;
|
||||||
|
uint topic;
|
||||||
|
uint whois;
|
||||||
|
} replies;
|
||||||
|
|
||||||
|
void handle(struct Message msg);
|
||||||
|
void command(uint id, char *input);
|
||||||
|
const char *commandIsPrivmsg(uint id, const char *input);
|
||||||
|
const char *commandIsNotice(uint id, const char *input);
|
||||||
|
const char *commandIsAction(uint id, const char *input);
|
||||||
|
void commandComplete(void);
|
||||||
|
|
||||||
enum Heat { Cold, Warm, Hot };
|
enum Heat { Cold, Warm, Hot };
|
||||||
extern struct Util uiNotifyUtil;
|
extern struct Util uiNotifyUtil;
|
||||||
void uiInit(void);
|
void uiInit(void);
|
||||||
|
|
103
command.c
103
command.c
|
@ -39,53 +39,45 @@ static void commandQuote(uint id, char *params) {
|
||||||
if (params) ircFormat("%s\r\n", params);
|
if (params) ircFormat("%s\r\n", params);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void commandPrivmsg(uint id, char *params) {
|
static void echoMessage(char *cmd, uint id, char *params) {
|
||||||
if (!params || !params[0]) return;
|
if (!params || !params[0]) return;
|
||||||
ircFormat("PRIVMSG %s :%s\r\n", idNames[id], params);
|
ircFormat("%s %s :%s\r\n", cmd, idNames[id], params);
|
||||||
struct Message msg = {
|
struct Message msg = {
|
||||||
.nick = self.nick,
|
.nick = self.nick,
|
||||||
.user = self.user,
|
.user = self.user,
|
||||||
.cmd = "PRIVMSG",
|
.cmd = cmd,
|
||||||
.params[0] = idNames[id],
|
.params[0] = idNames[id],
|
||||||
.params[1] = params,
|
.params[1] = params,
|
||||||
};
|
};
|
||||||
handle(msg);
|
handle(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void commandPrivmsg(uint id, char *params) {
|
||||||
|
echoMessage("PRIVMSG", id, params);
|
||||||
|
}
|
||||||
|
|
||||||
static void commandNotice(uint id, char *params) {
|
static void commandNotice(uint id, char *params) {
|
||||||
if (!params || !params[0]) return;
|
echoMessage("NOTICE", id, params);
|
||||||
ircFormat("NOTICE %s :%s\r\n", idNames[id], params);
|
|
||||||
struct Message msg = {
|
|
||||||
.nick = self.nick,
|
|
||||||
.user = self.user,
|
|
||||||
.cmd = "NOTICE",
|
|
||||||
.params[0] = idNames[id],
|
|
||||||
.params[1] = params,
|
|
||||||
};
|
|
||||||
handle(msg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void commandMe(uint id, char *params) {
|
static void commandMe(uint id, char *params) {
|
||||||
char buf[512];
|
char buf[512];
|
||||||
snprintf(buf, sizeof(buf), "\1ACTION %s\1", (params ? params : ""));
|
snprintf(buf, sizeof(buf), "\1ACTION %s\1", (params ? params : ""));
|
||||||
commandPrivmsg(id, buf);
|
echoMessage("PRIVMSG", id, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void commandMsg(uint id, char *params) {
|
static void commandMsg(uint id, char *params) {
|
||||||
(void)id;
|
id = idFor(strsep(¶ms, " "));
|
||||||
char *nick = strsep(¶ms, " ");
|
echoMessage("PRIVMSG", id, params);
|
||||||
if (!params) return;
|
|
||||||
commandPrivmsg(idFor(nick), params);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void commandJoin(uint id, char *params) {
|
static void commandJoin(uint id, char *params) {
|
||||||
|
if (!params) params = idNames[id];
|
||||||
uint count = 1;
|
uint count = 1;
|
||||||
if (params) {
|
for (char *ch = params; *ch && *ch != ' '; ++ch) {
|
||||||
for (char *ch = params; *ch && *ch != ' '; ++ch) {
|
if (*ch == ',') count++;
|
||||||
if (*ch == ',') count++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ircFormat("JOIN %s\r\n", (params ? params : idNames[id]));
|
ircFormat("JOIN %s\r\n", params);
|
||||||
replies.join += count;
|
replies.join += count;
|
||||||
replies.topic += count;
|
replies.topic += count;
|
||||||
replies.names += count;
|
replies.names += count;
|
||||||
|
@ -101,7 +93,7 @@ static void commandPart(uint id, char *params) {
|
||||||
|
|
||||||
static void commandQuit(uint id, char *params) {
|
static void commandQuit(uint id, char *params) {
|
||||||
(void)id;
|
(void)id;
|
||||||
set(&self.quit, (params ? params : "Goodbye"));
|
set(&self.quit, (params ? params : "nyaa~"));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void commandNick(uint id, char *params) {
|
static void commandNick(uint id, char *params) {
|
||||||
|
@ -131,7 +123,7 @@ static void commandTopic(uint id, char *params) {
|
||||||
|
|
||||||
static void commandNames(uint id, char *params) {
|
static void commandNames(uint id, char *params) {
|
||||||
(void)params;
|
(void)params;
|
||||||
ircFormat("NAMES :%s\r\n", idNames[id]);
|
ircFormat("NAMES %s\r\n", idNames[id]);
|
||||||
replies.names++;
|
replies.names++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,14 +162,12 @@ static void commandWhois(uint id, char *params) {
|
||||||
|
|
||||||
static void commandNS(uint id, char *params) {
|
static void commandNS(uint id, char *params) {
|
||||||
(void)id;
|
(void)id;
|
||||||
if (!params) return;
|
if (params) ircFormat("PRIVMSG NickServ :%s\r\n", params);
|
||||||
ircFormat("PRIVMSG NickServ :%s\r\n", params);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void commandCS(uint id, char *params) {
|
static void commandCS(uint id, char *params) {
|
||||||
(void)id;
|
(void)id;
|
||||||
if (!params) return;
|
if (params) ircFormat("PRIVMSG ChanServ :%s\r\n", params);
|
||||||
ircFormat("PRIVMSG ChanServ :%s\r\n", params);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void commandQuery(uint id, char *params) {
|
static void commandQuery(uint id, char *params) {
|
||||||
|
@ -330,36 +320,41 @@ const char *commandIsAction(uint id, const char *input) {
|
||||||
void command(uint id, char *input) {
|
void command(uint id, char *input) {
|
||||||
if (id == Debug && input[0] != '/') {
|
if (id == Debug && input[0] != '/') {
|
||||||
commandQuote(id, input);
|
commandQuote(id, input);
|
||||||
|
return;
|
||||||
} else if (commandIsPrivmsg(id, input)) {
|
} else if (commandIsPrivmsg(id, input)) {
|
||||||
commandPrivmsg(id, input);
|
commandPrivmsg(id, input);
|
||||||
|
return;
|
||||||
} else if (input[0] == '/' && isdigit(input[1])) {
|
} else if (input[0] == '/' && isdigit(input[1])) {
|
||||||
commandWindow(id, &input[1]);
|
commandWindow(id, &input[1]);
|
||||||
} else {
|
return;
|
||||||
const char *cmd = strsep(&input, " ");
|
|
||||||
const char *unique = complete(None, cmd);
|
|
||||||
if (unique && !complete(None, cmd)) {
|
|
||||||
cmd = unique;
|
|
||||||
completeReject();
|
|
||||||
}
|
|
||||||
const struct Handler *handler = bsearch(
|
|
||||||
cmd, Commands, ARRAY_LEN(Commands), sizeof(*handler), compar
|
|
||||||
);
|
|
||||||
if (self.restricted && handler && handler->restricted) {
|
|
||||||
handler = NULL;
|
|
||||||
}
|
|
||||||
if (handler) {
|
|
||||||
if (input) {
|
|
||||||
input += strspn(input, " ");
|
|
||||||
size_t len = strlen(input);
|
|
||||||
while (input[len - 1] == ' ') input[--len] = '\0';
|
|
||||||
if (!input[0]) input = NULL;
|
|
||||||
}
|
|
||||||
if (input && !input[0]) input = NULL;
|
|
||||||
handler->fn(id, input);
|
|
||||||
} else {
|
|
||||||
uiFormat(id, Hot, NULL, "No such command %s", cmd);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *cmd = strsep(&input, " ");
|
||||||
|
const char *unique = complete(None, cmd);
|
||||||
|
if (unique && !complete(None, cmd)) {
|
||||||
|
cmd = unique;
|
||||||
|
completeReject();
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct Handler *handler = bsearch(
|
||||||
|
cmd, Commands, ARRAY_LEN(Commands), sizeof(*handler), compar
|
||||||
|
);
|
||||||
|
if (!handler) {
|
||||||
|
uiFormat(id, Warm, NULL, "No such command %s", cmd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (self.restricted && handler->restricted) {
|
||||||
|
uiFormat(id, Warm, NULL, "Command %s is restricted", cmd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input) {
|
||||||
|
input += strspn(input, " ");
|
||||||
|
size_t len = strlen(input);
|
||||||
|
while (input[len - 1] == ' ') input[--len] = '\0';
|
||||||
|
if (!input[0]) input = NULL;
|
||||||
|
}
|
||||||
|
handler->fn(id, input);
|
||||||
}
|
}
|
||||||
|
|
||||||
void commandComplete(void) {
|
void commandComplete(void) {
|
||||||
|
|
11
complete.c
11
complete.c
|
@ -35,10 +35,10 @@ static struct Node *alloc(uint id, const char *str, enum Color color) {
|
||||||
if (!node) err(EX_OSERR, "malloc");
|
if (!node) err(EX_OSERR, "malloc");
|
||||||
node->id = id;
|
node->id = id;
|
||||||
node->str = strdup(str);
|
node->str = strdup(str);
|
||||||
if (!node->str) err(EX_OSERR, "strdup");
|
|
||||||
node->color = color;
|
node->color = color;
|
||||||
node->prev = NULL;
|
node->prev = NULL;
|
||||||
node->next = NULL;
|
node->next = NULL;
|
||||||
|
if (!node->str) err(EX_OSERR, "strdup");
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,7 +75,9 @@ static struct Node *append(struct Node *node) {
|
||||||
|
|
||||||
static struct Node *find(uint id, const char *str) {
|
static struct Node *find(uint id, const char *str) {
|
||||||
for (struct Node *node = head; node; node = node->next) {
|
for (struct Node *node = head; node; node = node->next) {
|
||||||
if (node->id == id && !strcmp(node->str, str)) return node;
|
if (node->id != id) continue;
|
||||||
|
if (strcmp(node->str, str)) continue;
|
||||||
|
return node;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -86,7 +88,7 @@ void completeAdd(uint id, const char *str, enum Color color) {
|
||||||
|
|
||||||
void completeTouch(uint id, const char *str, enum Color color) {
|
void completeTouch(uint id, const char *str, enum Color color) {
|
||||||
struct Node *node = find(id, str);
|
struct Node *node = find(id, str);
|
||||||
if (node && node->color != color) node->color = color;
|
if (node) node->color = color;
|
||||||
prepend(node ? detach(node) : alloc(id, str, color));
|
prepend(node ? detach(node) : alloc(id, str, color));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,11 +130,10 @@ void completeReplace(uint id, const char *old, const char *new) {
|
||||||
next = node->next;
|
next = node->next;
|
||||||
if (id && node->id != id) continue;
|
if (id && node->id != id) continue;
|
||||||
if (strcmp(node->str, old)) continue;
|
if (strcmp(node->str, old)) continue;
|
||||||
if (match == node) match = NULL;
|
|
||||||
free(node->str);
|
free(node->str);
|
||||||
node->str = strdup(new);
|
node->str = strdup(new);
|
||||||
if (!node->str) err(EX_OSERR, "strdup");
|
|
||||||
prepend(detach(node));
|
prepend(detach(node));
|
||||||
|
if (!node->str) err(EX_OSERR, "strdup");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
18
irc.c
18
irc.c
|
@ -157,15 +157,17 @@ int ircConnect(const char *bindHost, const char *host, const char *port) {
|
||||||
return sock;
|
return sock;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void debug(char dir, const char *line) {
|
enum { MessageCap = 8191 + 512 };
|
||||||
|
|
||||||
|
static void debug(const char *pre, const char *line) {
|
||||||
if (!self.debug) return;
|
if (!self.debug) return;
|
||||||
size_t len = strcspn(line, "\r\n");
|
size_t len = strcspn(line, "\r\n");
|
||||||
uiFormat(
|
uiFormat(
|
||||||
Debug, Cold, NULL, "\3%d%c%c\3\t%.*s",
|
Debug, Cold, NULL, "\3%02d%s\3\t%.*s",
|
||||||
Gray, dir, dir, (int)len, line
|
Gray, pre, (int)len, line
|
||||||
);
|
);
|
||||||
if (!isatty(STDERR_FILENO)) {
|
if (!isatty(STDERR_FILENO)) {
|
||||||
fprintf(stderr, "%c%c %.*s\n", dir, dir, (int)len, line);
|
fprintf(stderr, "%s %.*s\n", pre, (int)len, line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,13 +183,13 @@ void ircSend(const char *ptr, size_t len) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ircFormat(const char *format, ...) {
|
void ircFormat(const char *format, ...) {
|
||||||
char buf[1024];
|
char buf[MessageCap];
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start(ap, format);
|
va_start(ap, format);
|
||||||
int len = vsnprintf(buf, sizeof(buf), format, ap);
|
int len = vsnprintf(buf, sizeof(buf), format, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
assert((size_t)len < sizeof(buf));
|
assert((size_t)len < sizeof(buf));
|
||||||
debug('<', buf);
|
debug("<<", buf);
|
||||||
ircSend(buf, len);
|
ircSend(buf, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -249,7 +251,7 @@ static struct Message parse(char *line) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ircRecv(void) {
|
void ircRecv(void) {
|
||||||
static char buf[8191 + 512];
|
static char buf[MessageCap];
|
||||||
static size_t len = 0;
|
static size_t len = 0;
|
||||||
|
|
||||||
assert(client);
|
assert(client);
|
||||||
|
@ -265,7 +267,7 @@ void ircRecv(void) {
|
||||||
crlf = memmem(line, &buf[len] - line, "\r\n", 2);
|
crlf = memmem(line, &buf[len] - line, "\r\n", 2);
|
||||||
if (!crlf) break;
|
if (!crlf) break;
|
||||||
*crlf = '\0';
|
*crlf = '\0';
|
||||||
debug('>', line);
|
debug(">>", line);
|
||||||
handle(parse(line));
|
handle(parse(line));
|
||||||
line = crlf + 2;
|
line = crlf + 2;
|
||||||
}
|
}
|
||||||
|
|
4
ui.c
4
ui.c
|
@ -90,10 +90,10 @@ struct Window {
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
uint show;
|
|
||||||
uint swap;
|
|
||||||
struct Window *ptrs[IDCap];
|
struct Window *ptrs[IDCap];
|
||||||
uint len;
|
uint len;
|
||||||
|
uint show;
|
||||||
|
uint swap;
|
||||||
} windows;
|
} windows;
|
||||||
|
|
||||||
static uint windowPush(struct Window *window) {
|
static uint windowPush(struct Window *window) {
|
||||||
|
|
7
url.c
7
url.c
|
@ -17,6 +17,7 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <limits.h>
|
||||||
#include <regex.h>
|
#include <regex.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -142,8 +143,10 @@ static void urlCopy(const char *url) {
|
||||||
int error = pipe(rw);
|
int error = pipe(rw);
|
||||||
if (error) err(EX_OSERR, "pipe");
|
if (error) err(EX_OSERR, "pipe");
|
||||||
|
|
||||||
ssize_t len = write(rw[1], url, strlen(url));
|
size_t len = strlen(url);
|
||||||
if (len < 0) err(EX_IOERR, "write");
|
if (len > PIPE_BUF) len = PIPE_BUF;
|
||||||
|
ssize_t n = write(rw[1], url, len);
|
||||||
|
if (n < 0) err(EX_IOERR, "write");
|
||||||
|
|
||||||
error = close(rw[1]);
|
error = close(rw[1]);
|
||||||
if (error) err(EX_IOERR, "close");
|
if (error) err(EX_IOERR, "close");
|
||||||
|
|
Loading…
Reference in New Issue