summaryrefslogtreecommitdiffstats
path: root/main/sircbot/disconnect-fix.patch
blob: 523264a632dc8e0503dc10e903e710053e738085 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
From 93d007481e25c9db88e8b16117b0378d51951bb6 Mon Sep 17 00:00:00 2001
From: Natanael Copa <ncopa@alpinelinux.org>
Date: Thu, 07 Mar 2013 15:20:22 +0000
Subject: fix segfault when IRC server does disconnect

and fix lots of whitespace damage
---
diff --git a/irc.c b/irc.c
index 92a925e..5832421 100644
--- a/irc.c
+++ b/irc.c
@@ -14,11 +14,11 @@ static int tcp_connect(const char *host, int port)
 	struct sockaddr_in addr;
 	struct hostent *h;
 	int sock = socket(AF_INET, SOCK_STREAM, 0);
-	if (sock < 0) 
+	if (sock < 0)
 		return sock;
 
 	h = gethostbyname(host);
-	if (h == NULL) 
+	if (h == NULL)
 		return -1;
 
 	memset(&addr, 0, sizeof(addr));
@@ -38,17 +38,17 @@ struct irc_session *irc_connect(const char* server, int port, const char *nick,
 {
 	char buf[256];
 	struct irc_session *sess;
-	
+
 	sess = malloc(sizeof(struct irc_session));
 	if (sess == NULL)
 		return NULL;
-		
+
 	sess->nick = nick;
 	sess->server = server;
 	sess->fd = tcp_connect(server, port);
-	if (sess->fd < 0) 
+	if (sess->fd < 0)
 		return NULL;
-		
+
 	/* login */
 	if (pass)
 		irc_send(sess, "PASS", pass);
@@ -79,7 +79,9 @@ int irc_send_ping(struct irc_session *s)
 
 int irc_close(struct irc_session *s, const char *msg)
 {
-	irc_send(s, "QUIT", msg ? msg : "");
-	close(s->fd);
+	if (s->fd > 0) {
+		irc_send(s, "QUIT", msg ? msg : "");
+		close(s->fd);
+	}
 	free(s);
 }
diff --git a/sircbot.c b/sircbot.c
index b85d7d0..7d9c1a3 100644
--- a/sircbot.c
+++ b/sircbot.c
@@ -56,8 +56,8 @@ struct sircbot_socket_callback {
 	int (*callback)(struct sircbot_session *sb, struct pollfd *fds,
 			void *ctx);
 };
-	
-	
+
+
 static int foreground = 0;
 static int sigterm = 0;
 static int flush_rate = 2;
@@ -90,7 +90,7 @@ int daemonize(const char *pidfile, const char *logfile)
 	/* exit parent */
 	if (pid > 0)
 		exit(0);
-	
+
 	/* detatch to controling terminal */
 	setsid();
 
@@ -220,10 +220,10 @@ int run_hooks(char *user, char *rcpt, char* data)
 		/* exit parent */
 		if (pid > 0)
 			exit(0);
-		
+
 		snprintf(dir, sizeof(dir), "/etc/" PROGNAME ".d/%s", rcpt);
 		printf("DEBUG: running scripts in %s\n", dir);
-		execlp("/bin/run-parts", "/bin/run-parts", "-a", user, 
+		execlp("/bin/run-parts", "/bin/run-parts", "-a", user,
 			   "-a", data, "-a", rcpt, dir, NULL);
 		log_err("run-parts");
 		exit(1);
@@ -302,17 +302,21 @@ int parse_irc_data(struct sircbot_session *sb, char *buf)
 }
 
 /* callback functions */
-static int irc_server_cb(struct sircbot_session *sb, struct pollfd *fds, 
+static int irc_server_cb(struct sircbot_session *sb, struct pollfd *fds,
 	void *ctx)
 {
 	char buf[4096];
 	int r;
 	struct irc_session *sess = (struct irc_session *) ctx;
 
-	if (fds->revents & POLLHUP) 
+	if (fds->revents & POLLHUP) {
 		/* server hang up on us */
+		printf("DEBUG: %s: connection closed\n", sess ? sess->server : "null");
+		close(sess->fd);
+		sess->fd = -1;
 		return 0;
-	
+	}
+
 	if (fds->revents & POLLERR) {
 		log_err(sess->server);
 		return -1;
@@ -340,7 +344,7 @@ int channel_extend_fd_array(struct sircbot_channel *chan)
 		chan->fd_array[i] = -1;
 	return 0;
 }
-	
+
 
 void channel_add_connection(struct sircbot_channel *chan, int fd)
 {
@@ -428,7 +432,7 @@ static int irc_reset_pollfds(struct sircbot_session *sb, struct pollfd *fds,
 	fds[n].fd = sb->sess->fd;
 	fds[n].events = POLLIN;
 	fds[n].revents = 0;
-	cb[n].context = NULL;
+	cb[n].context = sb->sess;
 	cb[n].callback = &irc_server_cb;
 	n++;
 
@@ -474,18 +478,24 @@ static int send_fifo_queue(struct irc_session *sess,
 	return r;
 }
 
-static void join_channels(struct sircbot_session *sb)
+static int join_channels(struct sircbot_session *sb)
 {
 	time_t now = time(NULL);
 	int i;
 	/* wait atleast 5 secs before we join a channel */
 	for (i = 0; i < sb->numchan; i++)
-		if ((now - sb->chan[i].last_closetime) > 5 
-		     && sb->chan[i].listen_fd < 0) {
+		if ((now - sb->chan[i].last_closetime) > 5
+		     && sb->chan[i].listen_fd < 0 && sb->sess != NULL) {
+			int r = 0;
 			printf("DEBUG: joining %s\n", sb->chan[i].name);
 			sb->chan[i].last_closetime = now;
-			irc_send(sb->sess, "JOIN", sb->chan[i].name);
+			r = irc_send(sb->sess, "JOIN", sb->chan[i].name);
+			if (r < 0) {
+				printf("DEBUG: error %s: %s\n", sb->sess->server, strerror(r));
+				return r;
+			}
 		}
+	return 0;
 }
 
 static int irc_loop(struct sircbot_session *sb)
@@ -504,7 +514,8 @@ static int irc_loop(struct sircbot_session *sb)
 	tv.tv_sec = 1;
 	tv.tv_nsec = 0;
 	while (!sigterm) {
-		join_channels(sb);
+		if (join_channels(sb) < 0)
+			goto ret_err;
 		n = irc_reset_pollfds(sb, fds, cbs, maxfds);
 		r = ppoll(fds, n, &tv, &sigmask);
 		if (r < 0) {
@@ -633,11 +644,11 @@ int main(int argc, char *argv[])
 			sleep(10);
 			continue;
 		}
-		
+
 		irc_loop(&sb);
 		irc_close(sb.sess, "bye");
 		/* reset channel sockets */
-		for (i = 0; i < argc; i++) 
+		for (i = 0; i < argc; i++)
 			close_channel_socket(&sb.chan[i], 0);
 		if (sigterm)
 			break;
--
cgit v0.9.0.3