Rev 2892 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 2892 | Rev 2995 | ||
---|---|---|---|
1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
2 | ;; ;; |
2 | ;; ;; |
3 | ;; Copyright (C) KolibriOS team 2010-2012. All rights reserved. ;; |
3 | ;; Copyright (C) KolibriOS team 2010-2012. All rights reserved. ;; |
4 | ;; Distributed under terms of the GNU General Public License ;; |
4 | ;; Distributed under terms of the GNU General Public License ;; |
5 | ;; ;; |
5 | ;; ;; |
6 | ;; ftpd.asm - FTP Daemon for KolibriOS ;; |
6 | ;; ftpd.asm - FTP Daemon for KolibriOS ;; |
7 | ;; ;; |
7 | ;; ;; |
8 | ;; Written by hidnplayr@kolibrios.org ;; |
8 | ;; Written by hidnplayr@kolibrios.org ;; |
9 | ;; ;; |
9 | ;; ;; |
10 | ;; GNU GENERAL PUBLIC LICENSE ;; |
10 | ;; GNU GENERAL PUBLIC LICENSE ;; |
11 | ;; Version 2, June 1991 ;; |
11 | ;; Version 2, June 1991 ;; |
12 | ;; ;; |
12 | ;; ;; |
13 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
13 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
14 | 14 | ||
15 | DEBUG = 0 ; if set to one, program will run in a single thread |
15 | DEBUG = 0 ; if set to one, program will run in a single thread |
16 | 16 | ||
17 | BUFFERSIZE = 8192 |
17 | BUFFERSIZE = 8192 |
18 | 18 | ||
19 | ; using multiple's of 4 |
19 | ; using multiple's of 4 |
20 | STATE_CONNECTED = 0*4 |
20 | STATE_CONNECTED = 0*4 |
21 | STATE_LOGIN = 1*4 |
21 | STATE_LOGIN = 1*4 |
22 | STATE_LOGIN_FAIL = 2*4 ; When an invalid username was given |
22 | STATE_LOGIN_FAIL = 2*4 ; When an invalid username was given |
23 | STATE_ACTIVE = 3*4 |
23 | STATE_ACTIVE = 3*4 |
24 | 24 | ||
25 | TYPE_UNDEF = 0 |
25 | TYPE_UNDEF = 0 |
26 | 26 | ||
27 | TYPE_ASCII = 00000100b |
27 | TYPE_ASCII = 00000100b |
28 | TYPE_EBDIC = 00001000b |
28 | TYPE_EBDIC = 00001000b |
29 | ; subtypes for ascii & ebdic (np = default) |
29 | ; subtypes for ascii & ebdic (np = default) |
30 | TYPE_NP = 00000001b ; non printable |
30 | TYPE_NP = 00000001b ; non printable |
31 | TYPE_TELNET = 00000010b |
31 | TYPE_TELNET = 00000010b |
32 | TYPE_ASA = 00000011b |
32 | TYPE_ASA = 00000011b |
33 | 33 | ||
34 | TYPE_IMAGE = 01000000b ; binary data |
34 | TYPE_IMAGE = 01000000b ; binary data |
35 | TYPE_LOCAL = 10000000b ; bits per byte must be specified |
35 | TYPE_LOCAL = 10000000b ; bits per byte must be specified |
36 | ; lower 4 bits will hold this value |
36 | ; lower 4 bits will hold this value |
37 | MODE_NOTREADY = 0 |
37 | MODE_NOTREADY = 0 |
38 | MODE_ACTIVE = 1 |
38 | MODE_ACTIVE = 1 |
39 | MODE_PASSIVE_WAIT = 2 |
39 | MODE_PASSIVE_WAIT = 2 |
40 | MODE_PASSIVE_OK = 3 |
40 | MODE_PASSIVE_OK = 3 |
41 | MODE_PASSIVE_FAILED = 4 |
41 | MODE_PASSIVE_FAILED = 4 |
42 | 42 | ||
43 | PERMISSION_EXEC = 1b ; LIST |
43 | PERMISSION_EXEC = 1b ; LIST |
44 | PERMISSION_READ = 10b |
44 | PERMISSION_READ = 10b |
45 | PERMISSION_WRITE = 100b |
45 | PERMISSION_WRITE = 100b |
46 | PERMISSION_DELETE = 1000b |
46 | PERMISSION_DELETE = 1000b |
47 | PERMISSION_CD = 10000b ; Change Directory |
47 | PERMISSION_CD = 10000b ; Change Directory |
48 | 48 | ||
49 | ABORT = 1 shl 31 |
49 | ABORT = 1 shl 31 |
50 | 50 | ||
51 | format binary as "" |
51 | format binary as "" |
52 | 52 | ||
53 | use32 |
53 | use32 |
54 | db 'MENUET01' ; signature |
54 | db 'MENUET01' ; signature |
55 | dd 1 ; header version |
55 | dd 1 ; header version |
56 | dd start ; entry point |
56 | dd start ; entry point |
57 | dd i_end ; initialized size |
57 | dd i_end ; initialized size |
58 | dd mem+0x1000 ; required memory |
58 | dd mem+0x1000 ; required memory |
59 | dd mem+0x1000 ; stack pointer |
59 | dd mem+0x1000 ; stack pointer |
60 | dd params ; parameters |
60 | dd params ; parameters |
61 | dd path ; path |
61 | dd path ; path |
62 | 62 | ||
63 | include '../macros.inc' |
63 | include '../macros.inc' |
64 | purge mov,add,sub |
64 | purge mov,add,sub |
65 | include '../proc32.inc' |
65 | include '../proc32.inc' |
66 | include '../dll.inc' |
66 | include '../dll.inc' |
67 | include '../struct.inc' |
67 | include '../struct.inc' |
68 | include '../libio.inc' |
68 | include '../libio.inc' |
69 | 69 | ||
70 | include '../network.inc' |
70 | include '../network.inc' |
71 | 71 | ||
72 | macro sendFTP str { |
72 | macro sendFTP str { |
73 | local string, length |
73 | local string, length |
74 | xor edi, edi |
74 | xor edi, edi |
75 | mcall send, [ebp + thread_data.socketnum], string, length |
75 | mcall send, [ebp + thread_data.socketnum], string, length |
76 | 76 | ||
77 | iglobal |
77 | iglobal |
78 | string db str, 13, 10 |
78 | string db str, 13, 10 |
79 | length = $ - string |
79 | length = $ - string |
80 | \} |
80 | \} |
81 | } |
81 | } |
82 | 82 | ||
83 | include 'commands.inc' |
83 | include 'commands.inc' |
84 | 84 | ||
85 | start: |
85 | start: |
86 | mcall 68, 11 ; init heap |
86 | mcall 68, 11 ; init heap |
87 | mcall 40, 1 shl 7 ; we only want network events |
87 | mcall 40, 1 shl 7 ; we only want network events |
88 | 88 | ||
89 | ; load libraries |
89 | ; load libraries |
90 | stdcall dll.Load, @IMPORT |
90 | stdcall dll.Load, @IMPORT |
91 | test eax, eax |
91 | test eax, eax |
92 | jnz exit |
92 | jnz exit |
93 | 93 | ||
94 | ; find path to main settings file (ftpd.ini) |
94 | ; find path to main settings file (ftpd.ini) |
95 | mov edi, path ; Calculate the length of zero-terminated string |
95 | mov edi, path ; Calculate the length of zero-terminated string |
96 | xor al, al |
96 | xor al, al |
97 | mov ecx, 1024 |
97 | mov ecx, 1024 |
98 | repne scasb |
98 | repne scasb |
99 | dec edi |
99 | dec edi |
100 | mov esi, str_ini ; append it with '.ini', 0 |
100 | mov esi, str_ini ; append it with '.ini', 0 |
101 | movsd |
101 | movsd |
102 | movsb |
102 | movsb |
103 | 103 | ||
104 | ; now create the second path (users.ini) |
104 | ; now create the second path (users.ini) |
105 | std |
105 | std |
106 | mov al, '/' |
106 | mov al, '/' |
107 | repne scasb |
107 | repne scasb |
108 | lea ecx, [edi - path + 2] |
108 | lea ecx, [edi - path + 2] |
109 | cld |
109 | cld |
110 | mov esi, path |
110 | mov esi, path |
111 | mov edi, path2 |
111 | mov edi, path2 |
112 | rep movsb |
112 | rep movsb |
113 | mov esi, str_users |
113 | mov esi, str_users |
114 | movsd |
114 | movsd |
115 | movsd |
115 | movsd |
116 | movsw |
116 | movsw |
117 | 117 | ||
118 | ; initialize console |
118 | ; initialize console |
119 | invoke con_start, 1 |
119 | invoke con_start, 1 |
120 | invoke con_init, -1, -1, -1, -1, title |
120 | invoke con_init, -1, -1, -1, -1, title |
121 | 121 | ||
122 | invoke ini.get_str, path, str_ftpd, str_ip, ini_buf, 16, 0 |
122 | invoke ini.get_str, path, str_ftpd, str_ip, ini_buf, 16, 0 |
123 | mov esi, ini_buf |
123 | mov esi, ini_buf |
124 | mov cl, '.' |
124 | mov cl, '.' |
125 | call ip_to_dword |
125 | call ip_to_dword |
126 | mov [serverip], ebx |
126 | mov [serverip], ebx |
127 | 127 | ||
128 | invoke ini.get_int, path, str_ftpd, str_port, 21 |
128 | invoke ini.get_int, path, str_ftpd, str_port, 21 |
- | 129 | xchg al, ah |
|
129 | mov [sockaddr1.port], ax |
130 | mov [sockaddr1.port], ax |
- | 131 | ||
130 | 132 | xchg al, ah |
|
131 | invoke con_printf, str1, eax |
133 | invoke con_printf, str1, eax |
132 | add esp, 8 |
134 | add esp, 8 |
133 | 135 | ||
134 | mcall socket, AF_INET4, SOCK_STREAM, 0 |
136 | mcall socket, AF_INET4, SOCK_STREAM, 0 |
135 | cmp eax, -1 |
137 | cmp eax, -1 |
136 | je sock_err |
138 | je sock_err |
137 | mov [socketnum], eax |
139 | mov [socketnum], eax |
138 | 140 | ||
139 | invoke con_write_asciiz, str2 |
141 | invoke con_write_asciiz, str2 |
140 | 142 | ||
141 | ; mcall setsockopt, [socketnum], SOL_SOCKET, SO_REUSEADDR, &yes, |
143 | ; mcall setsockopt, [socketnum], SOL_SOCKET, SO_REUSEADDR, &yes, |
142 | ; cmp eax, -1 |
144 | ; cmp eax, -1 |
143 | ; je opt_err |
145 | ; je opt_err |
144 | 146 | ||
145 | mcall bind, [socketnum], sockaddr1, sockaddr1.length |
147 | mcall bind, [socketnum], sockaddr1, sockaddr1.length |
146 | cmp eax, -1 |
148 | cmp eax, -1 |
147 | je bind_err |
149 | je bind_err |
148 | 150 | ||
149 | invoke con_write_asciiz, str2 |
151 | invoke con_write_asciiz, str2 |
150 | 152 | ||
151 | invoke ini.get_int, path, str_ftpd, str_conn, 1 ; Backlog (max connections) |
153 | invoke ini.get_int, path, str_ftpd, str_conn, 1 ; Backlog (max connections) |
152 | mov edx, eax |
154 | mov edx, eax |
153 | 155 | ||
154 | invoke con_write_asciiz, str2 |
156 | invoke con_write_asciiz, str2 |
155 | 157 | ||
156 | mcall listen, [socketnum] |
158 | mcall listen, [socketnum] |
157 | cmp eax, -1 |
159 | cmp eax, -1 |
158 | je listen_err |
160 | je listen_err |
159 | 161 | ||
160 | invoke con_write_asciiz, str2b |
162 | invoke con_write_asciiz, str2b |
161 | 163 | ||
162 | invoke ini.get_int, path, str_pasv, str_start, 2000 |
164 | invoke ini.get_int, path, str_pasv, str_start, 2000 |
163 | mov [pasv_start], ax |
165 | mov [pasv_start], ax |
164 | invoke ini.get_int, path, str_pasv, str_end, 5000 |
166 | invoke ini.get_int, path, str_pasv, str_end, 5000 |
165 | mov [pasv_end], ax |
167 | mov [pasv_end], ax |
166 | 168 | ||
167 | mov [alive], 1 |
169 | mov [alive], 1 |
168 | 170 | ||
169 | mainloop: |
171 | mainloop: |
170 | mcall 23, 100 ; Wait here for incoming connections on the base socket (socketnum) |
172 | mcall 23, 100 ; Wait here for incoming connections on the base socket (socketnum) |
171 | ; One second timeout, we will use this to check if console is still working |
173 | ; One second timeout, we will use this to check if console is still working |
172 | 174 | ||
173 | test eax, eax ; network event? |
175 | test eax, eax ; network event? |
174 | jz .checkconsole |
176 | jz .checkconsole |
175 | 177 | ||
176 | if DEBUG |
178 | if DEBUG |
177 | jmp threadstart |
179 | jmp threadstart |
178 | else |
180 | else |
179 | mcall 51, 1, threadstart, 0 ; Start a new thread for every incoming connection |
181 | mcall 51, 1, threadstart, 0 ; Start a new thread for every incoming connection |
180 | ; NOTE: upon initialisation of the thread, stack will not be available! |
182 | ; NOTE: upon initialisation of the thread, stack will not be available! |
181 | end if |
183 | end if |
182 | jmp mainloop |
184 | jmp mainloop |
183 | 185 | ||
184 | .checkconsole: |
186 | .checkconsole: |
185 | 187 | ||
186 | invoke con_get_flags ; Is console still running? |
188 | invoke con_get_flags ; Is console still running? |
187 | test eax, 0x0200 |
189 | test eax, 0x0200 |
188 | jz mainloop |
190 | jz mainloop |
189 | mcall close, [socketnum] ; kill the listening socket |
191 | mcall close, [socketnum] ; kill the listening socket |
190 | mov [alive], 0 |
192 | mov [alive], 0 |
191 | mcall -1 ; and exit |
193 | mcall -1 ; and exit |
192 | 194 | ||
193 | diff16 "threadstart", 0, $ |
195 | diff16 "threadstart", 0, $ |
194 | 196 | ||
195 | threadstart: |
197 | threadstart: |
196 | ;;; mcall 68, 11 ; init heap |
198 | ;;; mcall 68, 11 ; init heap |
197 | mcall 68, 12, sizeof.thread_data ; allocate the thread data struct |
199 | mcall 68, 12, sizeof.thread_data ; allocate the thread data struct |
198 | test eax, eax |
200 | test eax, eax |
199 | je exit |
201 | je exit |
200 | 202 | ||
201 | lea esp, [eax + thread_data.stack] ; init stack |
203 | lea esp, [eax + thread_data.stack] ; init stack |
202 | mov ebp, eax |
204 | mov ebp, eax |
203 | 205 | ||
204 | mcall 40, 1 shl 7 ; we only want network events for this thread |
206 | mcall 40, 1 shl 7 ; we only want network events for this thread |
205 | 207 | ||
206 | lea ebx, [ebp + thread_data.buffer] ; get information about the current process |
208 | lea ebx, [ebp + thread_data.buffer] ; get information about the current process |
207 | or ecx, -1 |
209 | or ecx, -1 |
208 | mcall 9 |
210 | mcall 9 |
209 | mov eax, dword [ebp + thread_data.buffer + 30] ; PID is at offset 30 |
211 | mov eax, dword [ebp + thread_data.buffer + 30] ; PID is at offset 30 |
210 | mov [ebp + thread_data.pid], eax |
212 | mov [ebp + thread_data.pid], eax |
211 | 213 | ||
212 | invoke con_set_flags, 0x03 |
214 | invoke con_set_flags, 0x03 |
213 | invoke con_printf, str8, [ebp + thread_data.pid] ; print on the console that we have created the new thread successfully |
215 | invoke con_printf, str8, [ebp + thread_data.pid] ; print on the console that we have created the new thread successfully |
214 | add esp, 8 ; balance stack |
216 | add esp, 8 ; balance stack |
215 | invoke con_set_flags, 0x07 |
217 | invoke con_set_flags, 0x07 |
216 | 218 | ||
217 | mcall accept, [socketnum], sockaddr1, sockaddr1.length ; time to accept the awaiting connection.. |
219 | mcall accept, [socketnum], sockaddr1, sockaddr1.length ; time to accept the awaiting connection.. |
218 | cmp eax, -1 |
220 | cmp eax, -1 |
219 | je thread_exit |
221 | je thread_exit |
220 | mov [ebp + thread_data.socketnum], eax |
222 | mov [ebp + thread_data.socketnum], eax |
221 | 223 | ||
222 | if DEBUG |
224 | if DEBUG |
223 | mcall close, [socketnum] ; close the listening socket |
225 | mcall close, [socketnum] ; close the listening socket |
224 | end if |
226 | end if |
225 | 227 | ||
226 | mov [ebp + thread_data.state], STATE_CONNECTED |
228 | mov [ebp + thread_data.state], STATE_CONNECTED |
227 | mov [ebp + thread_data.permissions], 0 |
229 | mov [ebp + thread_data.permissions], 0 |
228 | mov [ebp + thread_data.mode], MODE_NOTREADY |
230 | mov [ebp + thread_data.mode], MODE_NOTREADY |
229 | lea eax, [ebp + thread_data.buffer] |
231 | lea eax, [ebp + thread_data.buffer] |
230 | mov [ebp + thread_data.buffer_ptr], eax |
232 | mov [ebp + thread_data.buffer_ptr], eax |
231 | mov [ebp + thread_data.passivesocknum], -1 |
233 | mov [ebp + thread_data.passivesocknum], -1 |
232 | 234 | ||
233 | sendFTP "220 Welcome to KolibriOS FTP daemon" |
235 | sendFTP "220 Welcome to KolibriOS FTP daemon" |
234 | 236 | ||
235 | diff16 "threadloop", 0, $ |
237 | diff16 "threadloop", 0, $ |
236 | threadloop: |
238 | threadloop: |
237 | ; Check if our socket is still connected |
239 | ; Check if our socket is still connected |
238 | mcall send, [ebp + thread_data.socketnum], 0, 0 ; Try to send zero bytes, if socket is closed, this will return -1 |
240 | mcall send, [ebp + thread_data.socketnum], 0, 0 ; Try to send zero bytes, if socket is closed, this will return -1 |
239 | cmp eax, -1 |
241 | cmp eax, -1 |
240 | je thread_exit |
242 | je thread_exit |
241 | 243 | ||
242 | cmp [alive], 0 ; Did main thread take a run for it? |
244 | cmp [alive], 0 ; Did main thread take a run for it? |
243 | je thread_exit |
245 | je thread_exit |
244 | 246 | ||
245 | mcall 10 ; Wait for network event |
247 | mcall 10 ; Wait for network event |
246 | 248 | ||
247 | cmp [ebp + thread_data.mode], MODE_PASSIVE_WAIT |
249 | cmp [ebp + thread_data.mode], MODE_PASSIVE_WAIT |
248 | jne .not_passive |
250 | jne .not_passive |
249 | mov ecx, [ebp + thread_data.passivesocknum] |
251 | mov ecx, [ebp + thread_data.passivesocknum] |
250 | lea edx, [ebp + thread_data.datasock] |
252 | lea edx, [ebp + thread_data.datasock] |
251 | mov esi, sizeof.thread_data.datasock |
253 | mov esi, sizeof.thread_data.datasock |
252 | mcall accept |
254 | mcall accept |
253 | cmp eax, -1 |
255 | cmp eax, -1 |
254 | je .not_passive |
256 | je .not_passive |
255 | mov [ebp + thread_data.datasocketnum], eax |
257 | mov [ebp + thread_data.datasocketnum], eax |
256 | mov [ebp + thread_data.mode], MODE_PASSIVE_OK |
258 | mov [ebp + thread_data.mode], MODE_PASSIVE_OK |
257 | mcall close ; [ebp + thread_data.passivesocknum] |
259 | mcall close ; [ebp + thread_data.passivesocknum] |
258 | mov [ebp + thread_data.passivesocknum], -1 |
260 | mov [ebp + thread_data.passivesocknum], -1 |
259 | 261 | ||
260 | invoke con_write_asciiz, str_datasock |
262 | invoke con_write_asciiz, str_datasock |
261 | .not_passive: |
263 | .not_passive: |
262 | 264 | ||
263 | mov ecx, [ebp + thread_data.socketnum] |
265 | mov ecx, [ebp + thread_data.socketnum] |
264 | mov edx, [ebp + thread_data.buffer_ptr] |
266 | mov edx, [ebp + thread_data.buffer_ptr] |
265 | mov esi, sizeof.thread_data.buffer ;;; FIXME |
267 | mov esi, sizeof.thread_data.buffer ;;; FIXME |
266 | mcall recv |
268 | mcall recv |
267 | inc eax ; error? (-1) |
269 | inc eax ; error? (-1) |
268 | jz threadloop |
270 | jz threadloop |
269 | dec eax ; 0 bytes read? |
271 | dec eax ; 0 bytes read? |
270 | jz threadloop |
272 | jz threadloop |
271 | 273 | ||
272 | mov edi, [ebp + thread_data.buffer_ptr] |
274 | mov edi, [ebp + thread_data.buffer_ptr] |
273 | add [ebp + thread_data.buffer_ptr], eax |
275 | add [ebp + thread_data.buffer_ptr], eax |
274 | 276 | ||
275 | ; Check if we received a newline character, if not, wait for more data |
277 | ; Check if we received a newline character, if not, wait for more data |
276 | mov ecx, eax |
278 | mov ecx, eax |
277 | mov al, 13 |
279 | mov al, 13 |
278 | repne scasb |
280 | repne scasb |
279 | jne threadloop |
281 | jne threadloop |
280 | 282 | ||
281 | ; We got a command! |
283 | ; We got a command! |
282 | mov byte [edi + 1], 0 ; append string with zero byte |
284 | mov byte [edi + 1], 0 ; append string with zero byte |
283 | lea esi, [ebp + thread_data.buffer] |
285 | lea esi, [ebp + thread_data.buffer] |
284 | mov ecx, [ebp + thread_data.buffer_ptr] |
286 | mov ecx, [ebp + thread_data.buffer_ptr] |
285 | sub ecx, esi |
287 | sub ecx, esi |
286 | mov [ebp + thread_data.buffer_ptr], esi ; reset buffer ptr |
288 | mov [ebp + thread_data.buffer_ptr], esi ; reset buffer ptr |
287 | 289 | ||
288 | invoke con_set_flags, 0x02 ; print received data to console (in green color) |
290 | invoke con_set_flags, 0x02 ; print received data to console (in green color) |
289 | invoke con_write_asciiz, str_newline |
291 | invoke con_write_asciiz, str_newline |
290 | invoke con_write_asciiz, esi |
292 | invoke con_write_asciiz, esi |
291 | invoke con_set_flags, 0x07 |
293 | invoke con_set_flags, 0x07 |
292 | 294 | ||
293 | push threadloop |
295 | push threadloop |
294 | jmp parse_cmd |
296 | jmp parse_cmd |
295 | 297 | ||
296 | listen_err: |
298 | listen_err: |
297 | invoke con_set_flags, 0x0c ; print errors in red |
299 | invoke con_set_flags, 0x0c ; print errors in red |
298 | invoke con_write_asciiz, str3 |
300 | invoke con_write_asciiz, str3 |
299 | jmp done |
301 | jmp done |
300 | 302 | ||
301 | bind_err: |
303 | bind_err: |
302 | invoke con_set_flags, 0x0c ; print errors in red |
304 | invoke con_set_flags, 0x0c ; print errors in red |
303 | invoke con_write_asciiz, str4 |
305 | invoke con_write_asciiz, str4 |
304 | jmp done |
306 | jmp done |
305 | 307 | ||
306 | sock_err: |
308 | sock_err: |
307 | invoke con_set_flags, 0x0c ; print errors in red |
309 | invoke con_set_flags, 0x0c ; print errors in red |
308 | invoke con_write_asciiz, str6 |
310 | invoke con_write_asciiz, str6 |
309 | jmp done |
311 | jmp done |
310 | 312 | ||
311 | done: |
313 | done: |
312 | invoke con_exit, 0 |
314 | invoke con_exit, 0 |
313 | exit: |
315 | exit: |
314 | mcall -1 |
316 | mcall -1 |
315 | 317 | ||
316 | 318 | ||
317 | thread_exit: |
319 | thread_exit: |
318 | invoke con_set_flags, 0x03 ; print thread info in blue |
320 | invoke con_set_flags, 0x03 ; print thread info in blue |
319 | invoke con_printf, str_bye, [ebp + thread_data.pid] ; print on the console that we are about to kill the thread |
321 | invoke con_printf, str_bye, [ebp + thread_data.pid] ; print on the console that we are about to kill the thread |
320 | add esp, 8 ; balance stack |
322 | add esp, 8 ; balance stack |
321 | mcall 68, 13, ebp ; free the memory |
323 | mcall 68, 13, ebp ; free the memory |
322 | mcall -1 ; and kill the thread |
324 | mcall -1 ; and kill the thread |
323 | 325 | ||
324 | 326 | ||
325 | ; initialized data |
327 | ; initialized data |
326 | 328 | ||
327 | title db 'KolibriOS FTP daemon 0.1', 0 |
329 | title db 'KolibriOS FTP daemon 0.1', 0 |
328 | str1 db 'Starting FTP daemon on port %u.', 0 |
330 | str1 db 'Starting FTP daemon on port %u.', 0 |
329 | str2 db '.', 0 |
331 | str2 db '.', 0 |
330 | str2b db ' OK!',10,0 |
332 | str2b db ' OK!',10,0 |
331 | str3 db 'Listen error',10,0 |
333 | str3 db 'Listen error',10,0 |
332 | str4 db 10,'ERROR: local port is already in use.',10,0 |
334 | str4 db 10,'ERROR: local port is already in use.',10,0 |
333 | ;str5 db 'Setsockopt error.',10,10,0 |
335 | ;str5 db 'Setsockopt error.',10,10,0 |
334 | str6 db 'ERROR: Could not open socket.',10,0 |
336 | str6 db 'ERROR: Could not open socket.',10,0 |
335 | str7 db 'Got data!',10,10,0 |
337 | str7 db 'Got data!',10,10,0 |
336 | str8 db 10,'Thread %d created',10,0 |
338 | str8 db 10,'Thread %d created',10,0 |
337 | str_bye db 10,'Thread %d killed',10,0 |
339 | str_bye db 10,'Thread %d killed',10,0 |
338 | 340 | ||
339 | str_logged_in db 'Login ok',10,0 |
341 | str_logged_in db 'Login ok',10,0 |
340 | str_pass_ok db 'Password ok',10,0 |
342 | str_pass_ok db 'Password ok',10,0 |
341 | str_pass_err db 'Password/Username incorrect',10,0 |
343 | str_pass_err db 'Password/Username incorrect',10,0 |
342 | str_pwd db 'Current directory is "%s"\n',0 |
344 | str_pwd db 'Current directory is "%s"\n',0 |
343 | str_err2 db 'ERROR: cannot open the directory.',10,0 |
345 | str_err2 db 'ERROR: cannot open the directory.',10,0 |
344 | str_datasock db 'Passive data socket connected.',10,0 |
346 | str_datasock db 'Passive data socket connected.',10,0 |
345 | str_notfound db 'ERROR: file not found.',10,0 |
347 | str_notfound db 'ERROR: file not found.',10,0 |
346 | str_sockerr db 'ERROR: socket error.',10,0 |
348 | str_sockerr db 'ERROR: socket error.',10,0 |
347 | 349 | ||
348 | str_newline db 10, 0 |
350 | str_newline db 10, 0 |
349 | str_mask db '*', 0 |
351 | str_mask db '*', 0 |
350 | str_infinity db 0xff, 0xff, 0xff, 0xff, 0 |
352 | str_infinity db 0xff, 0xff, 0xff, 0xff, 0 |
351 | 353 | ||
352 | months dd 'Jan ' |
354 | months dd 'Jan ' |
353 | dd 'Feb ' |
355 | dd 'Feb ' |
354 | dd 'Mar ' |
356 | dd 'Mar ' |
355 | dd 'Apr ' |
357 | dd 'Apr ' |
356 | dd 'May ' |
358 | dd 'May ' |
357 | dd 'Jun ' |
359 | dd 'Jun ' |
358 | dd 'Jul ' |
360 | dd 'Jul ' |
359 | dd 'Aug ' |
361 | dd 'Aug ' |
360 | dd 'Sep ' |
362 | dd 'Sep ' |
361 | dd 'Oct ' |
363 | dd 'Oct ' |
362 | dd 'Nov ' |
364 | dd 'Nov ' |
363 | dd 'Dec ' |
365 | dd 'Dec ' |
364 | 366 | ||
365 | str_users db 'users' |
367 | str_users db 'users' |
366 | str_ini db '.ini', 0 |
368 | str_ini db '.ini', 0 |
367 | str_port db 'port', 0 |
369 | str_port db 'port', 0 |
368 | str_ftpd db 'ftpd', 0 |
370 | str_ftpd db 'ftpd', 0 |
369 | str_conn db 'conn', 0 |
371 | str_conn db 'conn', 0 |
370 | str_ip db 'ip', 0 |
372 | str_ip db 'ip', 0 |
371 | str_pass db 'pass', 0 |
373 | str_pass db 'pass', 0 |
372 | str_home db 'home', 0 |
374 | str_home db 'home', 0 |
373 | str_mode db 'mode', 0 |
375 | str_mode db 'mode', 0 |
374 | str_pasv db 'pasv', 0 |
376 | str_pasv db 'pasv', 0 |
375 | str_start db 'start', 0 |
377 | str_start db 'start', 0 |
376 | str_end db 'end', 0 |
378 | str_end db 'end', 0 |
377 | 379 | ||
378 | 380 | ||
379 | sockaddr1: |
381 | sockaddr1: |
380 | dw AF_INET4 |
382 | dw AF_INET4 |
381 | .port dw 21 |
383 | .port dw 0 |
382 | .ip dd 0 |
384 | .ip dd 0 |
383 | rb 10 |
385 | rb 10 |
384 | .length = $ - sockaddr1 |
386 | .length = $ - sockaddr1 |
385 | 387 | ||
386 | ; import |
388 | ; import |
387 | 389 | ||
388 | align 4 |
390 | align 4 |
389 | @IMPORT: |
391 | @IMPORT: |
390 | 392 | ||
391 | diff16 "import", 0, $ |
393 | diff16 "import", 0, $ |
392 | 394 | ||
393 | library console, 'console.obj',\ |
395 | library console, 'console.obj',\ |
394 | libini, 'libini.obj', \ |
396 | libini, 'libini.obj', \ |
395 | libio, 'libio.obj' |
397 | libio, 'libio.obj' |
396 | 398 | ||
397 | import console,\ |
399 | import console,\ |
398 | con_start, 'START',\ |
400 | con_start, 'START',\ |
399 | con_init, 'con_init',\ |
401 | con_init, 'con_init',\ |
400 | con_write_asciiz, 'con_write_asciiz',\ |
402 | con_write_asciiz, 'con_write_asciiz',\ |
401 | con_exit, 'con_exit',\ |
403 | con_exit, 'con_exit',\ |
402 | con_gets, 'con_gets',\ |
404 | con_gets, 'con_gets',\ |
403 | con_cls, 'con_cls',\ |
405 | con_cls, 'con_cls',\ |
404 | con_printf, 'con_printf',\ |
406 | con_printf, 'con_printf',\ |
405 | con_getch2, 'con_getch2',\ |
407 | con_getch2, 'con_getch2',\ |
406 | con_set_cursor_pos, 'con_set_cursor_pos',\ |
408 | con_set_cursor_pos, 'con_set_cursor_pos',\ |
407 | con_set_flags, 'con_set_flags',\ |
409 | con_set_flags, 'con_set_flags',\ |
408 | con_get_flags, 'con_get_flags' |
410 | con_get_flags, 'con_get_flags' |
409 | 411 | ||
410 | import libini,\ |
412 | import libini,\ |
411 | ini.get_str, 'ini_get_str',\ |
413 | ini.get_str, 'ini_get_str',\ |
412 | ini.get_int, 'ini_get_int' |
414 | ini.get_int, 'ini_get_int' |
413 | 415 | ||
414 | import libio,\ |
416 | import libio,\ |
415 | file.size, 'file_size',\ |
417 | file.size, 'file_size',\ |
416 | file.open, 'file_open',\ |
418 | file.open, 'file_open',\ |
417 | file.read, 'file_read',\ |
419 | file.read, 'file_read',\ |
418 | file.close, 'file_close',\ |
420 | file.close, 'file_close',\ |
419 | file.find.first, 'file_find_first',\ |
421 | file.find.first, 'file_find_first',\ |
420 | file.find.next, 'file_find_next',\ |
422 | file.find.next, 'file_find_next',\ |
421 | file.find.close, 'file_find_close' |
423 | file.find.close, 'file_find_close' |
422 | 424 | ||
423 | 425 | ||
424 | IncludeIGlobals |
426 | IncludeIGlobals |
425 | 427 | ||
426 | 428 | ||
427 | i_end: |
429 | i_end: |
428 | 430 | ||
429 | diff16 "i_end", 0, $ |
431 | diff16 "i_end", 0, $ |
430 | 432 | ||
431 | ; uninitialised data |
433 | ; uninitialised data |
432 | 434 | ||
433 | socketnum dd ? |
435 | socketnum dd ? |
434 | path rb 1024 |
436 | path rb 1024 |
435 | path2 rb 1024 |
437 | path2 rb 1024 |
436 | params rb 1024 |
438 | params rb 1024 |
437 | serverip dd ? |
439 | serverip dd ? |
438 | pasv_start dw ? |
440 | pasv_start dw ? |
439 | pasv_end dw ? |
441 | pasv_end dw ? |
440 | pasv_port dw ? |
442 | pasv_port dw ? |
441 | 443 | ||
442 | ini_buf rb 3*4+3+1 |
444 | ini_buf rb 3*4+3+1 |
443 | 445 | ||
444 | alive db ? |
446 | alive db ? |
445 | 447 | ||
446 | mem: |
448 | mem: |