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

📄 ftpdaemon.c

📁 一个ftp服务器程序
💻 C
字号:
  # include "ftpdaemon.h"void    sig_handle(int);    char    ftplog_file[_POSIX_PATH_MAX];    char    curr_time[80];    int main(int argc, char **argv){    int            listenfd, connfd;    int            clilen;    struct sockaddr_in    cliaddr, servaddr;    if ( fork() )         exit ( 0 );    if ( setpgrp() < 0 ) {	FTPLOG("Cannot change process group");	fprintf(stderr, "---------- FTP server start failed ----------");	exit ( -1 );    }    signal( SIGPIPE, SIG_IGN );    signal( SIGINT, SIG_IGN );    signal( SIGQUIT, SIG_IGN );    signal( SIGHUP, SIG_IGN );    signal( SIGCLD, SIG_IGN );/**  * signal( SIGCLD, sig_handler );	  **/    /***   * log file located at $HOME/$LOGPATH/ftplog.log    ***/    memset( ftplog_file, 0, sizeof(ftplog_file) );    strncpy( ftplog_file, getenv( "LOGPATH" ), sizeof(ftplog_file) );    if ( *ftplog_file == 0 )        sprintf( ftplog_file, "%s/%s/", getenv("HOME"), "log" );    else if ( basename( ftplog_file ) )        strcat( ftplog_file, "/" );    strcat( ftplog_file, "ftplog.log" );    listenfd = socket(AF_INET, SOCK_STREAM, 0);    if ( listenfd < 0 ) {        FTPLOG("socket() calls fail");        perror( "!!!!!!!!!!!!!!!! socket()" );        return -1;    }    memset( &servaddr, 0, sizeof(servaddr) );    servaddr.sin_family      = AF_INET;    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);    servaddr.sin_port        = htons(FTP_SERV_PORT);    if ( bind(listenfd, (void *)&servaddr, sizeof(servaddr)) < 0 ) {        FTPLOG("bind() calls fail");        perror( "!!!!!!!!!!!!!!!! bind()" );        return -1;    }    if ( listen(listenfd, SOMAXCONN) < 0 ) {        FTPLOG("listen() calls fail");        perror( "!!!!!!!!!!!!!!!! listen()" );        return -1;    }    FTPLOG("----------------- FTP server startup -----------------");    while ( 1 ) {        clilen = sizeof(cliaddr);        if ((connfd = accept(listenfd, (void *)&cliaddr, &clilen)) < 0)             continue;        if ( fork() == 0 ) {            close( listenfd );                switch ( judge_req_type( connfd ) ) {                case GET_REQUEST:	/* NT client ==> this machine */                    if ( ftp_get_server( connfd ) != E_SUCC )                         FTPLOG("[%s:%d] ftp_get_server() call failure", CurrFILE, CurrLINE);                    else                        FTPLOG("[%s:%d] ftp_get_server() call success", CurrFILE, CurrLINE);		    break;                case PUT_REQUEST:	/* this machine ==> NT client */#ifdef UPLOAD_NOT_ALLOWED		    FTPLOG("[%s:%d] FTP upload request denied...", CurrFILE, CurrLINE);#else                    if ( ftp_put_server( connfd ) != E_SUCC )                         FTPLOG("[%s:%d] ftp_put_server() call failure", CurrFILE, CurrLINE);                    else                        FTPLOG("[%s:%d] ftp_put_server() call success", CurrFILE, CurrLINE);#endif	 	    break;		default:			FTPLOG("[%s:%d] Illegal user request", CurrFILE, CurrLINE);	    }            close( connfd );            exit( 0 );        }        close( connfd );                }}int ftp_get_server( int connfd ){    char filename[NAMELEN], pathname[_POSIX_PATH_MAX];        char backupname[_POSIX_PATH_MAX];    char buffer[FILEBUF_SIZE], ack;    char filenum[NUMLEN];    char prtdir[_POSIX_PATH_MAX], backupdir[_POSIX_PATH_MAX];    struct stat stat_buf;    FILE   *sndfp;    int num, left, bytes, i, j;    int looptime;    memset( prtdir, 0, sizeof( prtdir ));    memset( backupdir, 0, sizeof( backupdir ));    strncpy( prtdir, getenv("PRINTDIR"), sizeof(prtdir) );    if ( *prtdir == 0 )        sprintf( prtdir, "%s/%s", getenv("HOME"), "print/" );    if ( prtdir[strlen(prtdir)-1] != '/' ) 	strcat( prtdir, "/" );    strncpy( backupdir, getenv("FTPBACKUP"), sizeof(backupdir) );    if ( *backupdir == 0 )        sprintf( backupdir, "%s/%s", getenv("HOME"), "log/" );    if ( backupdir[strlen(backupdir)-1] != '/' ) 	strcat( backupdir, "/" );    if ( recv_nbytes( connfd, filenum, NUMLEN, RCV_TIME ) != E_SUCC ) {        FTPLOG("[%s:%d] Receive filenum failure",CurrFILE,CurrLINE);        return E_FAIL;    }    ack = ACK_SUCC;    if ( send_nbytes( connfd, &ack, 1 ) != E_SUCC ) {        FTPLOG("[%s:%d] Send filelen failure",CurrFILE,CurrLINE);        return E_FAIL;    }    if ( atoi( filenum ) == 0 )        FTPLOG("[%s:%d] No filename specified", CurrFILE, CurrLINE);    else if ( atoi( filenum ) > 1 )        FTPLOG("[%s:%d] File numbers [%s]", CurrFILE, CurrLINE, filenum);    for( looptime=0; looptime < atoi(filenum); looptime++ ) {        if ( recv_nbytes( connfd, filename, NAMELEN, RCV_TIME ) != E_SUCC ) {            FTPLOG("[%s:%d] Receive filename failure",CurrFILE,CurrLINE);            return E_FAIL;        }        if ( !filename ) {            FTPLOG("[%s:%d] Filename is null",CurrFILE,CurrLINE);            return E_FAIL;        }        if ( strlen(filename) != strlen( basename(filename) )) {            FTPLOG("[%s:%d] Filename [%s] include invalid char", CurrFILE, CurrLINE, filename );            return E_FAIL;        }        sprintf( pathname, "%s%s", prtdir, filename );        sprintf( backupname, "%s%s.%s", backupdir, filename, currtime() );	if ( stat(pathname, &stat_buf) < 0 ) {            FTPLOG("[%s:%d] File [%s] doesn't exist", CurrFILE, CurrLINE, pathname);            return E_FAIL;        }	else            FTPLOG("[%s:%d] File to download [%s]", CurrFILE, CurrLINE, filename);        if ( stat_buf.st_size < 0 )            stat_buf.st_size = 0;        sprintf( buffer, "%d", stat_buf.st_size );        if ( send_nbytes( connfd, buffer, _FILELEN_ ) != E_SUCC ) {            FTPLOG("[%s:%d] Send filelen failure",CurrFILE,CurrLINE);            return E_FAIL;        }        if ( (sndfp = fopen(pathname, "rb")) == NULL ) {            FTPLOG("[%s:%d] File [%s] not readable\n", CurrFILE, CurrLINE, pathname);            return E_FAIL;        }        if ( stat_buf.st_size == 0 )         /* NULL file */            goto endproc;        num  = stat_buf.st_size / FILEBUF_SIZE;        left = stat_buf.st_size % FILEBUF_SIZE;        for ( j=0; j <= num; j++ ) {            bytes = (j==num) ? left : FILEBUF_SIZE;            if ( bytes > 0 ) {                memset( buffer, 0, sizeof(buffer) );                if ( fread(buffer, bytes, 1, sndfp ) != 1 ) {                    FTPLOG("[%s:%d] Fread error",CurrFILE,CurrLINE);                    fclose(sndfp);                    return E_FAIL;                }                if(send_nbytes(connfd,buffer,bytes)!=E_SUCC) {                    fclose(sndfp);                    FTPLOG("[%s:%d] Data send() error",CurrFILE,CurrLINE);                    return E_FAIL;                }                if(recv_nbytes( connfd,&ack,1,RCV_TIME )!=E_SUCC) {                    fclose(sndfp);                    FTPLOG("[%s:%d] Recv ACK fail",CurrFILE,CurrLINE);                    return E_FAIL;                }                if ( ack != ACK_SUCC ) {                    fclose( sndfp );                    FTPLOG("[%s:%d] Bad ACK",CurrFILE,CurrLINE);                    return E_FAIL;               }            }        }endproc:        fclose( sndfp );	if( rename( pathname, backupname ) == 0 )	   FTPLOG("Backup file to [%s]", CurrFILE, CurrLINE, backupname);	else {	   FTPLOG("[%s:%d] Unable backup file to [%s]", CurrFILE, CurrLINE, backupname);	   unlink( pathname );	}        FTPLOG("[%s:%d] [%s] send over", CurrFILE, CurrLINE, filename);    }    return E_SUCC;}int ftp_put_server( int connfd ){    char filename[NAMELEN], pathname[_POSIX_PATH_MAX];        char buffer[FILEBUF_SIZE], ack;    char filenum[NUMLEN];    char prtdir[_POSIX_PATH_MAX];    FILE   *rcvfp;    int num, left, bytes, i, j;    int looptime;    int filesize;    memset( prtdir, 0, sizeof( prtdir ));    strncpy( prtdir, getenv("PRINTDIR"), sizeof(prtdir) );    if ( *prtdir == 0 )        sprintf( prtdir, "%s/%s", getenv("HOME"), "print/" );    if ( recv_nbytes( connfd, filenum, NUMLEN, RCV_TIME ) != E_SUCC ) {        FTPLOG("[%s:%d] Receive filenum failure",CurrFILE,CurrLINE);        return E_FAIL;    }    ack = ACK_SUCC;    if ( send_nbytes( connfd, &ack, 1 ) != E_SUCC ) {        FTPLOG("[%s:%d] Send ack failure",CurrFILE,CurrLINE);        return E_FAIL;    }    if ( atoi(filenum) == 0 )        FTPLOG("[%s:%d] No filename specified", CurrFILE, CurrLINE);    FTPLOG("[%s:%d] File numbers [%s]", CurrFILE, CurrLINE, filenum);    for( looptime=0; looptime < atoi(filenum); looptime++ ) {        if ( recv_nbytes( connfd, filename, NAMELEN, RCV_TIME ) != E_SUCC ) {            FTPLOG("[%s:%d] Receive filename failure",CurrFILE,CurrLINE);            return E_FAIL;        }        if ( !filename ) {            FTPLOG("[%s:%d] Filename is null",CurrFILE,CurrLINE);            return E_FAIL;        }        if ( strlen(filename) != strlen( basename(filename) )) {            FTPLOG("[%s:%d] Filename [%s] include invalid char", CurrFILE, CurrLINE, filename );            return E_FAIL;        }        sprintf( pathname, "%s%s", prtdir, filename );        FTPLOG("[%s:%d] File to upload [%s]", CurrFILE, CurrLINE, filename);        ack = ACK_SUCC;        if ( send_nbytes( connfd, &ack, 1 ) != E_SUCC ) {            FTPLOG("[%s:%d] Send ack failure",CurrFILE,CurrLINE);            return E_FAIL;        }	memset( buffer, 0, sizeof(buffer) );        if ( recv_nbytes( connfd, buffer, _FILELEN_, RCV_TIME ) != E_SUCC ) {            FTPLOG("[%s:%d] Receive filename failure",CurrFILE,CurrLINE);            return E_FAIL;        }	        filesize = atoi( buffer );	if ( filesize < 0 ) {            FTPLOG("[%s:%d] File size invalid",CurrFILE,CurrLINE);            return E_FAIL;        }        ack = ACK_SUCC;        if ( send_nbytes( connfd, &ack, 1 ) != E_SUCC ) {            FTPLOG("[%s:%d] Send ack failure",CurrFILE,CurrLINE);            return E_FAIL;        }        if ( (rcvfp = fopen(pathname, "wb")) == NULL ) {            FTPLOG("[%s:%d] File [%s] not writeable\n", CurrFILE, CurrLINE, pathname);            return E_FAIL;        }        num  = filesize / FILEBUF_SIZE;        left = filesize % FILEBUF_SIZE;        for ( j=0; j <= num; j++ ) {            bytes = (j==num) ? left : FILEBUF_SIZE;            if ( bytes > 0 ) {                memset( buffer, 0, sizeof(buffer) );                if( recv_nbytes( connfd, buffer, bytes, RCV_TIME ) != E_SUCC ){                     ack = ACK_FAIL;                    send_nbytes( connfd, &ack, 1 );                    fclose( rcvfp );                    FTPLOG("[%s:%d] Recv_nbytes() DATA fail", CurrFILE, CurrLINE);                    return E_FAIL;                }                ack = ACK_SUCC;                if(send_nbytes( connfd, &ack, 1) != E_SUCC) {                    fclose( rcvfp );                    FTPLOG("[%s:%d] ACK send() error",CurrFILE,CurrLINE);                    return E_FAIL;                }                if ( fwrite( buffer, bytes, 1, rcvfp ) != 1 ) {                    fclose( rcvfp );                    FTPLOG("[%s:%d] Fwrite() failure", CurrFILE, CurrLINE);                    return E_FAIL;                }            }        }endproc:        fclose( rcvfp );        FTPLOG("[%s:%d] [%s] send over", CurrFILE, CurrLINE, filename);    }    return E_SUCC;}void    sig_handle(int  sig){    int flag;    if ( sig == SIGCLD )	if ( waitpid( 0, &flag, WNOHANG ) > 0 ) {		signal( SIGCLD, sig_handle );		return;		}    else {        FTPLOG("Receive signal [%d]", sig);	signal( sig, sig_handle );    }    return;}/******************************************************************************   First client user send special string to identify itself.*   It is to avoid someone's attaching server through telnet directly*   In future's version, the identify code is usded to specify other actions.*   0xab 0xcd : server--> client     0xcd 0xef : client-->server******************************************************************************/int judge_req_type( int connfd ){    unsigned char strtmp[3];    int      retval;    memset( strtmp, 0, sizeof(strtmp) );    if ( recv_nbytes( connfd, strtmp, sizeof(strtmp), RCV_TIME ) != E_SUCC ) {        FTPLOG("[%s:%d] Receive Identify Code failure",CurrFILE,CurrLINE);        return E_FAIL;    }    if ( (strtmp[0] == 0xab) && (strtmp[1] == 0xcd) )        retval = GET_REQUEST;    else if ( (strtmp[0] == 0xcd) && (strtmp[1] == 0xef) )        retval = PUT_REQUEST;    else        memset( strtmp, 0, sizeof(strtmp) );    if ( send_nbytes( connfd, strtmp, sizeof(strtmp) ) != E_SUCC ) {        FTPLOG("[%s:%d] Send Identify Code failure",CurrFILE,CurrLINE);	retval = E_FAIL;    }    return retval ;}

⌨️ 快捷键说明

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