00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00077 #include <sys/version.h>
00078
00079 #include <sys/socket.h>
00080 #include <netinet/tcp.h>
00081
00082 #include <string.h>
00083 #include <stdio.h>
00084 #include <stdlib.h>
00085 #include <io.h>
00086 #include <fcntl.h>
00087 #include <sys/stat.h>
00088 #include <dirent.h>
00089 #include <unistd.h>
00090
00091 #include <pro/ftpd.h>
00092
00093 #ifdef FTPD_DEBUG
00094 #include <sys/heap.h>
00095 #endif
00096
00103
00110
00116 #ifndef FTP_ROOTPATH
00117 #define FTP_ROOTPATH "PNUT:"
00118 #endif
00119
00125 #ifndef FTP_DATA_PORT
00126 #define FTP_DATA_PORT 20
00127 #endif
00128
00131 static char *ftp_root;
00132 static char *ftp_user;
00133 static char *ftp_pass;
00134
00135
00136
00137
00138
00139 static prog_char cmd_cwd_P[] = "CWD";
00140 static prog_char cmd_dele_P[] = "DELE";
00141 static prog_char cmd_list_P[] = "LIST";
00142 static prog_char cmd_mkd_P[] = "MKD";
00143 static prog_char cmd_xmkd_P[] = "XMKD";
00144 static prog_char cmd_nlst_P[] = "NLST";
00145 static prog_char cmd_noop_P[] = "NOOP";
00146 static prog_char cmd_pass_P[] = "PASS";
00147 static prog_char cmd_pasv_P[] = "PASV";
00148 static prog_char cmd_port_P[] = "PORT";
00149 static prog_char cmd_pwd_P[] = "PWD";
00150 static prog_char cmd_xpwd_P[] = "XPWD";
00151 static prog_char cmd_quit_P[] = "QUIT";
00152 static prog_char cmd_retr_P[] = "RETR";
00153 static prog_char cmd_rmd_P[] = "RMD";
00154 static prog_char cmd_xrmd_P[] = "XRMD";
00155 static prog_char cmd_stor_P[] = "STOR";
00156 static prog_char cmd_syst_P[] = "SYST";
00157 static prog_char cmd_type_P[] = "TYPE";
00158 static prog_char cmd_user_P[] = "USER";
00159
00160 static char *mon_name = "JanFebMarAprMayJunJulAugSepOctNovDec";
00161
00162 static prog_char rep_banner[] = "220 Nut/OS FTP %s ready at %.3s%3d %02d:%02d:%02d\r\n";
00163
00176 static void SplitCmdArg(char * line, char ** cmd, char ** args)
00177 {
00178
00179 while (*line && *line <= ' ') {
00180 line++;
00181 }
00182
00183
00184 *cmd = line;
00185 while (*line > ' ') {
00186 if (*line >= (uint8_t) 'a' && *line <= (uint8_t) 'z') {
00187 *line -= (uint8_t) 'a' - 'A';
00188 }
00189 line++;
00190 }
00191
00192
00193 if (*line) {
00194 *line++ = '\0';
00195 }
00196
00197
00198 while (*line && *line <= ' ') {
00199 ++line;
00200 }
00201
00202
00203 *args = line;
00204 while (*line && *line != '\r' && *line != '\n') {
00205 line++;
00206 }
00207
00208
00209 *line = 0;
00210 }
00211
00227 static int ParseIpPort(CONST char * arg, uint32_t * ip, uint16_t * port)
00228 {
00229 int rc;
00230
00231 *ip = 0;
00232 *port = 0;
00233 for (rc = 0; rc < 6; rc++) {
00234 if (*arg < '0' || *arg > '9') {
00235 break;
00236 }
00237 if (rc < 4) {
00238 *ip >>= 8;
00239 *ip += atol(arg) << 24;
00240 } else {
00241 *port <<= 8;
00242 *port += atoi(arg);
00243 }
00244 while (*arg && *arg != ',') {
00245 arg++;
00246 }
00247 if (*arg == ',') {
00248 arg++;
00249 }
00250 }
00251 return rc;
00252 }
00253
00263 int NutFtpRespondOk(FTPSESSION * session, int code)
00264 {
00265 static prog_char fmt_P[] = "%d OK\r\n";
00266
00267 #ifdef FTPD_DEBUG
00268 printf("\n<'%d OK' ", code);
00269 #endif
00270 fprintf_P(session->ftp_stream, fmt_P, code);
00271 fflush(session->ftp_stream);
00272
00273 return 0;
00274 }
00275
00285 int NutFtpRespondBad(FTPSESSION * session, int code)
00286 {
00287 static prog_char fmt_P[] = "%d Failed\r\n";
00288
00289 #ifdef FTPD_DEBUG
00290 printf("\n<'%d Failed' ", code);
00291 #endif
00292 fprintf_P(session->ftp_stream, fmt_P, code);
00293 fflush(session->ftp_stream);
00294
00295 return 0;
00296 }
00297
00307 int NutFtpSendMode(FTPSESSION * session, int binary)
00308 {
00309 static prog_char intro_P[] = "150 Opening ";
00310 static prog_char amode_P[] = "ASCII.\r\n";
00311 static prog_char bmode_P[] = "BINARY.\r\n";
00312
00313 #ifdef FTPD_DEBUG
00314 printf("\n<'150 Opening %s' ", binary ? "BINARY" : "ASCII");
00315 #endif
00316 fputs_P(intro_P, session->ftp_stream);
00317 fputs_P(binary ? bmode_P : amode_P, session->ftp_stream);
00318 fflush(session->ftp_stream);
00319
00320 return 0;
00321 }
00322
00343 char *CreateFullPathName(char *root, char *work, char *path)
00344 {
00345 char *full;
00346 char *cp;
00347 size_t rl = root ? strlen(root) : 0;
00348 size_t wl = work ? strlen(work) : 0;
00349 size_t pl = path ? strlen(path) : 0;
00350
00351
00352 if (rl && *(root + rl - 1) == '/') {
00353 rl--;
00354 }
00355 if (wl && *(work + wl - 1) == '/') {
00356 wl--;
00357 }
00358
00359 if ((full = malloc(rl + wl + pl + 3)) != NULL) {
00360
00361 cp = full;
00362 if (rl) {
00363 cp = strcpy(full, root) + rl;
00364 }
00365
00366
00367 if(pl == 0 || *path != '/') {
00368 if (wl) {
00369 if (*work != '/') {
00370 *cp++ = '/';
00371 }
00372 cp = strcpy(cp, work) + wl;
00373 }
00374 *cp++ = '/';
00375 rl++;
00376 }
00377
00378 if (pl) {
00379 *cp = 0;
00380 work = full + rl;
00381
00382 while (*path) {
00383
00384 if (*path == '/') {
00385 *cp++ = *path++;
00386 while (*path == '/') {
00387 path++;
00388 }
00389 }
00390
00391 if (*path == '.') {
00392 path++;
00393 if (*path == '/') {
00394 path++;
00395 continue;
00396 }
00397 if (*path == 0) {
00398 break;
00399 }
00400 if (*path == '.') {
00401 path++;
00402 if (*path == '/' || *path == 0) {
00403 if (cp != work) {
00404 cp--;
00405 while (cp != work) {
00406 cp--;
00407 if (*cp == '/') {
00408 break;
00409 }
00410 }
00411 }
00412 continue;
00413 }
00414 path--;
00415 }
00416 path--;
00417 }
00418
00419 while (*path && *path != '/') {
00420 *cp++ = *path++;
00421 }
00422 }
00423 }
00424 *cp = 0;
00425 }
00426 return full;
00427 }
00428
00438 TCPSOCKET *NutFtpDataConnect(FTPSESSION * session)
00439 {
00440 TCPSOCKET *sock;
00441 int rc;
00442
00443 if ((sock = NutTcpCreateSocket()) != 0) {
00444
00445 if (session->ftp_maxseg) {
00446 NutTcpSetSockOpt(sock, TCP_MAXSEG, &session->ftp_maxseg, sizeof(session->ftp_maxseg));
00447 }
00448 if (session->ftp_passive) {
00449 rc = NutTcpAccept(sock, session->ftp_data_port);
00450 } else {
00451 rc = NutTcpConnect(sock, session->ftp_data_ip, session->ftp_data_port);
00452 }
00453 if (rc) {
00454 NutTcpCloseSocket(sock);
00455 sock = 0;
00456 }
00457 }
00458 return sock;
00459 }
00460
00474 int NutRegisterFtpRoot(CONST char *path)
00475 {
00476
00477 if (path == NULL || *path == 0) {
00478
00479 if (ftp_root) {
00480 free(ftp_root);
00481 }
00482 if ((ftp_root = malloc(sizeof(FTP_ROOTPATH))) == 0) {
00483 return -1;
00484 }
00485 strcpy(ftp_root, FTP_ROOTPATH);
00486 }
00487
00488
00489 else {
00490 char *cp = strchr(path, ':');
00491 int len = strlen(path);
00492
00493
00494 if (len < 2 || cp == 0 || (*++cp && *cp != '/')) {
00495 return -1;
00496 }
00497
00498
00499 if ((cp = malloc(len + 1)) == 0) {
00500 return -1;
00501 }
00502
00503
00504 strcpy(cp, path);
00505 if (ftp_root) {
00506 free(ftp_root);
00507 }
00508 ftp_root = cp;
00509
00510
00511 cp = cp + strlen(cp) - 1;
00512 if (*cp == '/') {
00513 *cp = 0;
00514 }
00515 }
00516 return 0;
00517 }
00518
00534 int NutRegisterFtpUser(CONST char *user, CONST char *pass)
00535 {
00536 if (ftp_user) {
00537 free(ftp_user);
00538 ftp_user = 0;
00539 }
00540 if (user && *user) {
00541 if ((ftp_user = malloc(strlen(user) + 1)) == 0) {
00542 return -1;
00543 }
00544 strcpy(ftp_user, user);
00545 }
00546 if (ftp_pass) {
00547 free(ftp_pass);
00548 ftp_pass = 0;
00549 }
00550 if (pass && *pass) {
00551 if ((ftp_pass = malloc(strlen(pass) + 1)) == 0) {
00552 return -1;
00553 }
00554 strcpy(ftp_pass, pass);
00555 }
00556 return 0;
00557 }
00558
00559
00569 FTPSESSION *NutFtpOpenSession(TCPSOCKET * sock)
00570 {
00571 FTPSESSION *session;
00572
00573 session = malloc(sizeof(FTPSESSION));
00574
00575 if (session) {
00576 memset(session, 0, sizeof(FTPSESSION));
00577 session->ftp_data_port = FTP_DATA_PORT;
00578 session->ftp_maxseg = sock->so_mss;
00579 session->ftp_sock = sock;
00580
00581
00582 if ((session->ftp_cwd = malloc(2)) == 0) {
00583 free(session);
00584 session = 0;
00585 } else {
00586 session->ftp_cwd[0] = '/';
00587 session->ftp_cwd[1] = 0;
00588
00589
00590
00591
00592
00593
00594 if ((session->ftp_stream = _fdopen((int) sock, "r+b")) == 0) {
00595 free(session->ftp_cwd);
00596 free(session);
00597 session = 0;
00598 }
00599 }
00600 }
00601 return session;
00602 }
00603
00610 void NutFtpCloseSession(FTPSESSION * session)
00611 {
00612 if (session) {
00613
00614 fclose(session->ftp_stream);
00615 if (session->ftp_cwd) {
00616 free(session->ftp_cwd);
00617 }
00618 free(session);
00619 }
00620 }
00621
00632 int NutFtpProcessCwd(FTPSESSION * session, char *path)
00633 {
00634 struct stat st;
00635 char *cp = path + strlen(ftp_root);
00636
00637 if (*cp && strcmp(cp, "/")) {
00638
00639
00640
00641 if (stat(path, &st) || !S_ISDIR(st.st_mode)) {
00642 return NutFtpRespondBad(session, 550);
00643 }
00644 }
00645
00646
00647
00648
00649 if (*cp == 0) {
00650 cp = "/";
00651 }
00652 if (session->ftp_cwd) {
00653 free(session->ftp_cwd);
00654 }
00655 if ((session->ftp_cwd = malloc(strlen(cp) + 1)) == 0) {
00656 return NutFtpRespondBad(session, 550);
00657 }
00658 strcpy(session->ftp_cwd, cp);
00659
00660 return NutFtpRespondOk(session, 250);
00661 }
00662
00675 int NutFtpProcessDelete(FTPSESSION * session, char *path)
00676 {
00677 if (unlink(path)) {
00678 return NutFtpRespondBad(session, 550);
00679 }
00680 return NutFtpRespondOk(session, 250);
00681 }
00682
00700 int NutFtpTransferFile(FTPSESSION * session, char *path, int mode)
00701 {
00702 TCPSOCKET *sock;
00703 int ec = 550;
00704 int fh;
00705
00706
00707 if (mode) {
00708 fh = _open(path, _O_BINARY | _O_RDONLY);
00709 }
00710
00711 else {
00712 fh = _open(path, _O_CREAT | _O_TRUNC);
00713 }
00714
00715 if (fh != -1) {
00716
00717 NutFtpSendMode(session, session->ftp_tran_mode);
00718 if ((sock = NutFtpDataConnect(session)) != 0) {
00719 uint16_t mss = sock->so_mss;
00720 uint8_t *buf;
00721
00722 if (mss < 256) {
00723 mss = 256;
00724 }
00725 if ((buf = malloc(mss)) != 0) {
00726 int got;
00727
00728 ec = 0;
00729
00730
00731 if (mode) {
00732 while ((got = _read(fh, buf, mss)) > 0) {
00733 if (NutTcpSend(sock, buf, got) != got) {
00734 ec = 551;
00735 break;
00736 }
00737 }
00738 }
00739
00740
00741 else {
00742 while ((got = NutTcpReceive(sock, buf, mss)) > 0) {
00743 int x;
00744 if ((x = _write(fh, buf, got)) != got) {
00745 ec = 552;
00746 break;
00747 }
00748 }
00749 }
00750 free(buf);
00751 }
00752 NutTcpCloseSocket(sock);
00753 }
00754 _close(fh);
00755
00756
00757 if (mode == 0 && ec) {
00758 unlink(path);
00759 }
00760 }
00761 if (ec) {
00762 return NutFtpRespondBad(session, ec);
00763 }
00764 return NutFtpRespondOk(session, 226);
00765 }
00766
00779 int NutFtpTransferDirectory(FTPSESSION * session, char *path)
00780 {
00781 TCPSOCKET *sock;
00782 FILE *fp;
00783
00784 struct stat st;
00785 DIR *dir;
00786 struct dirent *d_ent;
00787 tm *gmt;
00788 uint32_t size;
00789 int ec = 550;
00790 char *name;
00791
00792 dir = opendir(path);
00793 if (dir) {
00794 NutFtpSendMode(session, 0);
00795 if ((sock = NutFtpDataConnect(session)) != 0) {
00796 if ((fp = _fdopen((int) sock, "r+b")) != 0) {
00797 ec = 0;
00798 while ((d_ent = readdir(dir)) != 0) {
00799 if (d_ent->d_name[0] == '.') {
00800 continue;
00801 }
00802
00803 if ((name = malloc(strlen(path) + strlen(d_ent->d_name) + 2)) != 0) {
00804 sprintf(name, "%s/%s", path, d_ent->d_name);
00805 if (stat(name, &st) == 0) {
00806 if (S_ISDIR(st.st_mode)) {
00807 fputc('d', fp);
00808 size = 0;
00809 } else {
00810 fputc('-', fp);
00811 size = st.st_size;
00812 }
00813 fprintf(fp, "rw-rw-rw- 1 0 0 %6lu ", size);
00814 gmt = gmtime(&st.st_mtime);
00815
00816 fprintf(fp, "%.3s %u ", mon_name + gmt->tm_mon * 3, gmt->tm_mday);
00817
00818 fprintf(fp, "%02u:%02u ", gmt->tm_hour, gmt->tm_min);
00819 fputs(d_ent->d_name, fp);
00820 fputs("\r\n", fp);
00821 }
00822 free(name);
00823 }
00824 }
00825 fclose(fp);
00826 }
00827 NutTcpCloseSocket(sock);
00828 }
00829 closedir(dir);
00830 }
00831 if (ec) {
00832 return NutFtpRespondBad(session, ec);
00833 }
00834 return NutFtpRespondOk(session, 226);
00835 }
00836
00849 int NutFtpProcessMkd(FTPSESSION * session, char *path)
00850 {
00851 if (mkdir(path, 0777)) {
00852 return NutFtpRespondBad(session, 550);
00853 }
00854 return NutFtpRespondOk(session, 257);
00855 }
00856
00869 int NutFtpProcessPass(FTPSESSION * session, char *pass)
00870 {
00871 if (ftp_pass && *ftp_pass) {
00872 if (session->ftp_login != 1 || strcmp(ftp_pass, pass)) {
00873 session->ftp_login = 0;
00874 return NutFtpRespondBad(session, 550);
00875 }
00876 }
00877 session->ftp_login = 2;
00878 return NutFtpRespondOk(session, 230);
00879 }
00880
00894 int NutFtpProcessPassiv(FTPSESSION * session)
00895 {
00896 uint32_t ip = session->ftp_sock->so_local_addr;
00897 uint16_t port = 20;
00898
00899 fprintf(session->ftp_stream, "227 Passive (%u,%u,%u,%u,%u,%u).\r\n",
00900 (uint8_t) ip, (uint8_t) (ip >> 8), (uint8_t) (ip >> 16), (uint8_t) (ip >> 24),
00901 (uint8_t) (port >> 8), (uint8_t) port);
00902 fflush(session->ftp_stream);
00903 session->ftp_passive = 1;
00904
00905 return 0;
00906 }
00907
00922 int NutFtpProcessPort(FTPSESSION * session, char *args)
00923 {
00924 if (ParseIpPort(args, &session->ftp_data_ip, &session->ftp_data_port) == 6) {
00925 if (session->ftp_sock->so_remote_addr == session->ftp_data_ip) {
00926 return NutFtpRespondOk(session, 200);
00927 }
00928 return NutFtpRespondBad(session, 425);
00929 }
00930 return NutFtpRespondBad(session, 501);;
00931 }
00932
00945 int NutFtpProcessPwd(FTPSESSION * session)
00946 {
00947 #ifdef FTPD_DEBUG
00948 printf("\n<'257 \"%s\"' ", session->ftp_cwd);
00949 #endif
00950 fprintf(session->ftp_stream, "257 \"%s\"\r\n", session->ftp_cwd);
00951 return 0;
00952 }
00953
00966 int NutFtpProcessRmd(FTPSESSION * session, char *path)
00967 {
00968 if (rmdir(path)) {
00969 return NutFtpRespondBad(session, 451);
00970 }
00971 return NutFtpRespondOk(session, 257);
00972 }
00973
00983 int NutFtpProcessSystem(FTPSESSION * session)
00984 {
00985 #ifdef FTPD_DEBUG
00986 printf("\n<'215 UNIX Type: L8' ");
00987 #endif
00988 fputs("215 UNIX Type: L8\r\n", session->ftp_stream);
00989 return 0;
00990 }
00991
01006 int NutFtpProcessType(FTPSESSION * session, char *typecode)
01007 {
01008 session->ftp_tran_mode = (*typecode != 'A') && (*typecode != 'a');
01009 return NutFtpRespondOk(session, 200);
01010 }
01011
01024 int NutFtpProcessUser(FTPSESSION * session, char *user)
01025 {
01026 if (ftp_user && *ftp_user) {
01027 if (session->ftp_login && strcmp(ftp_user, user)) {
01028 session->ftp_login = 0;
01029 return NutFtpRespondBad(session, 550);
01030 }
01031 }
01032
01033
01034 if (ftp_pass && *ftp_pass) {
01035 session->ftp_login = 1;
01036 return NutFtpRespondOk(session, 331);
01037 }
01038
01039
01040 session->ftp_login = 2;
01041 return NutFtpRespondOk(session, 230);
01042 }
01043
01055 int NutFtpProcessRequest(FTPSESSION * session, char *request)
01056 {
01057 int rc = 0;
01058 char *cmd;
01059 char *args;
01060
01061
01062 SplitCmdArg(request, &cmd, &args);
01063 #ifdef FTPD_DEBUG
01064 printf("\n>'%s %s' ", cmd, args);
01065 #endif
01066
01067
01068 if (strcmp_P(cmd, cmd_quit_P) == 0) {
01069 NutFtpRespondOk(session, 221);
01070 rc = -1;
01071 }
01072
01073
01074 else if (strcmp_P(cmd, cmd_user_P) == 0) {
01075 rc = NutFtpProcessUser(session, args);
01076 }
01077
01078
01079 else if (strcmp_P(cmd, cmd_pass_P) == 0) {
01080 rc = NutFtpProcessPass(session, args);
01081 } else if (strcmp_P(cmd, cmd_noop_P) == 0) {
01082 NutFtpRespondOk(session, 200);
01083 }
01084
01085 else if (session->ftp_login < 2) {
01086 rc = NutFtpRespondBad(session, 530);
01087 }
01088
01089
01090 else {
01091
01092
01093 if (strcmp_P(cmd, cmd_pasv_P) == 0) {
01094 rc = NutFtpProcessPassiv(session);
01095 }
01096
01097
01098 else if (strcmp_P(cmd, cmd_port_P) == 0) {
01099 rc = NutFtpProcessPort(session, args);
01100 }
01101
01102
01103 else if (strcmp_P(cmd, cmd_pwd_P) == 0 || strcmp_P(cmd, cmd_xpwd_P) == 0) {
01104 rc = NutFtpProcessPwd(session);
01105 }
01106
01107
01108 else if (strcmp_P(cmd, cmd_syst_P) == 0) {
01109 rc = NutFtpProcessSystem(session);
01110 }
01111
01112
01113 else if (strcmp_P(cmd, cmd_type_P) == 0) {
01114 rc = NutFtpProcessType(session, args);
01115 }
01116
01117
01118 else {
01119 char *path;
01120
01121 if ((path = CreateFullPathName(ftp_root, session->ftp_cwd, args)) == 0) {
01122 rc = NutFtpRespondBad(session, 451);
01123 }
01124
01125
01126 else if (strcmp_P(cmd, cmd_cwd_P) == 0) {
01127 rc = NutFtpProcessCwd(session, path);
01128 }
01129
01130
01131 else if (strcmp_P(cmd, cmd_dele_P) == 0) {
01132 rc = NutFtpProcessDelete(session, path);
01133 }
01134
01135
01136 else if (strcmp_P(cmd, cmd_list_P) == 0 || strcmp_P(cmd, cmd_nlst_P) == 0) {
01137 rc = NutFtpTransferDirectory(session, path);
01138 }
01139
01140
01141 else if (strcmp_P(cmd, cmd_mkd_P) == 0 || strcmp_P(cmd, cmd_xmkd_P) == 0) {
01142 rc = NutFtpProcessMkd(session, path);
01143 }
01144
01145
01146 else if (strcmp_P(cmd, cmd_retr_P) == 0) {
01147 rc = NutFtpTransferFile(session, path, 1);
01148 }
01149
01150
01151 else if (strcmp_P(cmd, cmd_rmd_P) == 0 || strcmp_P(cmd, cmd_xrmd_P) == 0) {
01152 rc = NutFtpProcessRmd(session, path);
01153 }
01154
01155
01156 else if (strcmp_P(cmd, cmd_stor_P) == 0) {
01157 rc = NutFtpTransferFile(session, path, 0);
01158 }
01159
01160
01161 else {
01162 rc = NutFtpRespondBad(session, 502);
01163 }
01164
01165 if (path) {
01166 free(path);
01167 }
01168 }
01169 }
01170 return rc;
01171 }
01172
01188 int NutFtpServerSession(TCPSOCKET * sock)
01189 {
01190 int rc = 0;
01191 FTPSESSION *session;
01192 char *buff;
01193 time_t now;
01194 struct _tm *tip;
01195 char ch;
01196
01197
01198 if (NutRegisterFtpRoot(ftp_root)) {
01199 return -1;
01200 }
01201
01202
01203 if ((buff = malloc(FTP_MAX_CMDBUF)) == 0) {
01204 return -1;
01205 }
01206
01207
01208 if ((session = NutFtpOpenSession(sock)) == 0) {
01209 free(buff);
01210 return -1;
01211 }
01212
01213
01214 time(&now);
01215 tip = localtime(&now);
01216 #ifdef FTPD_DEBUG
01217 printf("\n<'");
01218 printf_P(rep_banner, NutVersionString(), &mon_name[tip->tm_mon * 3],
01219 tip->tm_mday, tip->tm_hour, tip->tm_min, tip->tm_sec);
01220 #endif
01221 fprintf_P(session->ftp_stream, rep_banner, NutVersionString(),
01222 &mon_name[tip->tm_mon * 3],
01223 tip->tm_mday, tip->tm_hour, tip->tm_min, tip->tm_sec);
01224
01225
01226
01227
01228 while (rc == 0) {
01229
01230
01231 fflush(session->ftp_stream);
01232 if (fgets(buff, FTP_MAX_CMDBUF, session->ftp_stream) == 0) {
01233 rc = -1;
01234 break;
01235 }
01236
01237
01238 if ((ch = *(buff + strlen(buff) - 1)) != '\n' && ch != '\r') {
01239 do {
01240 if (fgets(buff, FTP_MAX_CMDBUF, session->ftp_stream) == 0) {
01241 rc = -1;
01242 break;
01243 }
01244 } while ((ch = *(buff + strlen(buff) - 1)) != '\n' && ch != '\r');
01245 if (rc == 0) {
01246 rc = NutFtpRespondBad(session, 500);
01247 }
01248 }
01249
01250
01251 else {
01252 rc = NutFtpProcessRequest(session, buff);
01253 }
01254 }
01255
01256
01257 NutFtpCloseSession(session);
01258 free(buff);
01259 return rc;
01260 }
01261