]>
Commit | Line | Data |
---|---|---|
1 | ||
2 | #include <faim/aim.h> | |
3 | #include <signal.h> | |
4 | #include <sys/wait.h> | |
5 | #include "network.h" | |
6 | ||
7 | #define RUNNAME "aimdebugd" | |
8 | #define RUNPREFIX RUNNAME ": " | |
9 | ||
10 | typedef struct { | |
11 | struct aim_session_t sess; | |
12 | } client_t; | |
13 | ||
14 | int stayalive = 1; | |
15 | ||
16 | int clientready = 0; | |
17 | int scriptfd = -1; | |
18 | ||
19 | void sigchld(int signum) | |
20 | { | |
21 | pid_t pid; | |
22 | int status; | |
23 | ||
24 | pid = wait(&status); | |
25 | ||
26 | return; | |
27 | } | |
28 | ||
29 | int cb_login(struct aim_session_t *sess, struct command_rx_struct *command, ...) | |
30 | { | |
31 | return 1; | |
32 | } | |
33 | ||
34 | int incomingim(struct aim_session_t *sess, struct command_rx_struct *command, ...) | |
35 | { | |
36 | int channel; | |
37 | va_list ap; | |
38 | ||
39 | va_start(ap, command); | |
40 | channel = va_arg(ap, int); | |
41 | ||
42 | if (channel == 1) { | |
43 | char *sn = NULL; | |
44 | char *msg = NULL; | |
45 | u_int icbmflags = 0; | |
46 | u_short flag1, flag2; | |
47 | ||
48 | sn = va_arg(ap, char *); | |
49 | msg = va_arg(ap, char *); | |
50 | icbmflags = va_arg(ap, u_int); | |
51 | flag1 = va_arg(ap, u_short); | |
52 | flag2 = va_arg(ap, u_short); | |
53 | va_end(ap); | |
54 | ||
55 | printf("aimdebugd: client %d: %s/0x%04x/0x%02x/0x%02x/%s\n", | |
56 | getpid(), | |
57 | sn, | |
58 | icbmflags, flag1, | |
59 | flag2, msg); | |
60 | ||
61 | } else | |
62 | printf("aimdebugd: client %d: unsupported ICBM channel %d\n", getpid(), channel); | |
63 | ||
64 | return 1; | |
65 | } | |
66 | ||
67 | int debugconn_connect(struct aim_session_t *sess, struct command_rx_struct *command, ...) | |
68 | { | |
69 | struct aim_conn_t *scriptconn; | |
70 | ||
71 | clientready = 1; | |
72 | ||
73 | if (!(scriptconn = aim_newconn(sess, 0, NULL))) { | |
74 | printf(RUNPREFIX "unable to allocate script structures\n"); | |
75 | aim_logoff(sess); | |
76 | return 1; | |
77 | } | |
78 | scriptconn->fd = scriptfd; | |
79 | ||
80 | return 1; | |
81 | } | |
82 | ||
83 | int parsescriptline(struct aim_session_t *sess, struct aim_conn_t **conn); /* file.c */ | |
84 | ||
85 | int handlechild(int fd, char *scriptname) | |
86 | { | |
87 | int alive; | |
88 | int selstat; | |
89 | client_t client; | |
90 | struct aim_conn_t *inconn, *waitingconn; | |
91 | ||
92 | aim_session_init(&client.sess, 0); | |
93 | //client.sess.tx_enqueue = aim_tx_enqueue__immediate; | |
94 | ||
95 | if (!(inconn = aim_newconn(&client.sess, AIM_CONN_TYPE_BOS, NULL))) { | |
96 | printf(RUNPREFIX "unable to allocate client structures\n"); | |
97 | exit(-1); | |
98 | } | |
99 | inconn->fd = fd; | |
100 | ||
101 | if (scriptname) { | |
102 | if (scriptname[0] == '-') | |
103 | scriptfd = STDIN_FILENO; | |
104 | else if ((scriptfd = open(scriptname, O_RDONLY)) < 0) { | |
105 | perror(RUNPREFIX "open"); | |
106 | return -1; | |
107 | } | |
108 | } | |
109 | ||
110 | aim_conn_addhandler(&client.sess, inconn, 0x0000, 0x0001, cb_login, 0); | |
111 | aim_conn_addhandler(&client.sess, inconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_DEBUGCONN_CONNECT, debugconn_connect, 0); | |
112 | aim_conn_addhandler(&client.sess, inconn, 0x0004, 0x0006, incomingim, 0); | |
113 | ||
114 | aim_debugconn_sendconnect(&client.sess, inconn); | |
115 | ||
116 | alive = 1; | |
117 | while (alive) { | |
118 | waitingconn = aim_select(&client.sess, NULL, &selstat); | |
119 | ||
120 | switch(selstat) { | |
121 | case -1: /* error */ | |
122 | alive = 0; /* fall through and hit aim_logoff() */ | |
123 | break; | |
124 | case 0: /* nothing pending */ | |
125 | break; | |
126 | case 1: /* outgoing data pending */ | |
127 | aim_tx_flushqueue(&client.sess); | |
128 | break; | |
129 | case 2: /* incoming data pending */ | |
130 | if (waitingconn->fd == scriptfd) { | |
131 | if (clientready) { | |
132 | if (parsescriptline(&client.sess, &waitingconn) < 0) { | |
133 | alive = 0; | |
134 | } | |
135 | } | |
136 | } else { | |
137 | if (aim_get_command(&client.sess, waitingconn) < 0) { | |
138 | printf(RUNPREFIX "connection error\n"); | |
139 | alive = 0; /* fall through to aim_logoff() */ | |
140 | } else { | |
141 | aim_rxdispatch(&client.sess); | |
142 | } | |
143 | } | |
144 | break; | |
145 | default: /* invalid */ | |
146 | break; | |
147 | } | |
148 | } | |
149 | ||
150 | printf(RUNPREFIX "client disconnected\n"); | |
151 | ||
152 | close(fd); | |
153 | aim_logoff(&client.sess); | |
154 | ||
155 | return fd; | |
156 | } | |
157 | ||
158 | int main(int argc, char **argv) | |
159 | { | |
160 | int listener = -1; | |
161 | int client = -1; | |
162 | int n; | |
163 | char *scriptname = NULL; | |
164 | int nofork = 0; | |
165 | int runonce = 0, runsleft = 1; | |
166 | ||
167 | while ((n = getopt(argc, argv, "c:noh")) != EOF) { | |
168 | switch(n) { | |
169 | case 'c': | |
170 | scriptname = optarg; | |
171 | break; | |
172 | case 'n': /* don't fork */ | |
173 | nofork = 1; | |
174 | break; | |
175 | case 'o': /* run once only */ | |
176 | runonce = 1; | |
177 | break; | |
178 | usage: | |
179 | case 'h': | |
180 | printf("aimdebugd v0.10 -- Adam Fritzler (mid@auk.cx)\n"); | |
181 | printf("Usage:\n"); | |
182 | printf("\taimdebugd [-c file] [-n] [-o]\n"); | |
183 | printf("\t\t-c file\tScript file or - for stdin\n"); | |
184 | printf("\t\t-n\tDo not fork for each client, process serially\n"); | |
185 | printf("\t\t-o\tRun once and exit (required if script from stdin)\n"); | |
186 | printf("\n"); | |
187 | exit(2); | |
188 | } | |
189 | } | |
190 | ||
191 | if (scriptname && (scriptname[0] == '-') && (!nofork || !runonce)) { | |
192 | printf(RUNPREFIX "stdin script is not valid without -n and -o\n"); | |
193 | return -1; | |
194 | } | |
195 | ||
196 | printf(RUNPREFIX "starting\n"); | |
197 | ||
198 | signal(SIGCHLD, sigchld); | |
199 | ||
200 | if ((listener = establish(5190)) < 0) { | |
201 | perror(RUNPREFIX "establish"); | |
202 | exit(-1); | |
203 | } | |
204 | ||
205 | while (stayalive) { | |
206 | if (runonce && !runsleft) | |
207 | break; | |
208 | if ((client = get_connection(listener)) < 0) { | |
209 | perror(RUNPREFIX "get_connection"); | |
210 | stayalive = 0; | |
211 | } else { | |
212 | runsleft--; | |
213 | if (nofork) | |
214 | handlechild(client, scriptname); | |
215 | else { | |
216 | switch(fork()) { | |
217 | case -1: | |
218 | perror(RUNPREFIX "fork"); | |
219 | break; | |
220 | case 0: | |
221 | return handlechild(client, scriptname); | |
222 | break; | |
223 | default: | |
224 | close(client); /* let the child have it */ | |
225 | break; | |
226 | } | |
227 | } | |
228 | } | |
229 | } | |
230 | ||
231 | printf(RUNPREFIX "stopping\n"); | |
232 | return 0; | |
233 | } |