📄 ftpdlib.c
字号:
* parsing the request indicates a valid command, ftpdWorkTask() will* call appropriate functions to handle the request and return the* result of the request. The parsing of the requests are done via* a list of strncmp routines for simplicity.** RETURNS: N/A** ERRNO: N/A** NOMANUAL** INTERNAL* To handle multiple simultaneous connections, this routine and all secondary* routines which process client commands must be re-entrant. If the server's* halt routine is started, the shutdown flag is set, causing this routine to* exit after completing any operation already in progress.*/LOCAL STATUS ftpdWorkTask ( FTPD_SESSION_DATA *pSlot /* pointer to the active slot to be handled */ ) { FAST int sock; /* command socket descriptor */ FAST char *pBuf; /* pointer to session specific buffer */ struct sockaddr_in passiveAddr; /* socket address in passive mode */ FAST char *dirName; /* directory name place holder */ FAST int numRead; int addrLen = sizeof (passiveAddr); /* for getpeername */ int portNum [6]; /* used for "%d,%d,%d,%d,%d,%d" */ u_long value; char *pTail; char newPath [MAX_FILENAME_LENGTH]; char curDirName [MAX_FILENAME_LENGTH]; char *pFileName; FILE *inStream; FILE *outStream; char *upperCommand; /* convert command to uppercase */ pBuf = &pSlot->buf [0]; /* use session specific buffer area */ sock = pSlot->cmdSock; if (ftpsShutdownFlag) { /* Server halt in progress - send abort message to client. */ ftpdCmdSend (pSlot, sock, 421, "Service not available, closing control connection", 0, 0, 0, 0, 0, 0); ftpdSessionDelete (pSlot); return (OK); } /* tell the client we're ready to rock'n'roll */ if (ftpdCmdSend (pSlot, sock, 220, messages [MSG_SERVER_READY], (int)vxWorksVersion, 0, 0, 0, 0, 0) == ERROR) { ftpdSessionDelete (pSlot); return (ERROR); } FOREVER { taskDelay (1); /* time share among same priority tasks */ /* Check error in writting to the control socket */ if (pSlot->cmdSockError == ERROR) { ftpdSessionDelete (pSlot); return (ERROR); } /* * Stop processing client requests if a server halt is in progress. * These tests of the shutdown flag are not protected with the * mutual exclusion semaphore to prevent unnecessary synchronization * between client sessions. Because the secondary tasks execute at * a lower priority than the primary task, the worst case delay * before ending this session after shutdown has started would only * allow a single additional command to be performed. */ if (ftpsShutdownFlag) break; /* get a request command */ FOREVER { taskDelay (1); /* time share among same priority tasks */ if ((numRead = read (sock, pBuf, 1)) <= 0) { /* * The primary server task will close the control connection * when a halt is in progress, causing an error on the socket. * In this case, ignore the error and exit the command loop * to send a termination message to the connected client. */ if (ftpsShutdownFlag) { *pBuf = EOS; break; } /* * Send a final message if the control socket * closed unexpectedly. */ if (numRead == 0) ftpdCmdSend (pSlot, sock, 221, messages [MSG_NO_GOOD_BYE], 0, 0, 0, 0, 0, 0); ftpdSessionDelete (pSlot); return ERROR; } /* Skip the CR in the buffer. */ if ( *pBuf == '\r' ) continue; /* End Of Command delimeter. exit loop and process command */ if ( *pBuf == '\n' ) { *pBuf = EOS; break; } pBuf++; /* Advance to next character to read */ } /* Reset Buffer Pointer before we use it */ pBuf = &pSlot->buf [0]; /* convert the command to upper-case */ for (upperCommand = pBuf; (*upperCommand != ' ') && (*upperCommand != EOS); upperCommand++) *upperCommand = toupper (*upperCommand); ftpdDebugMsg ("read command %s\n", (int)pBuf,0,0,0); /* * Send an abort message to the client if a server * shutdown was started while reading the next command. */ if (ftpsShutdownFlag) { ftpdCmdSend (pSlot, sock, 421, "Service not available, closing control connection", 0, 0, 0, 0, 0, 0); break; } if (strncmp (pBuf, "USER", 4) == 0) { /* check user name */ /* Actually copy the user name into a buffer and save it */ /* till the password comes in. Name is located one space */ /* character after USER string */ if ( *(pBuf + 4) == '\0' ) pSlot->user[0] = '\0'; /* NOP user for null user */ else strncpy(pSlot->user, pBuf+5, MAX_LOGIN_NAME_LEN); pSlot->status &= ~FTPD_USER_OK; if (ftpdCmdSend (pSlot, sock, 331, messages [MSG_PASSWORD_REQUIRED], 0, 0, 0, 0, 0, 0) == ERROR) { ftpdSessionDelete (pSlot); return (ERROR); } continue; } else if (strncmp (pBuf, "PASS", 4) == 0) { /* check user passwd */ /* Actually check it against earlier supplied user name */ if ( loginVerifyRtn != (FUNCPTR)NULL ) { if ( (FUNCPTR *)(loginVerifyRtn)(pSlot->user, pBuf+5) != OK ) { if (ftpdCmdSend (pSlot, sock, 530, messages [MSG_USER_LOGIN_FAILED], 0, 0, 0, 0, 0, 0) == ERROR) { ftpdSessionDelete (pSlot); return (ERROR); } pSlot->status &= ~FTPD_USER_OK; continue; } } pSlot->status |= FTPD_USER_OK; if (ftpdCmdSend (pSlot, sock, 230, messages [MSG_USER_LOGGED_IN], 0, 0, 0, 0, 0, 0) == ERROR) { ftpdSessionDelete (pSlot); return (ERROR); } continue; } else if (strncmp (pBuf, "QUIT", 4) == 0) { /* sayonara */ ftpdCmdSend (pSlot, sock, 221, messages [MSG_SEE_YOU_LATER], 0, 0, 0, 0, 0, 0); ftpdSessionDelete (pSlot); return OK; } else if (strncmp (pBuf, "HELP", 4) == 0) { /* send list of supported commands with multiple line response */ if (ftpdCmdSend (pSlot, sock, FTPD_MULTI_LINE | 214, messages [MSG_COMMAND_LIST_BEGIN], 0, 0, 0, 0, 0, 0) == ERROR) { ftpdSessionDelete (pSlot); return (ERROR); } if (write (pSlot->cmdSock, ftpdCommandList, strlen (ftpdCommandList)) <= 0) { ftpdSessionDelete (pSlot); return (ERROR); } /* this signifies the end of the multiple line response */ if (ftpdCmdSend (pSlot, sock, 214, messages [MSG_COMMAND_LIST_END], 0, 0, 0, 0, 0, 0) == ERROR) { ftpdSessionDelete (pSlot); return (ERROR); } continue; /* All is well go wait for the next command */ } else if ((pSlot->status & FTPD_USER_OK) == 0) /* validated yet? */ { /* user is not validated yet. tell him to log in first */ if (ftpdCmdSend (pSlot, sock, 530, messages [MSG_USER_PASS_REQ], 0, 0, 0, 0, 0, 0) == ERROR) { ftpdSessionDelete (pSlot); return (ERROR); } /* do not proceed further until he's legit */ continue; } if (strncmp (pBuf, "LIST", 4) == 0 || strncmp (pBuf, "NLST", 4) == 0) { STATUS retVal; /* client wants to list out the contents of a directory */ /* if no directory specified or "." specified as a directory * we use the currently active directory name */ if (strlen (pBuf) < 6 || pBuf [5] == '.') dirName = &pSlot->curDirName [0]; else if (pBuf [5] != '/') { if (pSlot->curDirName [strlen (pSlot->curDirName) - 1] == '/') (void) sprintf (newPath, "%s%s", pSlot->curDirName, &pBuf [5]); else (void) sprintf (newPath, "%s/%s", pSlot->curDirName, &pBuf [5]); dirName = newPath; } else dirName = &pBuf [5]; ftpdDebugMsg ("LIST %s\n", (int)dirName,0,0,0); /* get a new data socket connection for the transmission of * the directory listing data */ if (ftpdDataConnGet (pSlot) == ERROR) { if (ftpdCmdSend (pSlot, sock, 426, messages [MSG_DATA_CONN_ERROR], 0, 0, 0, 0, 0, 0) == ERROR) { ftpdSessionDelete (pSlot); return (ERROR); } continue; } /* print out the directory contents over the data connection */ retVal = ftpdDirListGet (pSlot->dataSock, dirName, (strncmp (pBuf, "LIST", 4) == 0)); if (retVal == ERROR) { if (ftpdCmdSend (pSlot, sock, 550, messages [MSG_DIR_ERROR], 0, 0, 0, 0, 0, 0) == ERROR) { ftpdSessionDelete (pSlot); return (ERROR); } } else { if (ftpdCmdSend (pSlot, sock, 226, messages [MSG_TRANS_COMPLETE], 0, 0, 0, 0, 0, 0) == ERROR) { ftpdSessionDelete (pSlot); return (ERROR); } } /* free up the data socket */ ftpdSockFree (&pSlot->dataSock); } else if (strncmp (pBuf, "RETR", 4) == 0) { /* retrieve a file */ /* open the file to be sent to the client */ if (pBuf [5] != '/') { if (pSlot->curDirName [strlen (pSlot->curDirName) - 1] == '/') (void) sprintf (newPath, "%s%s", pSlot->curDirName, &pBuf [5]); else (void) sprintf (newPath, "%s/%s", pSlot->curDirName, &pBuf [5]); pFileName = newPath; } else pFileName = &pBuf [5]; ftpdDebugMsg ("RETR %s\n", (int)pFileName,0,0,0); if ((inStream = fopen (pFileName, "r")) == NULL) { if (ftpdCmdSend (pSlot, sock, 550, messages [MSG_FILE_ERROR], (int)(&pBuf[5]), 0, 0, 0, 0, 0) == ERROR) { ftpdSessionDelete (pSlot); return (ERROR); } continue; } /* ship it away */ ftpdDataStreamSend (pSlot, inStream); (void) fclose (inStream); } else if (strncmp (pBuf, "STOR", 4) == 0) { /* store a file */ /* create a local file */ if (pBuf [5] != '/') { if (pSlot->curDirName [strlen (pSlot->curDirName) - 1] == '/') (void) sprintf (newPath, "%s%s", pSlot->curDirName, &pBuf [5]); else (void) sprintf (newPath, "%s/%s", pSlot->curDirName, &pBuf [5]); pFileName = newPath; } else pFileName = &pBuf [5]; ftpdDebugMsg ("STOR %s\n", (int)pFileName,0,0,0); if ((outStream = fopen (pFileName, "w")) == NULL) { if (ftpdCmdSend (pSlot, sock, 553, messages[MSG_CREATE_ERROR], (int)(&pBuf[5]), 0, 0, 0, 0, 0) == ERROR) { ftpdSessionDelete (pSlot); return (ERROR); } continue; } /* receive the file */ ftpdDataStreamReceive (pSlot, outStream); (void) fclose (outStream); } else if (strncmp (pBuf, "CWD", 3) == 0) { /* change directory */ dirName = &pBuf [4]; /* there is no default device for the specified directory */ if (iosDevFind (dirName, &pTail) == NULL) { if (ftpdCmdSend (pSlot, sock, 501, messages [MSG_DIR_NOT_PRESENT], 0, 0, 0, 0, 0, 0) == ERROR) { ftpdSessionDelete (pSlot); return (ERROR); } continue; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -