|
1 /* |
|
2 * Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 |
|
18 // Include Files |
|
19 |
|
20 #include <stdlib.h> |
|
21 #include <stdio.h> |
|
22 #include <string.h> |
|
23 #include <math.h> |
|
24 #include <sys/select.h> |
|
25 #include <unistd.h> |
|
26 #include <sys/wait.h> |
|
27 #include <arpa/telnet.h> |
|
28 |
|
29 //For connect |
|
30 #include <sys/socket.h> |
|
31 #include <netinet/in.h> |
|
32 |
|
33 //For posix_spawn |
|
34 #include <spawn.h> |
|
35 |
|
36 //for pipe |
|
37 #include <fcntl.h> |
|
38 #include <sys/stat.h> |
|
39 #include <sys/param.h> |
|
40 |
|
41 //Symbian headers |
|
42 #include <e32std.h> |
|
43 #include <es_sock.h> |
|
44 #include <f32file.h> |
|
45 |
|
46 void add_return(char* source, char* dest); |
|
47 int startConnection(); |
|
48 TDriveNumber getSystemDrive(); |
|
49 |
|
50 int main(int argc, char *argv[], char **envp) |
|
51 { |
|
52 |
|
53 int net; |
|
54 int fds[3]; |
|
55 int pid; |
|
56 int ctl_sock; |
|
57 int on = 1; |
|
58 int replicate = 0; |
|
59 int ch = 1; |
|
60 |
|
61 char ayt_response[]={IAC,NOP}; |
|
62 |
|
63 socklen_t addrlen; |
|
64 |
|
65 int port = 23; |
|
66 |
|
67 sockaddr_in server_addr; |
|
68 sockaddr_in his_addr; |
|
69 |
|
70 const char *argstr = "RDP:"; |
|
71 |
|
72 while ((ch = getopt(argc, argv, argstr)) != -1) { |
|
73 switch (ch) { |
|
74 |
|
75 case 'D': |
|
76 |
|
77 for(int i=1 /*no name*/; i<argc; i++) |
|
78 { |
|
79 for(unsigned int j=0;j<strlen(argv[i]); j++) |
|
80 if(argv[i][j]=='D') |
|
81 { |
|
82 //Daemon token found, change it to allow replication to new background processes |
|
83 argv[i][j]='R'; |
|
84 } |
|
85 } |
|
86 posix_spawn(NULL,argv[0],NULL,NULL,argv,envp); |
|
87 exit(0); |
|
88 break; |
|
89 |
|
90 case 'R': |
|
91 replicate = 1; |
|
92 break; |
|
93 |
|
94 case 'P': |
|
95 port = atoi(optarg); |
|
96 break; |
|
97 |
|
98 default: |
|
99 printf("unknown flag -%c ignored", optopt); |
|
100 scanf(""); |
|
101 break; |
|
102 } |
|
103 } |
|
104 |
|
105 if(startConnection() != KErrNone) |
|
106 { |
|
107 exit(1); |
|
108 } |
|
109 |
|
110 ctl_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); |
|
111 |
|
112 if (ctl_sock < 0) |
|
113 { |
|
114 exit(1); |
|
115 } |
|
116 |
|
117 if (setsockopt(ctl_sock, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) |
|
118 { |
|
119 exit(1); |
|
120 } |
|
121 |
|
122 |
|
123 server_addr.sin_family = AF_INET; |
|
124 server_addr.sin_addr.s_addr = htonl(INADDR_ANY); |
|
125 server_addr.sin_port = htons(port); |
|
126 |
|
127 if (bind(ctl_sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) |
|
128 { |
|
129 exit(1); |
|
130 } |
|
131 |
|
132 if (listen(ctl_sock, 32) < 0) |
|
133 { |
|
134 exit(1); |
|
135 } |
|
136 |
|
137 addrlen = sizeof(his_addr); |
|
138 |
|
139 net = accept(ctl_sock, (struct sockaddr *)&his_addr, &addrlen); |
|
140 |
|
141 if(net<0) |
|
142 { |
|
143 exit(1); |
|
144 } |
|
145 |
|
146 close(ctl_sock); |
|
147 |
|
148 //replicate server |
|
149 if(replicate) |
|
150 posix_spawn(NULL,argv[0],NULL,NULL,argv,envp); |
|
151 |
|
152 //launch shell and redirect the commands... |
|
153 pid=popen3("zsh.exe", NULL, NULL, fds); |
|
154 |
|
155 |
|
156 if(pid>0) |
|
157 { |
|
158 |
|
159 char read_zsh[256]; |
|
160 char read_zsh_crlf[512]; |
|
161 int sock_cnt=0, zsh_cnt=0, ret; |
|
162 int max=0; |
|
163 fd_set read_fds; |
|
164 |
|
165 //create fifo pipe |
|
166 char pipeName[MAXPATHLEN]; |
|
167 sprintf(pipeName,"%c:\\telnetd_%d_pipe",getSystemDrive()+'A',getpid()); |
|
168 |
|
169 if (mkfifo(pipeName, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH) < 0) |
|
170 { |
|
171 exit(1); |
|
172 } |
|
173 |
|
174 int pipe = open(pipeName, O_RDONLY | O_NONBLOCK); |
|
175 |
|
176 |
|
177 max = fds[1] > fds[2] ? fds[1] : fds[2]; |
|
178 max = max > net ? max : net; |
|
179 max = max > pipe ? max : pipe; |
|
180 |
|
181 char exportVariable[MAXPATHLEN]; |
|
182 sprintf(exportVariable,"PIPE='%s'\n",pipeName); |
|
183 |
|
184 //read first prompt and write PIPE variable |
|
185 read(fds[1], read_zsh, 11); //"localhost# " |
|
186 write(fds[0], exportVariable, strlen(exportVariable)); |
|
187 |
|
188 for(;;) |
|
189 { |
|
190 int status=-1; |
|
191 |
|
192 FD_ZERO(&read_fds); |
|
193 FD_SET(net, &read_fds); |
|
194 FD_SET(fds[1], &read_fds); |
|
195 FD_SET(fds[2], &read_fds); |
|
196 FD_SET(pipe, &read_fds); |
|
197 |
|
198 //is child terminated... |
|
199 |
|
200 //Fix for defect to prevent the process from taking too much of the processor |
|
201 sleep(1); |
|
202 |
|
203 int wait_pid=waitpid(pid, &status, WNOHANG); |
|
204 if(pid == wait_pid || wait_pid == -1) //dont wait for the child to terminate |
|
205 { |
|
206 break; |
|
207 } |
|
208 |
|
209 //is any of the fds ready for read... |
|
210 ret=select(max+1, &read_fds, NULL, NULL, NULL); |
|
211 |
|
212 if(ret==-1) |
|
213 { |
|
214 break; |
|
215 } |
|
216 |
|
217 //is there any data to be written onto socket.. |
|
218 if(FD_ISSET(fds[1], &read_fds)) |
|
219 { |
|
220 memset(&read_zsh[0], 0, 256); |
|
221 |
|
222 zsh_cnt=read(fds[1], read_zsh, 255); |
|
223 if(zsh_cnt>0) |
|
224 { |
|
225 //reading from the socket can have more than one \n |
|
226 //so replace all \n with \r\n. |
|
227 add_return(read_zsh,read_zsh_crlf); |
|
228 write(net, read_zsh_crlf, strlen(read_zsh_crlf)); |
|
229 } |
|
230 } |
|
231 |
|
232 //is there any data to be written onto socket.. |
|
233 if (FD_ISSET(fds[2], &read_fds)) |
|
234 { |
|
235 memset(&read_zsh[0], 0, 256); |
|
236 |
|
237 zsh_cnt=read(fds[2], read_zsh, 255); |
|
238 if(zsh_cnt>0) |
|
239 { |
|
240 //reading from the socket can have more than one \n |
|
241 //so replace all \n with \r\n. |
|
242 add_return(read_zsh,read_zsh_crlf); |
|
243 write(net, read_zsh_crlf, strlen(read_zsh_crlf)); |
|
244 } |
|
245 } |
|
246 |
|
247 |
|
248 //is there any data to be written on to pipe |
|
249 if(FD_ISSET(net, &read_fds)) |
|
250 { |
|
251 //char* ptr=0; |
|
252 char temp,temp2; |
|
253 |
|
254 sock_cnt=0; |
|
255 |
|
256 sock_cnt=read(net, &temp, 1); |
|
257 if(sock_cnt > 0) |
|
258 { |
|
259 //echo the command.. |
|
260 //write(net, &temp, 1); |
|
261 |
|
262 switch(temp & 0xFF) |
|
263 { |
|
264 case '\r': |
|
265 sock_cnt=read(net, &temp, 1); //expect \n here... |
|
266 //write(net, &temp, 1); |
|
267 if(sock_cnt && !(write(fds[0], &temp, 1) > 0)) |
|
268 printf("1 telnetd: zsh is not waiting for data.\n"); |
|
269 break; |
|
270 |
|
271 case IAC: //telnet command |
|
272 { |
|
273 read(net, &temp2, 1); |
|
274 switch(temp2 & 0xFF) |
|
275 { |
|
276 case AYT: |
|
277 write(net,&ayt_response,2); |
|
278 break; |
|
279 } |
|
280 break; |
|
281 } |
|
282 |
|
283 default: |
|
284 if(!(write(fds[0], &temp, 1) > 0)) |
|
285 printf("2 telnetd: zsh is not waiting for data.\n"); |
|
286 } |
|
287 |
|
288 } |
|
289 } |
|
290 |
|
291 |
|
292 if(FD_ISSET(pipe, &read_fds)) |
|
293 { |
|
294 memset(&read_zsh[0], 0, 256); |
|
295 zsh_cnt=read(pipe, read_zsh, 255); |
|
296 |
|
297 if(zsh_cnt>0) |
|
298 { |
|
299 write(net, read_zsh, strlen(read_zsh)); |
|
300 } |
|
301 } |
|
302 |
|
303 |
|
304 } |
|
305 |
|
306 close(net); |
|
307 close(fds[0]); |
|
308 close(fds[1]); |
|
309 close(fds[2]); |
|
310 close(pipe); |
|
311 |
|
312 //delete pipe file |
|
313 unlink(pipeName); |
|
314 |
|
315 exit(0);//exit server here... |
|
316 |
|
317 |
|
318 |
|
319 } |
|
320 else |
|
321 { |
|
322 |
|
323 char errorMessage[]="\n\rShell (zsh.exe) not launched\n\r"; |
|
324 |
|
325 write(net, errorMessage, strlen(errorMessage)); |
|
326 sleep(5); |
|
327 exit(-1); //exit here |
|
328 } |
|
329 |
|
330 } |
|
331 |
|
332 |
|
333 void add_return(char* source, char* dest) |
|
334 { |
|
335 |
|
336 int sourceLen = strlen(source); |
|
337 int destIndex = 0; |
|
338 int sourceIndex = 0; |
|
339 |
|
340 for(; sourceIndex<sourceLen; sourceIndex++, destIndex++) |
|
341 { |
|
342 if(source[sourceIndex]=='\n') |
|
343 { |
|
344 dest[destIndex]='\r'; |
|
345 destIndex++; |
|
346 } |
|
347 dest[destIndex] = source[sourceIndex]; |
|
348 } |
|
349 |
|
350 dest[destIndex] = '\0'; |
|
351 |
|
352 } |
|
353 |
|
354 |
|
355 int startConnection() |
|
356 { |
|
357 |
|
358 int error; |
|
359 |
|
360 RSocketServ rSockServer; |
|
361 |
|
362 error = rSockServer.Connect(); |
|
363 |
|
364 if(error == KErrNone) |
|
365 { |
|
366 RConnection rConnect; |
|
367 error = rConnect.Open(rSockServer); |
|
368 if(error == KErrNone) |
|
369 { |
|
370 TRequestStatus status; |
|
371 rConnect.Start(status); |
|
372 User::WaitForRequest(status); |
|
373 } |
|
374 rConnect.Close(); |
|
375 } |
|
376 |
|
377 rSockServer.Close(); |
|
378 |
|
379 return error; |
|
380 |
|
381 } |
|
382 |
|
383 |
|
384 TDriveNumber getSystemDrive() |
|
385 { |
|
386 _LIT(KFileSrvDll, "efsrv.dll"); |
|
387 |
|
388 TDriveNumber defaultSysDrive(EDriveC); |
|
389 RLibrary pluginLibrary; |
|
390 TInt pluginErr = pluginLibrary.Load(KFileSrvDll); |
|
391 |
|
392 if (pluginErr == KErrNone) |
|
393 { |
|
394 typedef TDriveNumber(*fun1)(); |
|
395 fun1 sysdrive; |
|
396 |
|
397 #ifdef __EABI__ |
|
398 sysdrive = (fun1)pluginLibrary.Lookup(336); |
|
399 #else |
|
400 sysdrive = (fun1)pluginLibrary.Lookup(304); |
|
401 #endif |
|
402 |
|
403 if(sysdrive!=NULL) |
|
404 { |
|
405 defaultSysDrive = sysdrive(); |
|
406 } |
|
407 } |
|
408 pluginLibrary.Close(); |
|
409 return defaultSysDrive; |
|
410 } |
|
411 |
|
412 |
|
413 |