Various small cleanups

Haven't really gone through ui.c yet.
master
C. McEnroe 2020-02-16 23:05:43 -05:00
parent ba524ed804
commit b20be7cbad
7 changed files with 125 additions and 123 deletions

38
chat.c
View File

@ -17,6 +17,7 @@
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <locale.h>
#include <poll.h>
#include <signal.h>
@ -39,7 +40,7 @@
static void genCert(const char *path) {
const char *name = strrchr(path, '/');
name = (name ? &name[1] : path);
char subj[256];
char subj[4 + NAME_MAX];
snprintf(subj, sizeof(subj), "/CN=%.*s", (int)strcspn(name, "."), name);
umask(0066);
execlp(
@ -56,13 +57,11 @@ char *idNames[IDCap] = {
[Debug] = "<debug>",
[Network] = "<network>",
};
enum Color idColors[IDCap] = {
[None] = Black,
[Debug] = Green,
[Network] = Gray,
};
uint idNext = Network + 1;
struct Network network;
@ -79,21 +78,9 @@ static void exitSave(void) {
uint32_t hashInit;
int utilPipe[2] = { -1, -1 };
uint execID;
int execPipe[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);
}
}
int utilPipe[2] = { -1, -1 };
static void execRead(void) {
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 void signalHandler(int signal) {
signals[signal] = 1;
@ -188,7 +188,7 @@ int main(int argc, char *argv[]) {
if (!user) user = nick;
if (!real) real = nick;
set(&network.name, host);
// Modes defined in RFC 1459:
set(&network.chanTypes, "#&");
set(&network.prefixes, "@+");
set(&network.prefixModes, "ov");
@ -196,6 +196,8 @@ int main(int argc, char *argv[]) {
set(&network.paramModes, "k");
set(&network.setParamModes, "l");
set(&network.channelModes, "imnpst");
set(&network.name, host);
set(&self.nick, "*");
commandComplete();

67
chat.h
View File

@ -65,8 +65,8 @@ static inline uint idFor(const char *name) {
if (id) return id;
if (idNext == IDCap) return Network;
idNames[idNext] = strdup(name);
if (!idNames[idNext]) err(EX_OSERR, "strdup");
idColors[idNext] = Default;
if (!idNames[idNext]) err(EX_OSERR, "strdup");
return idNext++;
}
@ -79,9 +79,22 @@ static inline enum Color hash(const char *str) {
hash ^= *str;
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 \
X("extended-join", CapExtendedJoin) \
X("invite-notify", CapInviteNotify) \
@ -96,25 +109,12 @@ enum Cap {
#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 {
bool debug;
bool restricted;
char *plain;
const char *join;
enum Cap caps;
char *plain;
char *join;
char *nick;
char *user;
enum Color color;
@ -155,25 +155,8 @@ void ircFormat(const char *format, ...)
__attribute__((format(printf, 1, 2)));
void ircClose(void);
extern struct Replies {
uint away;
uint join;
uint list;
uint names;
uint topic;
uint whois;
} replies;
uint execID;
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];
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 };
extern struct Util uiNotifyUtil;
void uiInit(void);

View File

@ -39,53 +39,45 @@ static void commandQuote(uint id, char *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;
ircFormat("PRIVMSG %s :%s\r\n", idNames[id], params);
ircFormat("%s %s :%s\r\n", cmd, idNames[id], params);
struct Message msg = {
.nick = self.nick,
.user = self.user,
.cmd = "PRIVMSG",
.cmd = cmd,
.params[0] = idNames[id],
.params[1] = params,
};
handle(msg);
}
static void commandPrivmsg(uint id, char *params) {
echoMessage("PRIVMSG", id, params);
}
static void commandNotice(uint id, char *params) {
if (!params || !params[0]) return;
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);
echoMessage("NOTICE", id, params);
}
static void commandMe(uint id, char *params) {
char buf[512];
snprintf(buf, sizeof(buf), "\1ACTION %s\1", (params ? params : ""));
commandPrivmsg(id, buf);
echoMessage("PRIVMSG", id, buf);
}
static void commandMsg(uint id, char *params) {
(void)id;
char *nick = strsep(&params, " ");
if (!params) return;
commandPrivmsg(idFor(nick), params);
id = idFor(strsep(&params, " "));
echoMessage("PRIVMSG", id, params);
}
static void commandJoin(uint id, char *params) {
if (!params) params = idNames[id];
uint count = 1;
if (params) {
for (char *ch = params; *ch && *ch != ' '; ++ch) {
if (*ch == ',') count++;
}
}
ircFormat("JOIN %s\r\n", (params ? params : idNames[id]));
ircFormat("JOIN %s\r\n", params);
replies.join += count;
replies.topic += count;
replies.names += count;
@ -101,7 +93,7 @@ static void commandPart(uint id, char *params) {
static void commandQuit(uint id, char *params) {
(void)id;
set(&self.quit, (params ? params : "Goodbye"));
set(&self.quit, (params ? params : "nyaa~"));
}
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) {
(void)params;
ircFormat("NAMES :%s\r\n", idNames[id]);
ircFormat("NAMES %s\r\n", idNames[id]);
replies.names++;
}
@ -170,14 +162,12 @@ static void commandWhois(uint id, char *params) {
static void commandNS(uint id, char *params) {
(void)id;
if (!params) return;
ircFormat("PRIVMSG NickServ :%s\r\n", params);
if (params) ircFormat("PRIVMSG NickServ :%s\r\n", params);
}
static void commandCS(uint id, char *params) {
(void)id;
if (!params) return;
ircFormat("PRIVMSG ChanServ :%s\r\n", params);
if (params) ircFormat("PRIVMSG ChanServ :%s\r\n", 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) {
if (id == Debug && input[0] != '/') {
commandQuote(id, input);
return;
} else if (commandIsPrivmsg(id, input)) {
commandPrivmsg(id, input);
return;
} else if (input[0] == '/' && isdigit(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) {
uiFormat(id, Warm, NULL, "No such command %s", cmd);
return;
}
if (handler) {
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;
}
if (input && !input[0]) input = NULL;
handler->fn(id, input);
} else {
uiFormat(id, Hot, NULL, "No such command %s", cmd);
}
}
}
void commandComplete(void) {

View File

@ -35,10 +35,10 @@ static struct Node *alloc(uint id, const char *str, enum Color color) {
if (!node) err(EX_OSERR, "malloc");
node->id = id;
node->str = strdup(str);
if (!node->str) err(EX_OSERR, "strdup");
node->color = color;
node->prev = NULL;
node->next = NULL;
if (!node->str) err(EX_OSERR, "strdup");
return node;
}
@ -75,7 +75,9 @@ static struct Node *append(struct Node *node) {
static struct Node *find(uint id, const char *str) {
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;
}
@ -86,7 +88,7 @@ void completeAdd(uint id, const char *str, enum Color color) {
void completeTouch(uint id, const char *str, enum Color color) {
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));
}
@ -128,11 +130,10 @@ void completeReplace(uint id, const char *old, const char *new) {
next = node->next;
if (id && node->id != id) continue;
if (strcmp(node->str, old)) continue;
if (match == node) match = NULL;
free(node->str);
node->str = strdup(new);
if (!node->str) err(EX_OSERR, "strdup");
prepend(detach(node));
if (!node->str) err(EX_OSERR, "strdup");
}
}

18
irc.c
View File

@ -157,15 +157,17 @@ int ircConnect(const char *bindHost, const char *host, const char *port) {
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;
size_t len = strcspn(line, "\r\n");
uiFormat(
Debug, Cold, NULL, "\3%d%c%c\3\t%.*s",
Gray, dir, dir, (int)len, line
Debug, Cold, NULL, "\3%02d%s\3\t%.*s",
Gray, pre, (int)len, line
);
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, ...) {
char buf[1024];
char buf[MessageCap];
va_list ap;
va_start(ap, format);
int len = vsnprintf(buf, sizeof(buf), format, ap);
va_end(ap);
assert((size_t)len < sizeof(buf));
debug('<', buf);
debug("<<", buf);
ircSend(buf, len);
}
@ -249,7 +251,7 @@ static struct Message parse(char *line) {
}
void ircRecv(void) {
static char buf[8191 + 512];
static char buf[MessageCap];
static size_t len = 0;
assert(client);
@ -265,7 +267,7 @@ void ircRecv(void) {
crlf = memmem(line, &buf[len] - line, "\r\n", 2);
if (!crlf) break;
*crlf = '\0';
debug('>', line);
debug(">>", line);
handle(parse(line));
line = crlf + 2;
}

4
ui.c
View File

@ -90,10 +90,10 @@ struct Window {
};
static struct {
uint show;
uint swap;
struct Window *ptrs[IDCap];
uint len;
uint show;
uint swap;
} windows;
static uint windowPush(struct Window *window) {

7
url.c
View File

@ -17,6 +17,7 @@
#include <assert.h>
#include <err.h>
#include <errno.h>
#include <limits.h>
#include <regex.h>
#include <stdio.h>
#include <stdlib.h>
@ -142,8 +143,10 @@ static void urlCopy(const char *url) {
int error = pipe(rw);
if (error) err(EX_OSERR, "pipe");
ssize_t len = write(rw[1], url, strlen(url));
if (len < 0) err(EX_IOERR, "write");
size_t len = strlen(url);
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]);
if (error) err(EX_IOERR, "close");