📄 ftpdaemon.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 + -