2 * Copyright (C) 2017 Andy Spencer <andy753421@gmail.com>
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
27 #include <sys/types.h>
45 static const char *proto_map[] = {
51 void strdcat(char *dst, const char *src, size_t n)
54 while (di < (n-1) && dst[di])
56 while (di < (n-1) && src[si]) {
58 dst[di++] = (si++,'_');
60 dst[di++] = src[si++];
65 static void init_logs()
71 wordexp(log_dir, &wexp, WRDE_NOCMD);
72 if (wexp.we_wordc > 1)
73 error("Found multiple log dirs: %s\n %s\n %s\n ...",
74 log_dir, wexp.we_wordv[0], wexp.we_wordv[1]);
75 strset(&log_dir, wexp.we_wordv[0]);
76 if (mkdir(log_dir, 0755) && (errno != EEXIST))
77 error("Failed to create log dir: %s", log_dir);
81 static void write_log(message_t *msg)
83 static char log_path[4096];
88 channel_t *chan = msg->channel;
89 server_t *srv = chan->server;
92 /* Create server directory */
93 strncpy(log_path, log_dir, sizeof(log_path));
94 strncat(log_path, "/", sizeof(log_path));
95 strdcat(log_path, srv->name, sizeof(log_path));
96 if (!mkdir(log_path, 0755)) {
97 debug("Failed to create server log dir\n");
101 /* Open log file directory */
102 strncat(log_path, "/", sizeof(log_path));
103 strdcat(log_path, chan->name, sizeof(log_path));
104 strncat(log_path, ".log", sizeof(log_path));
105 if (!(chan->log = fopen(log_path, "a+"))) {
106 debug("Cannot open log file: %s\n", log_path);
111 time_t timep = msg->when;
112 struct tm *tm = gmtime(&timep);
114 fprintf(chan->log, "(%04d-%02d-%02d %02d:%02d:%02d) %s%s %s\n",
115 tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
116 tm->tm_hour, tm->tm_min, tm->tm_sec,
117 msg->from ? msg->from->name : "***",
118 msg->from ? ":" : "",
126 messages = (message_t*)msg_buf.data;
134 void proto_config(const char *pname, const char *sname, const char *cname,
135 const char *group, const char *name,
136 const char *key, const char *value)
138 protocol_t proto = -1;
139 server_t *srv = NULL;
140 channel_t *chan = NULL;
142 for (srv = servers; srv; srv = srv->next)
143 if (match(sname, srv->name))
145 for (chan = channels; chan; chan = chan->next)
146 if (match(cname, chan->name))
149 if (pname) proto = get_map(pname, proto_map);
150 else if (srv) proto = srv->protocol;
151 else if (chan) proto = chan->server->protocol;
153 debug("chat_config: [%s-%s \"%s\"] %s = %s",
154 proto>=0 ? proto_map[proto] : "none",
155 group, name, key, value);
159 irc_config(srv, chan, group, name, key, value);
162 xmpp_config(srv, chan, group, name, key, value);
167 void chat_config(const char *group, const char *name, const char *key, const char *value)
169 if (match(group, "general")) {
170 if (match(key, "logdir"))
171 log_dir = strcopy(get_string(value));
173 if (match(group, "server")) {
176 else if (match(key, "protocol"))
177 proto_config(value, NULL, NULL, group, name, key, value);
179 proto_config(NULL, name, NULL, group, name, key, value);
181 if (match(group, "channel")) {
184 else if (match(key, "server"))
185 proto_config(NULL, value, NULL, group, name, key, value);
187 proto_config(NULL, NULL, name, group, name, key, value);
191 void chat_recv(channel_t *channel, user_t *from, const char *text)
193 append(&msg_buf, NULL, sizeof(message_t));
194 messages = (message_t*)msg_buf.data;
196 message_t *msg = &messages[history];
197 msg->channel = channel;
198 msg->when = time(NULL);
200 msg->text = strcopy(text);
207 void chat_complete(channel_t *channel, const char *text)
209 switch (channel->server->protocol) {
211 irc_complete(channel, text);
214 xmpp_complete(channel, text);
219 void chat_send(channel_t *channel, const char *text)
221 switch (channel->server->protocol) {
223 irc_send(channel, text);
226 xmpp_send(channel, text);
231 void chat_update(void)
241 for (int i = 0; i < history; i++)
242 free((void*)messages[i].text);
246 /* Server and channel function */
247 void add_server(server_t *server)
249 protocol_t proto = server->protocol;
250 debug("adding %s server \"%s\"", proto_map[proto], server->name);
251 server_t **last = &servers;
253 last = &(*last)->next;
257 void add_channel(channel_t *channel)
259 debug("adding %s channel \"%s\"", channel->server->name, channel->name);
260 channel_t **last = &channels;
262 last = &(*last)->next;
266 void add_user(user_t *user)
268 debug("adding %s user \"%s\"", user->server->name, user->name);
269 user_t **last = &users;
271 last = &(*last)->next;