Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

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