⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ftpdlib.c

📁 cpc-1631的BSP包for VxWorks操作系统
💻 C
📖 第 1 页 / 共 5 页
字号:
* sessions have exited.
*/

LOCAL void ftpdSessionDelete
    (
    FAST FTPD_SESSION_DATA *pSlot       /* pointer to the slot to be deleted */
    )
    {
    if (pSlot == NULL)			/* null slot? don't do anything */
        return;

    /*
     * The deletion of a session entry must be an atomic operation to support
     * an upper limit on the number of simultaneous connections allowed.
     * This mutual exclusion also prevents a race condition with the server
     * shutdown routine. The last client session will always send an exit
     * signal to the shutdown routine, whether or not the shutdown flag was
     * detected during normal processing.
     */

    semTake (ftpsMutexSem, WAIT_FOREVER);
    --ftpdNumTasks;
    --ftpsCurrentClients;
    lstDelete (&ftpsSessionList, &pSlot->node);

    ftpdSockFree (&pSlot->cmdSock);	/* release data and command sockets */
    ftpdSockFree (&pSlot->dataSock);

    KHEAP_FREE((char *)pSlot);

    /* Send required signal if all sessions are closed. */

    if (ftpsShutdownFlag)
        {
        if (ftpsCurrentClients == 0)
            semGive (ftpsSignalSem);
        }
    semGive (ftpsMutexSem);

    return;
    }

/*******************************************************************************
*
* ftpdWorkTask - main protocol processor for the FTP service
*
* This function handles all the FTP protocol requests by parsing
* the request string and performing appropriate actions and returning
* the result strings.  The main body of this function is a large
* FOREVER loop which reads in FTP request commands from the client
* located on the other side of the connection.  If the result of
* 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 */
#ifdef _WRS_VXWORKS_5_X
    if (ftpdCmdSend (pSlot, sock, 220, messages [MSG_SERVER_READY],
		(int)vxWorksVersion, 0, 0, 0, 0, 0) == ERROR)
#else
        if (ftpdCmdSend (pSlot, sock, 220, messages [MSG_SERVER_READY],
                         (int)runtimeVersion, 0, 0, 0, 0, 0) == ERROR)
#endif /* _WRS_VXWORKS_5_X */
	{
	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 or exceed the buf boundry. exit loop and process command */
	    if ( *pBuf == '\n' ||
		 pBuf >= &pSlot->buf [BUFSIZE-1] )
	    {
		*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);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -