Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 608 lines (589 sloc) 14.744 kB
9f0cff1 Initial commit.
Sound and Fury authored
1 /*
15c709f Fixed bug with .quirc file and improved .quirc error handling
ec429 authored
2 quIRC - simple terminal-based IRC client
4e3364b @ec429 Nudge copyright year to 2013
authored
3 Copyright (C) 2010-13 Edward Cree
15c709f Fixed bug with .quirc file and improved .quirc error handling
ec429 authored
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
9f0cff1 Initial commit.
Sound and Fury authored
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
a439150 @ec429 More Makefile rework, using .d files for dependencies
authored
19 #include <stdio.h>
20 #include <string.h>
21 #include <unistd.h>
22 #include <sys/time.h>
23 #include <ctype.h>
24 #include <errno.h>
25 #include <signal.h>
26 #ifdef USE_MTRACE
27 #include <mcheck.h>
28 #endif // USE_MTRACE
29
30 #include "ttyraw.h"
31 #include "ttyesc.h"
32 #include "colour.h"
33 #include "irc.h"
34 #include "bits.h"
35 #include "buffer.h"
36 #include "config.h"
37 #include "input.h"
38 #include "version.h"
43a77f5 @rbryan Added all commands. Appears to be working.
rbryan authored
39 #include "cmd.h"
9f0cff1 Initial commit.
Sound and Fury authored
40
41 int main(int argc, char *argv[])
42 {
68d1b71 Use mcheck.h for memory profiling
Sound and Fury authored
43 #ifdef USE_MTRACE
44 mtrace();
45 #endif // USE_MTRACE
417d27e Handle SIGPIPE
Sound and Fury authored
46
2fc1d43 Push the start_buffer if we exit before transferring it
ec429 authored
47 bufs=NULL;
48
6518daf Made ttyesc stuff be terminfo based (other code still wants the #defi…
ec429 authored
49 setupterm((char *)0, fileno(stdout), (int *)0);
8a8c47f Fix some more problems associated with keymapping
ec429 authored
50 putp(keypad_xmit);
e184c8b Ring-buffer for debug messages. Complicated (see full message).
ec429 authored
51 init_ring(&s_buf);
7cb81a2 start_buffer, catches messages produced before bufs initialised
ec429 authored
52
417d27e Handle SIGPIPE
Sound and Fury authored
53 sigpipe=0;
b7319a8 Asynch name lookups
ec429 authored
54 sigwinch=0;
55 sigusr1=0;
ca84446 React to SIGWINCH (unless option 'winch' is set false)
ec429 authored
56 struct sigaction sa;
b7319a8 Asynch name lookups
ec429 authored
57 sa.sa_handler=handle_signals;
ca84446 React to SIGWINCH (unless option 'winch' is set false)
ec429 authored
58 sa.sa_flags=0;
59 sigemptyset(&sa.sa_mask);
7cb81a2 start_buffer, catches messages produced before bufs initialised
ec429 authored
60
61 if(sigaction(SIGPIPE, &sa, NULL)==-1)
62 {
63 fprintf(stderr, "Failed to set SIGPIPE handler\n");
64 perror("sigaction");
e184c8b Ring-buffer for debug messages. Complicated (see full message).
ec429 authored
65 push_ring(&s_buf, QUIET);
70de5f7 Use SGR0 to reset terminal attributes after running. Fixes: Issue 10
ec429 authored
66 termsgr0();
7cb81a2 start_buffer, catches messages produced before bufs initialised
ec429 authored
67 return(1);
68 }
ca84446 React to SIGWINCH (unless option 'winch' is set false)
ec429 authored
69 if(sigaction(SIGWINCH, &sa, NULL)==-1)
70 {
71 fprintf(stderr, "Failed to set SIGWINCH handler\n");
72 perror("sigaction");
e184c8b Ring-buffer for debug messages. Complicated (see full message).
ec429 authored
73 push_ring(&s_buf, QUIET);
70de5f7 Use SGR0 to reset terminal attributes after running. Fixes: Issue 10
ec429 authored
74 termsgr0();
ca84446 React to SIGWINCH (unless option 'winch' is set false)
ec429 authored
75 return(1);
76 }
b7319a8 Asynch name lookups
ec429 authored
77 if(sigaction(SIGUSR1, &sa, NULL)==-1)
78 {
79 fprintf(stderr, "Failed to set SIGUSR1 handler\n");
80 perror("sigaction");
e184c8b Ring-buffer for debug messages. Complicated (see full message).
ec429 authored
81 push_ring(&s_buf, QUIET);
70de5f7 Use SGR0 to reset terminal attributes after running. Fixes: Issue 10
ec429 authored
82 termsgr0();
b7319a8 Asynch name lookups
ec429 authored
83 return(1);
84 }
7cb81a2 start_buffer, catches messages produced before bufs initialised
ec429 authored
85
6518daf Made ttyesc stuff be terminfo based (other code still wants the #defi…
ec429 authored
86 int infc=fcntl(fileno(stdin), F_GETFD);
569371d Set stdin to non-blocking, 'just in case'
Sound and Fury authored
87 if(infc>=0)
88 {
6518daf Made ttyesc stuff be terminfo based (other code still wants the #defi…
ec429 authored
89 if(fcntl(fileno(stdin), F_SETFD, infc|O_NONBLOCK)==-1)
7cb81a2 start_buffer, catches messages produced before bufs initialised
ec429 authored
90 {
91 char *err=strerror(errno);
92 char msg[48+strlen(err)];
93 sprintf(msg, "Failed to mark stdin non-blocking: fcntl: %s", err);
e184c8b Ring-buffer for debug messages. Complicated (see full message).
ec429 authored
94 atr_failsafe(&s_buf, STA, msg, "init: ");
7cb81a2 start_buffer, catches messages produced before bufs initialised
ec429 authored
95 }
569371d Set stdin to non-blocking, 'just in case'
Sound and Fury authored
96 }
62617ff Configurable keymapping
ec429 authored
97 if(initkeys())
98 {
99 fprintf(stderr, "Failed to initialise keymapping\n");
e184c8b Ring-buffer for debug messages. Complicated (see full message).
ec429 authored
100 push_ring(&s_buf, QUIET);
70de5f7 Use SGR0 to reset terminal attributes after running. Fixes: Issue 10
ec429 authored
101 termsgr0();
62617ff Configurable keymapping
ec429 authored
102 return(1);
103 }
104 if(c_init()) // should be impossible
ac506d8 Generate the default colours from an awk script
Sound and Fury authored
105 {
7cb81a2 start_buffer, catches messages produced before bufs initialised
ec429 authored
106 fprintf(stderr, "Failed to initialise colours\n");
e184c8b Ring-buffer for debug messages. Complicated (see full message).
ec429 authored
107 push_ring(&s_buf, QUIET);
70de5f7 Use SGR0 to reset terminal attributes after running. Fixes: Issue 10
ec429 authored
108 termsgr0();
ac506d8 Generate the default colours from an awk script
Sound and Fury authored
109 return(1);
110 }
43a77f5 @rbryan Added all commands. Appears to be working.
rbryan authored
111 if(init_cmds())
112 {
113 fprintf(stderr, "Failed to initialise commands\n");
114 push_ring(&s_buf, QUIET);
115 termsgr0();
116 return(1);
117 }
29252b6 More refactoring; chopping up quirc.c. '#pragma once'-ing headers
Sound and Fury authored
118 if(def_config())
119 {
120 fprintf(stderr, "Failed to apply default configuration\n");
e184c8b Ring-buffer for debug messages. Complicated (see full message).
ec429 authored
121 push_ring(&s_buf, QUIET);
70de5f7 Use SGR0 to reset terminal attributes after running. Fixes: Issue 10
ec429 authored
122 termsgr0();
29252b6 More refactoring; chopping up quirc.c. '#pragma once'-ing headers
Sound and Fury authored
123 return(1);
124 }
7491561 Handles rc shadow file for eg. NickServ logins
Sound and Fury authored
125 resetcol();
46a229c Merge runs of joins/parts/quits into a single row (option 'merge')
ec429 authored
126 char *qmsg=strdup(fname);
da9052c Look for .quirc (and files generally) in $HOME
Sound and Fury authored
127 char *home=getenv("HOME");
b7554a7 Correctly handle missing ~/.quirc/ directory (or other chdir failure)
ec429 authored
128 bool haveqfld=true;
4881617 Moved rc from ~/.quirc to ~/.quirc/rc (cherrypicked from script branch)
ec429 authored
129 if(home)
130 {
131 char *qfld=malloc(strlen(home)+8);
132 if(qfld)
133 {
134 sprintf(qfld, "%s/.quirc", home);
ac2ac2c Backport fixes from openSUSE (pbleser)
ec429 authored
135 if(chdir(qfld))
136 {
b7554a7 Correctly handle missing ~/.quirc/ directory (or other chdir failure)
ec429 authored
137 char *err=strerror(errno);
138 char msg[48+strlen(err)+strlen(qfld)];
139 sprintf(msg, "Failed to change directory into %s: chdir: %s", qfld, err);
140 atr_failsafe(&s_buf, STA, msg, "init: ");
141 haveqfld=false;
ac2ac2c Backport fixes from openSUSE (pbleser)
ec429 authored
142 }
4881617 Moved rc from ~/.quirc to ~/.quirc/rc (cherrypicked from script branch)
ec429 authored
143 free(qfld);
144 }
145 else
146 {
147 perror("Failed to allocate space for 'qfld'");
e184c8b Ring-buffer for debug messages. Complicated (see full message).
ec429 authored
148 push_ring(&s_buf, QUIET);
70de5f7 Use SGR0 to reset terminal attributes after running. Fixes: Issue 10
ec429 authored
149 termsgr0();
4881617 Moved rc from ~/.quirc to ~/.quirc/rc (cherrypicked from script branch)
ec429 authored
150 return(1);
151 }
152 }
153 else
154 {
155 fprintf(stderr, "Environment variable $HOME not set! Exiting\n");
e184c8b Ring-buffer for debug messages. Complicated (see full message).
ec429 authored
156 push_ring(&s_buf, QUIET);
70de5f7 Use SGR0 to reset terminal attributes after running. Fixes: Issue 10
ec429 authored
157 termsgr0();
4881617 Moved rc from ~/.quirc to ~/.quirc/rc (cherrypicked from script branch)
ec429 authored
158 return(1);
159 }
b7554a7 Correctly handle missing ~/.quirc/ directory (or other chdir failure)
ec429 authored
160 FILE *rcfp=haveqfld?fopen("rc", "r"):NULL;
15c709f Fixed bug with .quirc file and improved .quirc error handling
ec429 authored
161 int rc_err=0;
709dc6b Various improvements eg rc file (.quirc)
Sound and Fury authored
162 if(rcfp)
163 {
15c709f Fixed bug with .quirc file and improved .quirc error handling
ec429 authored
164 rc_err=rcread(rcfp);
709dc6b Various improvements eg rc file (.quirc)
Sound and Fury authored
165 fclose(rcfp);
7cb81a2 start_buffer, catches messages produced before bufs initialised
ec429 authored
166 if(rc_err)
167 {
168 char msg[32];
4881617 Moved rc from ~/.quirc to ~/.quirc/rc (cherrypicked from script branch)
ec429 authored
169 sprintf(msg, "%d errors in ~/.quirc/rc", rc_err);
e184c8b Ring-buffer for debug messages. Complicated (see full message).
ec429 authored
170 atr_failsafe(&s_buf, STA, msg, "init: ");
7cb81a2 start_buffer, catches messages produced before bufs initialised
ec429 authored
171 }
172 }
173 else
174 {
e184c8b Ring-buffer for debug messages. Complicated (see full message).
ec429 authored
175 atr_failsafe(&s_buf, STA, "no config file found. Install one at ~/.quirc/rc", "init: ");
709dc6b Various improvements eg rc file (.quirc)
Sound and Fury authored
176 }
62617ff Configurable keymapping
ec429 authored
177 FILE *keyfp=fopen("keys", "r");
b7554a7 Correctly handle missing ~/.quirc/ directory (or other chdir failure)
ec429 authored
178 if(haveqfld&&keyfp)
62617ff Configurable keymapping
ec429 authored
179 {
180 loadkeys(keyfp);
181 fclose(keyfp);
182 }
29252b6 More refactoring; chopping up quirc.c. '#pragma once'-ing headers
Sound and Fury authored
183 signed int e=pargs(argc, argv);
fcf9495 Refactored .quirc and cmdline parsing; other refactoring
Sound and Fury authored
184 if(e>=0)
9f0cff1 Initial commit.
Sound and Fury authored
185 {
e184c8b Ring-buffer for debug messages. Complicated (see full message).
ec429 authored
186 push_ring(&s_buf, QUIET);
70de5f7 Use SGR0 to reset terminal attributes after running. Fixes: Issue 10
ec429 authored
187 termsgr0();
fcf9495 Refactored .quirc and cmdline parsing; other refactoring
Sound and Fury authored
188 return(e);
9f0cff1 Initial commit.
Sound and Fury authored
189 }
fcf9495 Refactored .quirc and cmdline parsing; other refactoring
Sound and Fury authored
190
de4ae60 config: generate much of the config code from a concise descriptions …
ec429 authored
191 conf_check();
192
28c2ab3 Fixed everything in buffer.c to use the new ttyesc functions
ec429 authored
193 if(ttyraw(fileno(stdout)))
9f0cff1 Initial commit.
Sound and Fury authored
194 {
e184c8b Ring-buffer for debug messages. Complicated (see full message).
ec429 authored
195 atr_failsafe(&s_buf, ERR, "Failed to set raw mode on tty: ttyraw:", "init: ");
196 atr_failsafe(&s_buf, ERR, strerror(errno), "init: ");
9f0cff1 Initial commit.
Sound and Fury authored
197 }
fcf9495 Refactored .quirc and cmdline parsing; other refactoring
Sound and Fury authored
198
3fcb080 Enable many warnings & fix them
ec429 authored
199 unsigned int i;
fcf9495 Refactored .quirc and cmdline parsing; other refactoring
Sound and Fury authored
200 for(i=0;i<height;i++) // push old stuff off the top of the screen, so it's preserved
201 printf("\n");
202
569371d Set stdin to non-blocking, 'just in case'
Sound and Fury authored
203 e=initialise_buffers(buflines);
29252b6 More refactoring; chopping up quirc.c. '#pragma once'-ing headers
Sound and Fury authored
204 if(e)
205 {
206 fprintf(stderr, "Failed to set up buffers\n");
e184c8b Ring-buffer for debug messages. Complicated (see full message).
ec429 authored
207 push_ring(&s_buf, QUIET);
70de5f7 Use SGR0 to reset terminal attributes after running. Fixes: Issue 10
ec429 authored
208 termsgr0();
29252b6 More refactoring; chopping up quirc.c. '#pragma once'-ing headers
Sound and Fury authored
209 return(1);
210 }
211
e184c8b Ring-buffer for debug messages. Complicated (see full message).
ec429 authored
212 push_ring(&s_buf, QUIET);
15c709f Fixed bug with .quirc file and improved .quirc error handling
ec429 authored
213
9f0cff1 Initial commit.
Sound and Fury authored
214 fd_set master, readfds;
215 FD_ZERO(&master);
6518daf Made ttyesc stuff be terminfo based (other code still wants the #defi…
ec429 authored
216 FD_SET(fileno(stdin), &master);
217 int fdmax=fileno(stdin);
1624b2a Text fixes (missing space) and make some messages QUIET
ec429 authored
218 if(!autoconnect(&master, &fdmax, servs))
30c1746 Implemented priorities (so quiet mode & debug are retroactive)
ec429 authored
219 add_to_buffer(0, STA, QUIET, 0, false, "Not connected - use /server to connect", "");
dbbd6c9 More work on the new input code
Sound and Fury authored
220 iline inp={{NULL, 0, 0}, {NULL, 0, 0}};
221 in_update(inp);
9f0cff1 Initial commit.
Sound and Fury authored
222 struct timeval timeout;
223 int state=0; // odd-numbered states are fatal
224 while(!(state%2))
225 {
ca84446 React to SIGWINCH (unless option 'winch' is set false)
ec429 authored
226 if(sigwinch)
227 {
228 if(winch)
229 {
e9d8e3b Try again to fix the SIGWINCH
ec429 authored
230 int l, c;
6518daf Made ttyesc stuff be terminfo based (other code still wants the #defi…
ec429 authored
231 if(termsize(fileno(stdin), &c, &l))
e9d8e3b Try again to fix the SIGWINCH
ec429 authored
232 {
30c1746 Implemented priorities (so quiet mode & debug are retroactive)
ec429 authored
233 add_to_buffer(0, ERR, NORMAL, 0, false, strerror(errno), "termsize: ioctl: ");
e9d8e3b Try again to fix the SIGWINCH
ec429 authored
234 }
235 else
236 {
ca84446 React to SIGWINCH (unless option 'winch' is set false)
ec429 authored
237 height=max(l, 5);
238 width=max(c, 30);
483c2cf Mark the bufs as dirty after a SIGWINCH
ec429 authored
239 for(int buf=0;buf<nbufs;buf++)
240 bufs[buf].dirty=true;
241 redraw_buffer();
e9d8e3b Try again to fix the SIGWINCH
ec429 authored
242 }
ca84446 React to SIGWINCH (unless option 'winch' is set false)
ec429 authored
243 }
244 sigwinch=0;
245 }
b7319a8 Asynch name lookups
ec429 authored
246 #if ASYNCH_NL
247 if(sigusr1)
248 {
ecc567b Further reworking of asynch NL
ec429 authored
249 sigusr1=0; // no race condition, because after this point we loop over the whole nl_list
250 int serverhandle;
251 nl_list *list=nl_active;
eebc9e0 Finally got the asynch nl working smoothly (it appears)
ec429 authored
252 while((list=nl_active)&&(serverhandle=irc_conn_found(&list, &master, &fdmax))&&list)
f68e45f Some more work on asynch nl
ec429 authored
253 {
ecc567b Further reworking of asynch NL
ec429 authored
254 const char *server=list->nl_details->ar_name;
255 if(!server) server="server";
256 const char *port=list->nl_details->ar_service;
257 if(!port) port="port";
258 char dstr[32+strlen(server)+strlen(port)];
259 sprintf(dstr, "Found %s, connecting on %s...", server, port);
22e3df7 @ec429 Remove obsolete 'force_redraw' option.
authored
260 redraw_buffer();
ecc567b Further reworking of asynch NL
ec429 authored
261 if(list->reconn_b)
c784a42 More work on asynch name lookups (reconnect handled)
ec429 authored
262 {
ecc567b Further reworking of asynch NL
ec429 authored
263 bufs[list->reconn_b].handle=serverhandle;
c784a42 More work on asynch name lookups (reconnect handled)
ec429 authored
264 int b2;
265 for(b2=1;b2<nbufs;b2++)
266 {
ecc567b Further reworking of asynch NL
ec429 authored
267 if(bufs[b2].server==list->reconn_b)
c784a42 More work on asynch name lookups (reconnect handled)
ec429 authored
268 bufs[b2].handle=serverhandle;
269 }
ecc567b Further reworking of asynch NL
ec429 authored
270 bufs[list->reconn_b].conninpr=true;
271 free(bufs[list->reconn_b].realsname);
272 bufs[list->reconn_b].realsname=NULL;
273 if(list->autoent)
274 bufs[list->reconn_b].autoent=list->autoent;
30c1746 Implemented priorities (so quiet mode & debug are retroactive)
ec429 authored
275 add_to_buffer(list->reconn_b, STA, QUIET, 0, false, dstr, "/server: ");
c784a42 More work on asynch name lookups (reconnect handled)
ec429 authored
276 }
ecc567b Further reworking of asynch NL
ec429 authored
277 else
c784a42 More work on asynch name lookups (reconnect handled)
ec429 authored
278 {
279 bufs=(buffer *)realloc(bufs, ++nbufs*sizeof(buffer));
280 init_buffer(nbufs-1, SERVER, server, buflines);
281 cbuf=nbufs-1;
282 bufs[cbuf].handle=serverhandle;
4a6824e @ec429 Fix issue (#18) with double-free(nick)
authored
283 bufs[cbuf].nick=bufs[0].nick?strdup(bufs[0].nick):NULL;
c784a42 More work on asynch name lookups (reconnect handled)
ec429 authored
284 bufs[cbuf].server=cbuf;
285 bufs[cbuf].conninpr=true;
ecc567b Further reworking of asynch NL
ec429 authored
286 if(list->autoent)
8953945 Fix autoconnect bugs (regression caused by the asynch nl)
ec429 authored
287 {
288 free(bufs[cbuf].nick);
289 bufs[cbuf].nick=strdup(list->autoent->nick);
c114bc8 Fix various memory access violations and double frees
ec429 authored
290 bufs[cbuf].ilist=n_dup(list->autoent->igns);
ecc567b Further reworking of asynch NL
ec429 authored
291 bufs[cbuf].autoent=list->autoent;
8953945 Fix autoconnect bugs (regression caused by the asynch nl)
ec429 authored
292 }
30c1746 Implemented priorities (so quiet mode & debug are retroactive)
ec429 authored
293 add_to_buffer(cbuf, STA, QUIET, 0, false, dstr, "/server: ");
c784a42 More work on asynch name lookups (reconnect handled)
ec429 authored
294 }
ecc567b Further reworking of asynch NL
ec429 authored
295 free((char *)list->nl_details->ar_name);
296 free((char *)list->nl_details->ar_service);
297 freeaddrinfo((void *)list->nl_details->ar_request);
f146cd2 @ec429 cleanup: fix some memory leaks. There's still something in getaddrin…
authored
298 free(list->nl_details);
ecc567b Further reworking of asynch NL
ec429 authored
299 if(list->prev) list->prev->next=list->next;
300 else nl_active=list->next;
301 if(list->next) list->next->prev=list->prev;
302 free(list);
b7319a8 Asynch name lookups
ec429 authored
303 }
304 }
305 #endif
1cd7a0e Ping idle connections to test liveness
Sound and Fury authored
306 // propagate liveness values into dependent tabs, and ping idle connections
1cd2840 Better handling of dropped-connection
Sound and Fury authored
307 {
1cd7a0e Ping idle connections to test liveness
Sound and Fury authored
308 time_t now=time(NULL);
1cd2840 Better handling of dropped-connection
Sound and Fury authored
309 int b;
310 for(b=0;b<nbufs;b++)
311 {
1cd7a0e Ping idle connections to test liveness
Sound and Fury authored
312 if(bufs[b].live)
313 {
314 if(bufs[b].type==SERVER)
315 {
3fcb080 Enable many warnings & fix them
ec429 authored
316 unsigned int idle=now-bufs[b].last;
1cd7a0e Ping idle connections to test liveness
Sound and Fury authored
317 if(tping && (idle>tping)) // a tping value of 0 means "don't ping"
318 {
319 if(bufs[b].ping)
320 {
321 bufs[b].live=false;
322 if(bufs[b].handle)
323 {
324 close(bufs[b].handle);
325 FD_CLR(bufs[b].handle, &master);
8bd79a8 Fix quit on select error (regression introduced by rev fbc2ee1)
ec429 authored
326 bufs[b].handle=0; // de-bind fd
30c1746 Implemented priorities (so quiet mode & debug are retroactive)
ec429 authored
327 add_to_buffer(b, ERR, NORMAL, 0, false, "Outbound ping timeout", "Disconnected: ");
1cd7a0e Ping idle connections to test liveness
Sound and Fury authored
328 }
329 bufs[b].alert=true;
330 bufs[b].hi_alert=5;
331 }
332 else
333 {
ba86cbe Fix bug with ping and realsname==NULL
ec429 authored
334 char pmsg[8+strlen(bufs[b].realsname?bufs[b].realsname:bufs[b].bname)];
335 sprintf(pmsg, "PING %s", bufs[b].realsname?bufs[b].realsname:bufs[b].bname);
1cd7a0e Ping idle connections to test liveness
Sound and Fury authored
336 irc_tx(bufs[b].handle, pmsg);
337 bufs[b].ping++;
338 }
339 bufs[b].last=now;
3c8779e Fixes involving --debug
Sound and Fury authored
340 in_update(inp);
1cd7a0e Ping idle connections to test liveness
Sound and Fury authored
341 }
342 }
343 else if(!bufs[bufs[b].server].live)
344 {
345 bufs[b].live=false;
fbc2ee1 de-bind fd when a tab goes dead; this should fix the 'read on a dead …
ec429 authored
346 bufs[b].handle=0; // just in case
30c1746 Implemented priorities (so quiet mode & debug are retroactive)
ec429 authored
347 add_to_buffer(b, ERR, NORMAL, 0, false, "Connection to server lost", "Disconnected: ");
1cd7a0e Ping idle connections to test liveness
Sound and Fury authored
348 }
349 }
1cd2840 Better handling of dropped-connection
Sound and Fury authored
350 }
351 }
7491561 Handles rc shadow file for eg. NickServ logins
Sound and Fury authored
352 timeout.tv_sec=0;
26fc4d5 Improve --force-redraw=3 handling
Sound and Fury authored
353 timeout.tv_usec=250000;
7491561 Handles rc shadow file for eg. NickServ logins
Sound and Fury authored
354
9f0cff1 Initial commit.
Sound and Fury authored
355 readfds=master;
356 if(select(fdmax+1, &readfds, NULL, NULL, &timeout)==-1)
357 {
017552f Quell the select() EINTR messages
ec429 authored
358 if(errno!=EINTR) // nobody cares if select() was interrupted by a signal
30c1746 Implemented priorities (so quiet mode & debug are retroactive)
ec429 authored
359 add_to_buffer(0, ERR, NORMAL, 0, false, strerror(errno), "select: ");
9f0cff1 Initial commit.
Sound and Fury authored
360 }
361 else
362 {
5a29c92 tab Hi-alerts (no triggers yet)
Sound and Fury authored
363 if(timeout.tv_usec==0) // flashing of hi-alert tabs
364 {
365 int b;
366 for(b=0;b<nbufs;b++)
367 {
368 switch(bufs[b].hi_alert%2)
369 {
370 case 1:
371 bufs[b].hi_alert=bufs[b].alert?4:bufs[b].hi_alert-1;
372 break;
373 case 0:
374 bufs[b].hi_alert=max(bufs[b].hi_alert-1, 0);
375 break;
376 }
377 }
d89a169 Fix bugs in hi-alerts
Sound and Fury authored
378 in_update(inp);
5a29c92 tab Hi-alerts (no triggers yet)
Sound and Fury authored
379 }
9f0cff1 Initial commit.
Sound and Fury authored
380 int fd;
381 for(fd=0;fd<=fdmax;fd++)
382 {
383 if(FD_ISSET(fd, &readfds))
384 {
6518daf Made ttyesc stuff be terminfo based (other code still wants the #defi…
ec429 authored
385 if(fd==fileno(stdin))
9f0cff1 Initial commit.
Sound and Fury authored
386 {
861788e More refactoring (input routines etc.)
Sound and Fury authored
387 inputchar(&inp, &state);
46a229c Merge runs of joins/parts/quits into a single row (option 'merge')
ec429 authored
388 /* XXX Possibly non-portable code; relies on edge-case behaviour */
5190d5c Use fflush(stdin) and ESPIPE to detect extra input (handles paste!)
Sound and Fury authored
389 bool loop=true;
390 while(loop && !state)
391 {
392 errno=0;
393 fflush(stdin);
394 if(errno==ESPIPE)
395 {
396 inputchar(&inp, &state); // ESPIPE only happens if there is data waiting to be read
397 }
398 else
399 {
400 loop=false;
401 }
402 }
de31114 @ec429 Some changes to input handling (prodding around a weird lockup bug)
authored
403 in_update(inp);
82c6f15 Part of the work on input line editing
Sound and Fury authored
404 break; // handle the input; everyone else can wait
9f0cff1 Initial commit.
Sound and Fury authored
405 }
a9c16e9 Things generally are now buffer-aware
Sound and Fury authored
406 else
9f0cff1 Initial commit.
Sound and Fury authored
407 {
a9c16e9 Things generally are now buffer-aware
Sound and Fury authored
408 int b;
409 for(b=0;b<nbufs;b++)
9f0cff1 Initial commit.
Sound and Fury authored
410 {
cc4fdc7 Main loop tweaks
Sound and Fury authored
411 if((fd==bufs[b].handle) && (bufs[b].type==SERVER))
9f0cff1 Initial commit.
Sound and Fury authored
412 {
5bd9397 Asynchronous connect(), fixes, and liveness (unfinished)
Sound and Fury authored
413 if(bufs[b].live)
9f0cff1 Initial commit.
Sound and Fury authored
414 {
5bd9397 Asynchronous connect(), fixes, and liveness (unfinished)
Sound and Fury authored
415 char *packet;
416 int e;
9c521e2 Fix irc_rx() infinite recv() loop
ec429 authored
417 if((e=irc_rx(fd, &packet, &master))!=0)
9f0cff1 Initial commit.
Sound and Fury authored
418 {
5bd9397 Asynchronous connect(), fixes, and liveness (unfinished)
Sound and Fury authored
419 char emsg[64];
01a8e84 Make delete key act as expected
Sound and Fury authored
420 sprintf(emsg, "irc_rx(%d, &%p): %d", fd, packet, e);
34c4be4 More liveness code
Sound and Fury authored
421 close(fd);
fbc2ee1 de-bind fd when a tab goes dead; this should fix the 'read on a dead …
ec429 authored
422 bufs[b].handle=0; // de-bind fd
34c4be4 More liveness code
Sound and Fury authored
423 FD_CLR(fd, &master);
424 bufs[b].live=false;
30c1746 Implemented priorities (so quiet mode & debug are retroactive)
ec429 authored
425 add_to_buffer(0, ERR, NORMAL, 0, false, emsg, "error: ");
34c4be4 More liveness code
Sound and Fury authored
426 redraw_buffer();
5bd9397 Asynchronous connect(), fixes, and liveness (unfinished)
Sound and Fury authored
427 }
428 else if(packet)
429 {
1cd7a0e Ping idle connections to test liveness
Sound and Fury authored
430 bufs[b].ping=0;
431 bufs[b].last=time(NULL);
61b2658 irc_breakdown() function, parses :prefix cmd args...
Sound and Fury authored
432 if(*packet)
c398280 Custom colours, tab completion of nicks
Sound and Fury authored
433 {
61b2658 irc_breakdown() function, parses :prefix cmd args...
Sound and Fury authored
434 message pkt=irc_breakdown(packet);
1cd7a0e Ping idle connections to test liveness
Sound and Fury authored
435 if(!bufs[b].realsname && pkt.prefix)
436 bufs[b].realsname=strdup(pkt.prefix);
7c3fe55 More work on parsing and protocol correctness etc.
Sound and Fury authored
437 if(isdigit(*pkt.cmd))
5bd9397 Asynchronous connect(), fixes, and liveness (unfinished)
Sound and Fury authored
438 {
7c3fe55 More work on parsing and protocol correctness etc.
Sound and Fury authored
439 irc_numeric(pkt, b);
5bd9397 Asynchronous connect(), fixes, and liveness (unfinished)
Sound and Fury authored
440 }
7c3fe55 More work on parsing and protocol correctness etc.
Sound and Fury authored
441 else if(strcmp(pkt.cmd, "PING")==0)
5bd9397 Asynchronous connect(), fixes, and liveness (unfinished)
Sound and Fury authored
442 {
3b9b287 Fix bug with rx_ping
Sound and Fury authored
443 rx_ping(pkt, b);
5bd9397 Asynchronous connect(), fixes, and liveness (unfinished)
Sound and Fury authored
444 }
4aff293 Handle RX PONG
Sound and Fury authored
445 else if(strcmp(pkt.cmd, "PONG")==0)
446 {
447 // ignore, as /anything/ resets the ping-timer
448 }
7c3fe55 More work on parsing and protocol correctness etc.
Sound and Fury authored
449 else if(strcmp(pkt.cmd, "MODE")==0)
5bd9397 Asynchronous connect(), fixes, and liveness (unfinished)
Sound and Fury authored
450 {
cdd4d11 Implemented MODEs, except that nick-prefixes are never displayed
ec429 authored
451 rx_mode(pkt, b);
5bd9397 Asynchronous connect(), fixes, and liveness (unfinished)
Sound and Fury authored
452 }
7c3fe55 More work on parsing and protocol correctness etc.
Sound and Fury authored
453 else if(strcmp(pkt.cmd, "KILL")==0)
5bd9397 Asynchronous connect(), fixes, and liveness (unfinished)
Sound and Fury authored
454 {
bf8886f Much more parsing work
Sound and Fury authored
455 rx_kill(pkt, b, &master);
5bd9397 Asynchronous connect(), fixes, and liveness (unfinished)
Sound and Fury authored
456 }
7c3fe55 More work on parsing and protocol correctness etc.
Sound and Fury authored
457 else if(strcmp(pkt.cmd, "KICK")==0)
95baa8f Recognise KICK messages
Sound and Fury authored
458 {
bf8886f Much more parsing work
Sound and Fury authored
459 rx_kick(pkt, b);
95baa8f Recognise KICK messages
Sound and Fury authored
460 }
7c3fe55 More work on parsing and protocol correctness etc.
Sound and Fury authored
461 else if(strcmp(pkt.cmd, "ERROR")==0)
5bd9397 Asynchronous connect(), fixes, and liveness (unfinished)
Sound and Fury authored
462 {
bf8886f Much more parsing work
Sound and Fury authored
463 rx_error(pkt, b, &master);
5bd9397 Asynchronous connect(), fixes, and liveness (unfinished)
Sound and Fury authored
464 }
7c3fe55 More work on parsing and protocol correctness etc.
Sound and Fury authored
465 else if(strcmp(pkt.cmd, "PRIVMSG")==0)
5bd9397 Asynchronous connect(), fixes, and liveness (unfinished)
Sound and Fury authored
466 {
bf8886f Much more parsing work
Sound and Fury authored
467 rx_privmsg(pkt, b, false);
5bd9397 Asynchronous connect(), fixes, and liveness (unfinished)
Sound and Fury authored
468 }
7c3fe55 More work on parsing and protocol correctness etc.
Sound and Fury authored
469 else if(strcmp(pkt.cmd, "NOTICE")==0)
5bd9397 Asynchronous connect(), fixes, and liveness (unfinished)
Sound and Fury authored
470 {
bf8886f Much more parsing work
Sound and Fury authored
471 rx_privmsg(pkt, b, true);
5bd9397 Asynchronous connect(), fixes, and liveness (unfinished)
Sound and Fury authored
472 }
7c3fe55 More work on parsing and protocol correctness etc.
Sound and Fury authored
473 else if(strcmp(pkt.cmd, "TOPIC")==0)
5bd9397 Asynchronous connect(), fixes, and liveness (unfinished)
Sound and Fury authored
474 {
bf8886f Much more parsing work
Sound and Fury authored
475 rx_topic(pkt, b);
5bd9397 Asynchronous connect(), fixes, and liveness (unfinished)
Sound and Fury authored
476 }
7c3fe55 More work on parsing and protocol correctness etc.
Sound and Fury authored
477 else if(strcmp(pkt.cmd, "JOIN")==0)
5bd9397 Asynchronous connect(), fixes, and liveness (unfinished)
Sound and Fury authored
478 {
bf8886f Much more parsing work
Sound and Fury authored
479 rx_join(pkt, b);
5bd9397 Asynchronous connect(), fixes, and liveness (unfinished)
Sound and Fury authored
480 }
7c3fe55 More work on parsing and protocol correctness etc.
Sound and Fury authored
481 else if(strcmp(pkt.cmd, "PART")==0)
5bd9397 Asynchronous connect(), fixes, and liveness (unfinished)
Sound and Fury authored
482 {
bf8886f Much more parsing work
Sound and Fury authored
483 rx_part(pkt, b);
5bd9397 Asynchronous connect(), fixes, and liveness (unfinished)
Sound and Fury authored
484 }
7c3fe55 More work on parsing and protocol correctness etc.
Sound and Fury authored
485 else if(strcmp(pkt.cmd, "QUIT")==0)
5bd9397 Asynchronous connect(), fixes, and liveness (unfinished)
Sound and Fury authored
486 {
bf8886f Much more parsing work
Sound and Fury authored
487 rx_quit(pkt, b);
5bd9397 Asynchronous connect(), fixes, and liveness (unfinished)
Sound and Fury authored
488 }
7c3fe55 More work on parsing and protocol correctness etc.
Sound and Fury authored
489 else if(strcmp(pkt.cmd, "NICK")==0)
5bd9397 Asynchronous connect(), fixes, and liveness (unfinished)
Sound and Fury authored
490 {
bf8886f Much more parsing work
Sound and Fury authored
491 rx_nick(pkt, b);
5bd9397 Asynchronous connect(), fixes, and liveness (unfinished)
Sound and Fury authored
492 }
493 else
494 {
6787aa2 Store nicks uncrushed, line types instead of colours.
ec429 authored
495 e_buf_print(b, UNK, pkt, "Unrecognised command: ");
5bd9397 Asynchronous connect(), fixes, and liveness (unfinished)
Sound and Fury authored
496 }
a173f22 Parsing revamp appears to be done; everything compiles again
Sound and Fury authored
497 message_free(pkt);
c398280 Custom colours, tab completion of nicks
Sound and Fury authored
498 }
90a2849 Fix crash bug (double-free packet)
Sound and Fury authored
499 else // if we called irc_breakdown, then that already free()d packet
500 {
501 free(packet);
502 }
9f0cff1 Initial commit.
Sound and Fury authored
503 }
5bd9397 Asynchronous connect(), fixes, and liveness (unfinished)
Sound and Fury authored
504 }
1cd2840 Better handling of dropped-connection
Sound and Fury authored
505 else if(bufs[b].conninpr)
5bd9397 Asynchronous connect(), fixes, and liveness (unfinished)
Sound and Fury authored
506 {
4a6824e @ec429 Fix issue (#18) with double-free(nick)
authored
507 irc_conn_rest(b, bufs[0].nick, username, pass, fname);
9f0cff1 Initial commit.
Sound and Fury authored
508 }
1cd2840 Better handling of dropped-connection
Sound and Fury authored
509 else
510 {
511 char emsg[32];
512 sprintf(emsg, "buf %d, fd %d", b, fd);
513 close(fd);
fbc2ee1 de-bind fd when a tab goes dead; this should fix the 'read on a dead …
ec429 authored
514 bufs[b].handle=0; // de-bind fd
1cd2840 Better handling of dropped-connection
Sound and Fury authored
515 FD_CLR(fd, &master);
516 bufs[b].live=false;
30c1746 Implemented priorities (so quiet mode & debug are retroactive)
ec429 authored
517 add_to_buffer(0, ERR, NORMAL, 0, false, emsg, "error: read on a dead tab: ");
1cd2840 Better handling of dropped-connection
Sound and Fury authored
518 redraw_buffer();
519 }
e3c326b Detects destinations of incoming data and directs them to their buf
Sound and Fury authored
520 in_update(inp);
a9c16e9 Things generally are now buffer-aware
Sound and Fury authored
521 b=nbufs+1;
9f0cff1 Initial commit.
Sound and Fury authored
522 }
523 }
a9c16e9 Things generally are now buffer-aware
Sound and Fury authored
524 if(b==nbufs)
525 {
34c4be4 More liveness code
Sound and Fury authored
526 char fmsg[48];
527 sprintf(fmsg, "select() returned data on unknown fd %d!", fd);
30c1746 Implemented priorities (so quiet mode & debug are retroactive)
ec429 authored
528 add_to_buffer(0, ERR, QUIET, 0, false, fmsg, "main loop:");
34c4be4 More liveness code
Sound and Fury authored
529 FD_CLR(fd, &master); // prevent it from happening again
a9c16e9 Things generally are now buffer-aware
Sound and Fury authored
530 }
9f0cff1 Initial commit.
Sound and Fury authored
531 }
532 }
533 }
534 }
535 switch(state)
536 {
ac1a527 Finished input editing
Sound and Fury authored
537 case 3:;
538 char *iptr=bufs[cbuf].input.line[(bufs[cbuf].input.ptr+bufs[cbuf].input.nlines-1)%bufs[cbuf].input.nlines];
539 if(!iptr)
9f0cff1 Initial commit.
Sound and Fury authored
540 {
ac1a527 Finished input editing
Sound and Fury authored
541 fprintf(stderr, "\nInternal error - state==3 and iptr is NULL!\n");
9f0cff1 Initial commit.
Sound and Fury authored
542 break;
543 }
ac1a527 Finished input editing
Sound and Fury authored
544 char *iinput=strdup(iptr);
dbbd6c9 More work on the new input code
Sound and Fury authored
545 if(iinput&&*iinput) // ignore empty lines, and ignore if iinput is NULL
9f0cff1 Initial commit.
Sound and Fury authored
546 {
a1caef4 Display tweaks
Sound and Fury authored
547 fflush(stdout);
dbbd6c9 More work on the new input code
Sound and Fury authored
548 char *deq=slash_dequote(iinput); // dequote
549 free(iinput);
550 iinput=deq;
551 if(*iinput=='/')
9f63fbf Send PRIVMSGs to channel
Sound and Fury authored
552 {
dbbd6c9 More work on the new input code
Sound and Fury authored
553 state=cmd_handle(iinput, &qmsg, &master, &fdmax);
9f63fbf Send PRIVMSGs to channel
Sound and Fury authored
554 }
555 else
556 {
d88f242 //text sends message /text (then /// sends //, etc.)
ec429 authored
557 talk(iinput);
a1caef4 Display tweaks
Sound and Fury authored
558 state=0;
9f63fbf Send PRIVMSGs to channel
Sound and Fury authored
559 }
d88f242 //text sends message /text (then /// sends //, etc.)
ec429 authored
560 free(iinput);iinput=NULL;
a1caef4 Display tweaks
Sound and Fury authored
561 }
562 else
563 {
9f0cff1 Initial commit.
Sound and Fury authored
564 state=0;
565 }
22e3df7 @ec429 Remove obsolete 'force_redraw' option.
authored
566 in_update(inp);
9f0cff1 Initial commit.
Sound and Fury authored
567 break;
568 }
569 }
a9c16e9 Things generally are now buffer-aware
Sound and Fury authored
570 int b;
3c8779e Fixes involving --debug
Sound and Fury authored
571 for(b=1;b<nbufs;b++)
9f0cff1 Initial commit.
Sound and Fury authored
572 {
f93e9e0 Fix bug with /quit interacting with debugger code
Sound and Fury authored
573 if((bufs[b].live) && (bufs[b].type==SERVER) && (bufs[b].handle!=0))
a9c16e9 Things generally are now buffer-aware
Sound and Fury authored
574 {
07c6f27 Adjust failover Quit-message
Sound and Fury authored
575 if(!qmsg) qmsg="quIRC Quit";
a9c16e9 Things generally are now buffer-aware
Sound and Fury authored
576 char quit[7+strlen(qmsg)];
577 sprintf(quit, "QUIT %s", qmsg);
1ad77fb MASSIVE changes to the code; we refer to buffers by index not pointer
Sound and Fury authored
578 irc_tx(bufs[b].handle, quit);
a9c16e9 Things generally are now buffer-aware
Sound and Fury authored
579 }
463b9ca Fix some memory leaks
Sound and Fury authored
580 bufs[b].live=false;
581 free_buffer(b);
582 b--;
9f0cff1 Initial commit.
Sound and Fury authored
583 }
3c8779e Fixes involving --debug
Sound and Fury authored
584 bufs[0].live=false;
585 free_buffer(0);
4b8ff78 De-if all the free()s
ec429 authored
586 free(bufs);
f146cd2 @ec429 cleanup: fix some memory leaks. There's still something in getaddrin…
authored
587 free_ring(&d_buf);
4b8ff78 De-if all the free()s
ec429 authored
588 free(username);
589 free(fname);
46a229c Merge runs of joins/parts/quits into a single row (option 'merge')
ec429 authored
590 free(qmsg);
4a6824e @ec429 Fix issue (#18) with double-free(nick)
authored
591 free(nick); // should be NULL by now anyway
4b8ff78 De-if all the free()s
ec429 authored
592 free(portno);
86c5674 Fix & improve the line editing
Sound and Fury authored
593 freeservlist(servs);
594 n_free(igns);
f146cd2 @ec429 cleanup: fix some memory leaks. There's still something in getaddrin…
authored
595 for(unsigned int i=0;i<nkeys;i++)
596 free(kmap[i].mod);
597 free(kmap);
598 free(version);
9186f24 Position the cursor correctly on quit
ec429 authored
599 locate(height-1, 0);
600 putchar('\n');
6518daf Made ttyesc stuff be terminfo based (other code still wants the #defi…
ec429 authored
601 ttyreset(fileno(stdout));
70de5f7 Use SGR0 to reset terminal attributes after running. Fixes: Issue 10
ec429 authored
602 termsgr0();
68d1b71 Use mcheck.h for memory profiling
Sound and Fury authored
603 #ifdef USE_MTRACE
604 muntrace();
605 #endif // USE_MTRACE
9f0cff1 Initial commit.
Sound and Fury authored
606 return(state>0?state:0);
607 }
Something went wrong with that request. Please try again.