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

📄 ftpdlib.c

📁 vxworks bsp,s3c2410的vxworks开发资料
💻 C
📖 第 1 页 / 共 5 页
字号:
    FTPD_SESSION_DATA * 	pData;    if (! ftpsActive)    /* Automatic success if server is not running. */        return (OK);    /*     * Remove the FTP server task to prevent additional sessions from starting.     * The exclusion semaphore guarantees a stable list of active clients.     */    semTake (ftpsMutexSem, WAIT_FOREVER);    taskDelete (ftpdTaskId);    ftpdTaskId = -1;    if (ftpsCurrentClients != 0)        serverActive = TRUE;    /*     * Set the shutdown flag so that any secondary server tasks will exit     * as soon as possible. Once the FTP server has started, this routine is     * the only writer of the flag and the secondary tasks are the only     * readers. To avoid unnecessary blocking, the secondary tasks do not     * guard access to this flag when checking for a pending shutdown during     * normal processing. Those tasks do protect access to this flag during     * their cleanup routine to prevent a race condition which would result     * in incorrect use of the signalling semaphore.     */    ftpsShutdownFlag = TRUE;    /*      * Close the command sockets of any active sessions to prevent further      * activity. If the session is waiting for a command from a socket,     * the close will trigger the session exit.     */    pData = (FTPD_SESSION_DATA *)lstFirst (&ftpsSessionList);    while (pData != NULL)        {        ftpdSockFree (&pData->cmdSock);        pData = (FTPD_SESSION_DATA *)lstNext (&pData->node);        }    semGive (ftpsMutexSem);       /* Wait for all secondary tasks to exit. */    if (serverActive)        {        /*         * When a shutdown is in progress, the cleanup routine of the last         * client task to exit gives the signalling semaphore.         */        semTake (ftpsSignalSem, WAIT_FOREVER);        }    /*     * Remove the original socket - this occurs after all secondary tasks     * have exited to avoid prematurely closing their control sockets.     */    ftpdSockFree (&ftpdServerSock);    /* Remove the protection and signalling semaphores and list of clients. */    lstFree (&ftpsSessionList);    /* Sanity check - should already be empty. */    semDelete (ftpsMutexSem);    semDelete (ftpsSignalSem);    ftpsActive = FALSE;    return (OK);    }/********************************************************************************* ftpdSessionAdd - add a new entry to the ftpd session slot list** Each of the incoming FTP sessions is associated with an entry in the* FTP server's session list which records session-specific context for each* control connection established by the FTP clients. This routine creates and* initializes a new entry in the session list, unless the needed memory is not* available or the upper limit for simultaneous connections is reached.** RETURNS: A pointer to the session list entry, or NULL of none available.** ERRNO: N/A** NOMANUAL** INTERNAL* This routine executes within a critical section of the primary FTP server* task, so mutual exclusion is already present when adding entries to the* client list and updating the shared variables indicating the current number* of connected clients.*/LOCAL FTPD_SESSION_DATA *ftpdSessionAdd (void)    {    FAST FTPD_SESSION_DATA 	*pSlot;    if (ftpsCurrentClients >= ftpsMaxClients)        return (NULL);    /* get memory for the new session entry */    pSlot = (FTPD_SESSION_DATA *) calloc (sizeof (FTPD_SESSION_DATA), 1);    if (pSlot == NULL)	{	return (NULL);	}    if (ftpdWindowSize < 0 || ftpdWindowSize > 65536)	    ftpdWindowSize = FTPD_WINDOW_SIZE;        pSlot->bufSize = ftpdWindowSize ;    ftpdDebugMsg ("allocating new session buffer %d bytes\n",	pSlot->bufSize,0,0,0);    pSlot->buf = malloc( pSlot->bufSize );    if( pSlot->buf == NULL )	{	free(pSlot);	return (NULL);	}    /* initialize key fields in the newly acquired slot */    pSlot->dataSock = FTPD_SOCK_FREE;    pSlot->cmdSock = FTPD_SOCK_FREE;    pSlot->cmdSockError = OK;    pSlot->status = FTPD_STREAM_MODE | FTPD_BINARY_TYPE | FTPD_NO_RECORD_STRU;    pSlot->byteCount = 0;    /* assign the default directory for this guy */    if(defaultHomeDir[0] == EOS )	ioDefPathGet (pSlot->curDirName);    else	strcpy( defaultHomeDir, pSlot->curDirName);    semTake (ftpsMutexSem, WAIT_FOREVER);    /* Add new entry to the list of active sessions. */    lstAdd (&ftpsSessionList, &pSlot->node);    ftpdNumTasks++;    ftpsCurrentClients++;    semGive (ftpsMutexSem);    return (pSlot);    }/********************************************************************************* ftpdSessionDelete - remove an entry from the FTP session list** This routine removes the session-specific context from the session list* after the client exits or a fatal error occurs.** RETURNS: N/A** ERRNO: N/A** NOMANUAL** INTERNAL* Unless an error occurs, this routine is only called in response to a* pending server shutdown, indicated by the shutdown flag. Even if the* shutdown flag is not detected and this routine is called because of an* error, the appropriate signal will still be sent to any pending shutdown* routine. The shutdown routine will only return after any active client* 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);    free (pSlot->buf);    free (pSlot);    /* Send required signal if all sessions are closed. */    if (ftpsShutdownFlag)        {        if (ftpsCurrentClients == 0)            semGive (ftpsSignalSem);        }    semGive (ftpsMutexSem);    return;    }/********************************************************************************* ftpPathAccessVerify - verify client access to a path**/LOCAL STATUS ftpPathAccessVerify    (    FTPD_SESSION_DATA *pSlot,    char * path,    int mode    )    {    char * where ;    int len;    /* allways allow access if not anonymous user */    if( (pSlot->status & FTPD_ANONYMOUS) == 0 )	return (OK);    if( mode == O_RDONLY )	{	where = guestHomeDir ;	}    else	{	where = writeDirName ;	}    len = strlen(where);    /* perform case-insensitive comparison a la strncmp() */	{	FAST char *s1, *s2;	FAST int i;	for( s1 = where, s2 = path, i = 0; 		(*s1!=EOS && *s2!=EOS) && i<len;		s1++, s2++, i-- )	    {	    if(toupper(*s1) == toupper(*s2))		continue ;	    else		goto deny;	    }	}    ftpdDebugMsg ("access mode %d allowed for path %s\n", mode, (int)path,0,0);    return OK ;deny:    ftpdDebugMsg ("access mode %d denied for path %s\n", mode, (int)path,0,0);    return ERROR;    }/********************************************************************************* ftpdPathForPrint - prepare a path to be printed to client**/LOCAL char * ftpdPathForPrint( FTPD_SESSION_DATA *pSlot, char * path )    {    if( pSlot->status & FTPD_ANONYMOUS )	{	int len = strlen( guestHomeDir );	if( strncmp( guestHomeDir, path, len) != 0)	    return NULL ;	strcpy( path, path+len );	/* XXX - in-place copy */	}    return(path);    }/********************************************************************************* ftpPathNormalize - process path provided by client for use***/LOCAL void ftpPathNormalize    (    FTPD_SESSION_DATA   *pSlot,    char *		path,    char *		buffer,    char **		pResult    )    {    if ( (strcmp(path,".") == 0) || (path[0] == EOS) )	{	/* explicitly relative */	*pResult = &pSlot->curDirName [0];	return ;	}    (void) pathCat (pSlot->curDirName, path, buffer);    pathCondense (buffer);		/* condense ".." shit */    *pResult = buffer;    }/********************************************************************************* 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, *pBufEnd;/* pointer to session specific buffer */    struct sockaddr_in	passiveAddr;	/* socket address in passive mode */    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 		renFile [MAX_FILENAME_LENGTH];    char 		newPath [MAX_FILENAME_LENGTH];    char		*pFileName;    FILE 		*outStream;    char                *upperCommand;    /* convert command to uppercase */    pBuf = &pSlot->buf [0];	/* use session specific buffer area */    pBufEnd = pSlot->bufSize-1 + pBuf ;/* buffer limit */    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)	goto connectionLost;    FOREVER	{	taskDelay (0);		/* time share among same priority tasks */	/* Check error in writting to the control socket */	if (pSlot->cmdSockError == ERROR)	    goto connectionLost;	pSlot->byteCount = 0 ;	(void) time( &pSlot->timeUsed );	/* refsh idle timer */        /*         * 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;	/* clean up cmd buffer, 8 chars should suffice */	bzero( pBuf, 8 );	/* get a request command */	FOREVER	    {	    taskDelay (0);	/* time share among same priority tasks */	    if ((numRead = read (sock, pBuf, 1)) <= 0)		{                /*                 * The primary server task will close the control connection

⌨️ 快捷键说明

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