/**
 * Parse arguments.
 *
 * @param argc Argument count.
 * @param argv Argument vector.
 * @param[out] conf Configuration.
 */
static void ParseArgs(int argc, char** argv, Config& conf) {
    std::stringstream usage;
    usage << "Usage: " PROJECT_NAME " <command> [options]";
    opts::options_description visible_desc(usage.str());

    try {
        opts::options_description common_desc("# Common options");
        common_desc.add_options()
            ("config", opts::value<std::string>(), "Path to configuration file.")
            ("cert-log", opts::value<std::string>(), "Certification log.")
            ("help", "Print this usage information.")
            ("port", opts::value<uint16_t>(), "Port.")
            ;

        visible_desc.add(common_desc);

        opts::variables_map vm;
        opts::store(
            opts::command_line_parser(argc, argv)
                .options(visible_desc)
                .run(),
            vm);

        if (vm.count("config")) {
            fs::path path(vm["config"].as<std::string>());
            if (!fs::exists(path))
                ExitError(visible_desc, "configuration file does not exist");

            try {
                opts::store(opts::parse_config_file<char>(path.c_str(), visible_desc), vm);
            } catch (const std::exception& e) {
                ExitError(visible_desc, "unable to parse configuration file");
            }
        }

        opts::notify(vm);

        if (vm.count("cert-log")) {
            conf.cert_log_ = vm["cert-log"].as<std::string>();
        }

        if (vm.count("port")) {
            conf.port_ = vm["port"].as<uint16_t>();
        }

        if (vm.count("help")) {
            std::cout << visible_desc;
            exit(0);
        }

        FLAGS_logtostderr = true;
    } catch (const std::exception& e) {
        std::stringstream msg;
        msg << "unable to process options -- " << e.what();
        ExitError(visible_desc, msg.str());
    }
}
BOOL CRegressTreeDlg::OnInitDialog(){
	CDialog::OnInitDialog();
	DNAStat_Tree = (CTreeCtrl *)GetDlgItem(IDC_TREE1); 
	
	DepthEdit = (CEdit *)GetDlgItem(IDC_DEPTH);
	CString d;
	d.Format("%d", DNAStat->getDepth());
	DepthEdit->SetWindowText(d);

	try{ 
		DNAStat->toTreeCtrl(DNAStat_Tree, DNAStat_Tree->GetRootItem());
	}
	catch(CString ErrMsg){
		CString Messg2(_T("--> Unable to display CDNAStatement in TreeForm at CRegressTreeDlg::OnInitDialog()"));
		Messg2 = ErrMsg + Messg2;
		ExitError(Messg2);
	}
	    
	ExpandTree(DNAStat_Tree->GetRootItem());

    
	VarEdit	= (CEdit*)GetDlgItem(IDC_X1EDIT); 
	FuncRes	= (CEdit*)GetDlgItem(IDC_FXEDID);
	FuncPrime 	= (CEdit*)GetDlgItem(IDC_PRIMEFX);

	VarEdit->SetWindowText(CString(_T("UNDEF")));
	FuncRes->SetWindowText(CString(_T("UNDEF")));
	FuncPrime->SetWindowText(CString(_T("UNDEF")));

	 return TRUE;  
}
Exemple #3
0
/* Get file info about a certain file (directories count as files). 
Note that "." and ".." are considering special files, not dirs. */
FileInfoEnum GetFileInfo(char* path)
{
	FileInfoEnum fileInfo;
	int fileDesc = open(path, O_RDONLY);
	if (fileDesc == -1)
	{
		if (errno = ENOENT)
			fileInfo = FILEINFO_DOESNOTEXIST;
		else
			fileInfo = FILEINFO_ERROR;
		
		close(fileDesc);
		return fileInfo;
	}
	
	struct stat statBuf;
	if ( fstat(fileDesc, &statBuf) != 0 )
		ExitError("fstat() failed to get file info.");
	
	if ( S_ISDIR(statBuf.st_mode) )
		fileInfo = FILEINFO_DIR;
	else if ( S_ISREG(statBuf.st_mode) )
		fileInfo = FILEINFO_REGULARFILE;
	else
		fileInfo = FILEINFO_SPECIALFILE;
	
	close(fileDesc);
	return fileInfo;
}
Exemple #4
0
void CheckForBreak( void )
{
    if( sig_count > 0 ) {
        sig_count = 0;
        PrtMsg( ERR | USER_BREAK_ENCOUNTERED );
        ExitError();
    }
}
Exemple #5
0
int CreateListenSocket(int maxBacklogConnections, int listenPort, bool dynamicPort = false, bool allowAddrInUseBind = false)
{
	/* binding with a port value of 0 in the sock address
	struct will bind to a dynamic port */
	if (dynamicPort)
	{
		listenPort = 0;
	}
	
	/* create our listentng socket */
	int listenSocket = socket(AF_INET, SOCK_STREAM, 0);	// create socket for TCP/IP connection
	if (listenSocket == -1) 				// socket() returns -1 upon failure
		ExitError("Failed to create listening socket.");
	
	if (allowAddrInUseBind)
	{
		/* this alleviates "address already in use" errors when the kernel has
		not gotten around to freeing the socket on the specified port from 
		previous instances of this or other processes */
		int yes = 1; // apparently for setting socket options on Solaris this would need to be '1'
		if ( setsockopt(listenSocket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1 )
			ExitError("Could not set socket option.");
	}
	
	/* fill in the local address struct for binding to */
	struct sockaddr_in localAddr;					// local machine internet address information
	localAddr.sin_family = AF_INET;					// host byte order
	localAddr.sin_port = htons(listenPort);				// port to listen on, network byte order
	localAddr.sin_addr.s_addr = htonl(INADDR_ANY);			// fill with the host machine's IP
	//localAddr.sin_addr.s_addr = inet_addr("127.0.0.1");		// another way
	memset(localAddr.sin_zero, 0, sizeof(localAddr.sin_zero));	// zero the sin_zero field
	
	/* bind the listen socket to the address and port */
	if ( bind(listenSocket, (struct sockaddr *)&localAddr, sizeof(localAddr)) == -1 )
		ExitError("Could not bind address to socket.");
	
	/* set the socket to listen for connections */
	if ( listen(listenSocket, maxBacklogConnections) == -1 )
		ExitError("Could not listen and on the address and port.");
	
	return listenSocket;
}
Exemple #6
0
int AcceptConnectionFromListenSocket(int listenSocket, struct sockaddr_in * remoteAddr)
{
	/* Accept the first connection on the backlog queue. accept() blocks if
	there are no connections in the queue. */
	socklen_t sinSize = sizeof(sockaddr_in);
	int acceptSocket = accept(listenSocket, (struct sockaddr *)remoteAddr, &sinSize);
	if (acceptSocket == -1)
		ExitError("Failure creating socket for accepting connection.");
	
	return acceptSocket;
}
Exemple #7
0
void	Vm::exec(std::vector<Token> &listInstr, bool verbose) {
	Factory		f;
	_verbose = verbose;

	for (std::vector<Token>::iterator it = listInstr.begin(); it != listInstr.end(); ++it) {
		if (_functInstr.find(it->getInstr()) != _functInstr.end()) {
			if (_verbose)
				std::cout << it->getInstr() << " " <<  it->getType() << " " << it->getValue() << std::endl;
			(this->*_functInstr[it->getInstr()])(f.createOperand(Vm::_typeMap[it->getType()], it->getValue()));
		}
		else if (_functInstrNoArgs.find(it->getInstr()) != _functInstrNoArgs.end()) {
			if (_verbose)
				std::cout << it->getInstr() << std::endl;
			(this->*_functInstrNoArgs[it->getInstr()])();
		}
	}
	throw ExitError();
}
Exemple #8
0
int main(int argc, char* argv[])
{
	/* Parse the command line arguments */
	int listenPort = -1;		// port to listen on
	char* dir = NULL;		// directory to serve
	ParseCmdLineArgs(argc, argv, dir, listenPort);
	printf("Running server in directory %s, and on port %i.\n", dir, listenPort);
	
	/* Create the listening socket for our FTP server */
	int listenSocket = CreateListenSocket( FTP_MAX_BACKLOG_CONNECTIONS, listenPort, false, true );

	/* Do this to reap zombie child processes */
	struct sigaction sa;			// need this struct for handling signals and destroying zombie child procs
	sa.sa_handler = SigChildHandler;	// function pointer
	sigemptyset(&sa.sa_mask);
	sa.sa_flags = SA_RESTART;
	if ( sigaction(SIGCHLD, &sa, NULL) == -1 )
		ExitError("sigaction() failed.");
	
	while (1)
	{
		/* Accept the next connection on the backlog queue. Blocks if
		there are no connections in the queue. */
		struct sockaddr_in remoteAddr;
		int acceptSocket = AcceptConnectionFromListenSocket(listenSocket, &remoteAddr);
		printf("FTP server received connection from %s\n", inet_ntoa(remoteAddr.sin_addr));
		
		/* Each FTP session gets its own process. */
		if ( !fork() )			
		{
			// child process code
			close(listenSocket);				// child doesn't need listen socket
			FTPSession(acceptSocket, dir, remoteAddr);	// begin the FTP session
			close(acceptSocket);				// when done with the session close the socket
			exit(EXIT_SUCCESS);				// exit with success code 0
		}
		
		// parent process continues here
		close(acceptSocket);			// parent doesn't need the accept socket anymore
	}
	
	return 0;
}
Exemple #9
0
STATIC RET_T perform( TARGET *targ, DEPEND *dep, DEPEND *impldep, time_t max_time )
/*********************************************************************************/
{
    CLIST   *clist;
    CLIST   *before;
    RET_T   ret;
    DEPEND  *depend;
    DEPEND  *impliedDepend;

    depend = NULL;
    impliedDepend = NULL;
    assert( targ != NULL && dep != NULL );

    if( Glob.query ) {
        ++cListCount;
        return( RET_WARN );
    }
    if( Glob.touch ) {
        ++cListCount;
        ResetExecuted();
        if( !targ->attr.symbolic ) {
            CacheRelease();
            if( TouchFile( targ->node.name ) != RET_SUCCESS ) {
                PrtMsg( ERR | COULD_NOT_TOUCH, targ->node.name );
                return( RET_ERROR );
            }
        }
        targ->touched = true;
        return( RET_SUCCESS );
    }

    /* means that this is a sufsuf made implicit rule */
    if( impldep == NULL ) {
        clist = dep->clist;
        depend = dep;
        impliedDepend = NULL;
    } else {
        clist = impldep->clist;
        depend = targ->depend;
        impliedDepend = dep;
    }
    if( clist == NULL ) {
        clist = DotCList( DOT_DEFAULT );
        if( clist == NULL ) {
            // No commands in Microsoft and POSIX mode is considered OK
            // and executed
            if( Glob.compat_nmake || Glob.compat_posix ) {
                targ->cmds_done = true;
                return( RET_SUCCESS );
            }
            if( targ->attr.symbolic != false ) {
                targ->cmds_done = true;
                return( RET_SUCCESS );
            }
            if( targ->allow_nocmd ) {
                /* for UNIX folks: make target symbolic */
                targ->attr.symbolic = true;
                return( RET_SUCCESS );
            }
            PrtMsg( FTL | NO_DEF_CMDS_FOR_MAKE, DotNames[DOT_DEFAULT], targ->node.name );
            ExitFatal();
        }
    }
    if( !Glob.noexec ) {
        ResetExecuted();
    }
    if( !doneBefore ) {
        before = DotCList( DOT_BEFORE );
        if( before != NULL ) {
            ++cListCount;
            if( ExecCList( before ) != RET_SUCCESS ) {
                PrtMsg( FTL | S_COMMAND_RET_BAD, DotNames[DOT_BEFORE] );
                ExitFatal();
            }
        }
        doneBefore = true;
    }
    exPush( targ, depend, impliedDepend );
    ret = carryOut( targ, clist, findMaxTime( targ, dep, max_time ) );
    exPop();
    if( ret == RET_ERROR ) {
        ExitError();
    }
    return( ret );
}
CRegressTreeDlg::CRegressTreeDlg(CWnd* pParent /*=NULL*/, CDNAStatement* D)
    : CDialog(CRegressTreeDlg::IDD, pParent), DNAStat(D)
{
    if(!DNAStat)
        ExitError(_T("No Tree Provided To Dialog Box"));
}
Exemple #11
0
void
vcerror(long lexIdx, short etype, const char *buf, va_list va, short eno)
{
    static const char *TNames[] = { "?","Warning","Error", "Fatal", "SoftError"
#ifndef REGISTERED
	, "Unimplemented"
#endif
    };
    long lexIdxBeg;
    long lexFileNameLen;
    long lexLine;
    char *lexFile;
    long errcol = 0;
    char ebuf[100];
    long ebufoff = 0;

    lexLine=FindLexFileLine(lexIdx, &lexFile, &lexFileNameLen, &lexIdxBeg);

    /*
     * Use original lexer file to obtain line for printing since the
     * internal copy could be munged.
     *
     * We need to determine a couple of things:
     *  lexLine - Indicates the line number of the error (0 if no associated line)
     *  errcol  - The physical column where the error occurred (0 for no line)
     *  ebuf    - The null terminated buffer.  This buffer is at most 80 characters
     *            but will contain the character position that has the error.
     *  ebufoff - The logical start of the error buffer.  This will be 0 as long as
     *            the error occurs in the first 80 columns.  Beyond that, this will
     *            jump by 10.
     * lexFile  - The name of the file containing the error
     * lexFileNameLen
     */

    ebuf[0] = 0;
    if (lexLine && ErrorInFileValid) {

	short c;
	long i = lexIdxBeg;
	short pos = 0;

	while ((c = FindLexCharAt(i)) != EOF && c != '\n')
	{
	    if (c == '\t')
	    {
		short tab;
		tab = ((pos + ebufoff + 8) & ~7) - ebufoff;
		while (pos < tab)
		    ebuf[pos++] = ' ';
	    }
	    else
		ebuf[pos++] = c;

	    if (i == lexIdx)
		errcol = pos + ebufoff;

	    if (pos > 80)
	    {
	       if ((errcol - (pos + ebufoff)) > 10) break;
	       memcpy(ebuf, ebuf+10, pos-10);
	       pos -= 10;
	       ebufoff += 10;
	    }
	    ++i;
	}
	ebuf[pos] = 0;
    }

    eprintf(1, "DC1: \"%.*s\" L:%d ", lexFileNameLen, lexFile, lexLine);

    if (ErrorOpt & 1)
	eprintf(1, "C:%d %c:%d ", errcol + 1, TNames[etype][0], eno);
    else
	eprintf(1, "%s:%d ", TNames[etype], eno);

    veprintf(1, buf, va);
    eprintf(1, "\n");

    if (lexLine && ErrorInFileValid && (ErrorOpt & 2))
    {
	short pos = errcol - ebufoff;

	/* We Need to account for the fact that the ^ will take up one space */
	if (pos)
	   pos = pos - 1;

	eprintf(0, "%s\n%*.*s^\n", ebuf, pos, pos, "");
    }

    if (etype == ESOFT || etype == EFATAL) {
	ExitError(20);
    }
    if (etype == EWARN && ExitCode < 5)
	ExitCode = 5;
    if (etype != EWARN && ExitCode < 20)
	ExitCode = 20;
}
Exemple #12
0
void FTPDataTransferSession(int controlSocket, int dataTransferSessionSocket)
{
	/* LIST command - Sends a list of files to be displayed. */
	if (strcmp(cmdTokens[0], ftpCmds[FTPCMD_LIST]) == 0)
	{
		printf("Receivied LIST command.\n");
		send(controlSocket, replies[REPLY_150_SENDING_DIR_LIST], strlen(replies[REPLY_150_SENDING_DIR_LIST]), 0);
		//FILE* lsOutput = popen("ls -l -n", "r");
		char cmdString[PATH_MAX+100]; // path plus room for the command
		sprintf(cmdString, "sh -c \"ls %s -l > .dirlist\"", dir);
		system(cmdString);
		FILE* dirListFile = fopen(".dirlist", "r"); // open in program's working directory
		
		char lineBuf[2000]; // HACK HACK: totally made up buffer size
		while ( fgets( lineBuf, 2000, dirListFile ) != NULL )
		{
			int lineBufLen = strlen( lineBuf );
			lineBuf[lineBufLen-1] = '\r';
			lineBuf[lineBufLen] = '\n';
			lineBufLen++;
			send(dataTransferSessionSocket, lineBuf, lineBufLen, 0);
		}
		fclose(dirListFile);
		
		send(controlSocket, replies[REPLY_226_DIR_SEND_OK], strlen(replies[REPLY_226_DIR_SEND_OK]), 0);
	}
	/* RETR command - Retrieve file over the data transfer connection. */
	else if (strcmp(cmdTokens[0], ftpCmds[FTPCMD_RETR]) == 0)
	{
		printf("Received RETR command.\n");
		
		sprintf(pathBuf, "%s%s", dir, cmdTokens[1]); // cmdTokens[1] is the file name
		FILE* fileToSend = fopen(pathBuf, "rb");
		if (fileToSend == NULL)
		{
			printf("RETR couldn't open file.\n");
			send(controlSocket, replies[REPLY_550_FILE_NOT_FOUND], strlen(replies[REPLY_550_FILE_NOT_FOUND]), 0);
			return; // error
		}
		
		//char fileSizeInBytes[20];
		char retrReply[PATH_MAX+1000]; // HACK : max path + max number of digits for byte size + reply string
		int fileSize = GetFileSize(pathBuf);
		sprintf(retrReply, replies[REPLY_150_OPEN_BINARY_DATA_CONNECTION], cmdTokens[1], fileSize);
		send(controlSocket, retrReply, strlen(retrReply), 0);
		
		/* FTP has three transfer modes: STREAM, BLOCK, and COMPRESSED.
		We will send using STERAM mode which simply sends a stream of
		bytes and treat all files as "file structures" as defined in
		RFC 959 as opposed to "record structures." From RFC959: "If the
		structure is a file structure, the EOF is indicated by the sending
		host closing the data connection and all bytes are data bytes."
		So, we just close the connection after sending all the bytes. */
		
		while ( 1 )
		{
			/* read blocks of 1024 bytes into msgBuf and then send */
			size_t numBytesRead = fread(msgBuf, 1, 1024, fileToSend);
			send(dataTransferSessionSocket, msgBuf, numBytesRead, 0);
			if (numBytesRead < 1024) // reached end of file
				break;
		}
		
		fclose(fileToSend);
		
		send(controlSocket, replies[REPLY_226_FILE_SEND_OK], strlen(replies[REPLY_226_FILE_SEND_OK]), 0);
	}
	/* STOR command - Receive file from user. */
	else if (strcmp(cmdTokens[0], ftpCmds[FTPCMD_STOR]) == 0)
	{
		printf("Received STOR command.\n");
		
		char* newFileName = cmdTokens[1];
		sprintf(pathBuf, "%s%s", dir, newFileName);
		FILE* fileToReceive = fopen(pathBuf, "wb");
		if (fileToReceive == NULL)
		{
			printf("STOR couldn't create file.\n");
			send(controlSocket, replies[REPLY_550_COULDNT_OPEN_FILE], strlen(replies[REPLY_550_COULDNT_OPEN_FILE]), 0);
			return; // error
		}
		
		send(controlSocket, replies[REPLY_150_READY_FOR_TRANSFER], strlen(replies[REPLY_150_READY_FOR_TRANSFER]), 0);
		
		/* keep reading until the connection is closed */
		while (1)
		{
			if ( ( msgBufLen = recv( dataTransferSessionSocket, msgBuf, MSG_BUF_MAX_SIZE, 0 ) ) == -1 )
				ExitError("Error receiving control connection data.");
			if ( msgBufLen == 0 ) // recv() returns 0 if the remote side has closed the connection */
				break;
			fwrite( msgBuf, 1, msgBufLen, fileToReceive );
		}
		
		send(controlSocket, replies[REPLY_226_RECEIVED_FILE_CLOSING_CONNECTION], strlen(replies[REPLY_226_RECEIVED_FILE_CLOSING_CONNECTION]), 0);
	}
	/* Unknown or invalid command */
	else
	{
		printf("Received invalid DTP command.\n");
		send(controlSocket, replies[REPLY_500_UNKNOWN_COMMAND], strlen(replies[REPLY_500_UNKNOWN_COMMAND]), 0);
		return; // error
	}
}
Exemple #13
0
void FTPSession(int controlSocket, char* inputRootDir, struct sockaddr_in remoteAddr)
{
	
	strcpy( dir, inputRootDir ); // copy into new buffer so we can make the directory string larger if needed
	AddTrailingSlashIfNeeded( dir ); // make sure we have a trailing slash on the file
	char properRootDir[PATH_MAX];
	strcpy( properRootDir, dir );
	
	/* Test to see if the directory to serve exists */	
	if ( GetFileInfo(dir) == FILEINFO_DOESNOTEXIST )
		ExitError("Failed to open directory to serve.");
	
	/* Reply 220 to user upon connection */
	if ( send(controlSocket, replies[REPLY_220_BEGIN_SESSION], strlen(replies[REPLY_220_BEGIN_SESSION ]), 0) == -1 )
		ExitError("Error sending reply.");
	
	while (1)
	{
		printf("Serving Directory: <%s>.\n", dir);
		
		int ret;
		
		/* Receive and parse the next command
		over the socket from the user. */
		ret = GetControlConnectionCmd(
			controlSocket,
			msgBuf, msgBufLen, MSG_BUF_MAX_SIZE,
			cmdTokens, numCmdTokens
		);
		if (ret == 1) // user has closed connection
			break; // break out of loop and end session
		
		/* Do the specified command */
		
		/* USER command - We're not doing authentication. Just reply
		with a normal username okay message */
		if (strcmp(cmdTokens[0], ftpCmds[FTPCMD_USER]) == 0)
		{
			printf("Receivied USER command.\n");
			send(controlSocket, replies[REPLY_331_USERNAME_OK], strlen(replies[REPLY_331_USERNAME_OK]), 0);
		}
		/* PASS command - Like with PASS we're not doing
		authentication. Just reply with a normal username okay
		message */
		else if (strcmp(cmdTokens[0], ftpCmds[FTPCMD_PASS]) == 0)
		{
			printf("Receivied PASS command.\n");
			send(controlSocket, replies[REPLY_230_PASS_ACCEPT], strlen(replies[REPLY_230_PASS_ACCEPT]), 0);
		}
		/* SYST command - Give a typical UNIX system response */
		else if (strcmp(cmdTokens[0], ftpCmds[FTPCMD_SYST]) == 0)
		{
			printf("Receivied SYST command.\n");
			send(controlSocket, replies[REPLY_215_SYST_RESPONSE], strlen(replies[REPLY_215_SYST_RESPONSE]), 0);
		}
		/* CWD command - Print out the current working directory. */
		else if (strcmp(cmdTokens[0], ftpCmds[FTPCMD_CWD]) == 0)
		{
			printf("Receivied CWD command.\n");
			
			char* dirToChangeTo = cmdTokens[1];
			
			if ( strcmp( "." , dirToChangeTo ) == 0 )
			{
				// change to current directory, so don't change anything and reply with success
				send(controlSocket, replies[REPLY_250_DIRCHANGE_SUCCESS], strlen(replies[REPLY_250_DIRCHANGE_SUCCESS]), 0);
				continue;
			}
			
			/* handle ".." CWD command */
			if ( strcmp( ".." , dirToChangeTo ) == 0 )
			{
				int len = strlen( dir );
				assert( dir[len-1] == '/' ); // all dirs should have slash at end
				if ( strcmp( dir , properRootDir ) == 0 )
				{
					printf("User tried to go above root directory.\n");
					send(controlSocket, replies[REPLY_550_DIRCHANGE_FAILURE], strlen(replies[REPLY_550_DIRCHANGE_FAILURE]), 0);
					continue;
				}
				/* chomp the last dir off the end */
				for (int i = len - 2;  ; i--)
				{
					assert ( i > 0 );
					if (dir[i] == '/')
					{
						dir[i+1] = '\0';
						break;
					}
				}
				send(controlSocket, replies[REPLY_250_DIRCHANGE_SUCCESS], strlen(replies[REPLY_250_DIRCHANGE_SUCCESS]), 0);
				continue;
			}
			
			/* make sure dirToChange is a subdirectory of the current
			directory to prevent the user from jumping multiple directories
			with the dirToChangeTo string (this check especially important
			to the prevent the use of ".."s somewhere in the string which
			might allow the user to navigate above the root directory). */
			
			DIR *dp;
			struct dirent *ep;
			bool entryExistsInCurrentDir;
			dp = opendir(dir);
			if (dp != NULL)
			{
				while ( ep = readdir(dp) )
					if ( strcmp( ep->d_name, dirToChangeTo ) == 0)
						entryExistsInCurrentDir = true;
				closedir(dp);
			}
			else
				ExitError("For some reason the current directory doesn't exist, or opendir() failed for some other reason.");
			
			if ( entryExistsInCurrentDir == false )
			{
				send(controlSocket, replies[REPLY_550_DIRCHANGE_FAILURE], strlen(replies[REPLY_550_DIRCHANGE_FAILURE]), 0);
				continue;
			}
			
			/* Finally, we have to make sure the file entry we found
			is actually a directory, not a regular file. */
			sprintf(pathBuf, "%s%s%s", dir, dirToChangeTo, "/");
			int fileInfo = GetFileInfo( pathBuf );
			if ( fileInfo == FILEINFO_DIR )
			{
				strcpy( dir, pathBuf );
				send(controlSocket, replies[REPLY_250_DIRCHANGE_SUCCESS], strlen(replies[REPLY_250_DIRCHANGE_SUCCESS]), 0);
			}
			else
			{
				send(controlSocket, replies[REPLY_550_DIRCHANGE_FAILURE], strlen(replies[REPLY_550_DIRCHANGE_FAILURE]), 0);
			}
		}
		/* PASV command - Reply over the the control connection with
		the IP and port info of the data transfer connection listening
		IP and port, and then fork off the data transfer process (DTP)
		which will get a command from the control connection while
		listening for a connection from the user on the data transfer
		connection. Once the DTP gets the command over the control
		connectionit will do the specified command over the data
		connection once the user connects. */
		else if (strcmp(cmdTokens[0], ftpCmds[FTPCMD_PASV]) == 0)
		{
			printf("Receivied PASV command.\n");
			
			/* Create new listening socket */
			
			const int DTP_MAX_BACKLOG_CONNECTIONS = 1;
			const uint16_t RANDOM_DTP_LISTEN_PORT = 49064; // HACK: for our random listening port we're just going to make a port number up
			int dataTransferListenSocket = CreateListenSocket( DTP_MAX_BACKLOG_CONNECTIONS, RANDOM_DTP_LISTEN_PORT, false, true );
			
			/* Say Bert.CS.UIC.edu is 131.193.40.32 to the
			outside world. We want to get that address. */
			char localHostName[MAXHOSTNAMELEN];
			gethostname(localHostName, MAXHOSTNAMELEN);
			struct hostent* hostEntry = gethostbyname(localHostName);
			struct in_addr hostIPAddr = *(struct in_addr *)*hostEntry->h_addr_list;// TODO: make sure the first item in the list isn't 127.0.0.1 or something
			char* localIPString = inet_ntoa( hostIPAddr ); // points to the first entry in the list
			
			printf("PASV found IP: %s.\n", localIPString);
			
			/* Create the port string */
			
			unsigned char h1, h2, h3, h4;
			unsigned char p1, p2;
			
			// HACK HACK: this stuff is not endian safe
			unsigned char* bytePtr = (unsigned char*)&hostIPAddr;
			h1 = bytePtr[0];
			h2 = bytePtr[1];
			h3 = bytePtr[2];
			h4 = bytePtr[3];
			
			bytePtr = (unsigned char*)&RANDOM_DTP_LISTEN_PORT;
			p2 = bytePtr[0]; // high byte
			p1 = bytePtr[1]; // low byte
			
			// port = p1 * 256 + p2 
			char pasvPortString[30]; // (xxx,yyy,zzz,www,ppp,nnn)
			sprintf(pasvPortString, "(%i,%i,%i,%i,%i,%i)", h1, h2, h3, h4, p1, p2);
			
			printf("Port value test: p1*256+p2 ?= port :: %d ?= %d.\n", p1*256+p2, RANDOM_DTP_LISTEN_PORT);
			printf("PASV string: %s.\n", pasvPortString);
			
			/* Send the PASV reply */
			
			char pasvReply[200];
			sprintf(pasvReply, replies[REPLY_227_PASSIVE_MODE], pasvPortString);
			send(controlSocket, pasvReply, strlen(pasvReply), 0);
			
			int dtp_pid = fork();
			if ( !dtp_pid )
			{
				/* Data Transfer Process (DTP) code */
				printf("Created data transfer process.\n");
				
				/* Get the next command from the control connection (RETR, STOR, LIST) */
				ret = GetControlConnectionCmd(
					controlSocket,
					msgBuf, msgBufLen, MSG_BUF_MAX_SIZE,
					cmdTokens, numCmdTokens
				);
				if (ret == 1) // control socket was closed for some reason
				{
					close(dataTransferListenSocket);	// done with the listen socket
					exit(EXIT_FAILURE);
				}
				
				/* Accept the user connection */
				struct sockaddr_in remoteAddr;
				int dataTransferSessionSocket = AcceptConnectionFromListenSocket(dataTransferListenSocket, &remoteAddr);
				printf("Data transfer process (DTP) received connection from %s\n", inet_ntoa(remoteAddr.sin_addr));
				
				FTPDataTransferSession(controlSocket, dataTransferSessionSocket);
				
				close(dataTransferSessionSocket);	// when done with the session close the socket
				close(dataTransferListenSocket);	// close the listen socket too
				
				printf("Closing data transfer process.\n");
				exit(EXIT_SUCCESS);				// exit with success code
			}
			
			/* parent continues here */
			
			close(dataTransferListenSocket); // parent doesn't need the this socket
			
			/* wait for the child process to complete */
			waitpid( dtp_pid, NULL, 0 ); // TODO: check for things other than normal termination
			printf("Server-PI resuming execution.\n");
		}
		/* TYPE command */
		else if (strcmp(cmdTokens[0], ftpCmds[FTPCMD_TYPE]) == 0)
		{
			if ( strcmp(cmdTokens[1], "I") == 0 ) // binary
			{
				send(controlSocket, replies[REPLY_200_TYPE_SET_TO_I], strlen(replies[REPLY_200_TYPE_SET_TO_I]), 0);
			}
			else if ( strcmp(cmdTokens[1], "A") == 0 ) // ASCII
			{
				send(controlSocket, replies[REPLY_200_TYPE_SET_TO_A], strlen(replies[REPLY_200_TYPE_SET_TO_A]), 0);
			}
			else
			{
				// TODO: handle other stuff
			}
		}
		/* QUIT command */
		else if (strcmp(cmdTokens[0], ftpCmds[FTPCMD_QUIT]) == 0)
		{
			printf("Receivied QUIT command.\n");
			send(controlSocket, replies[REPLY_221_END_SESSION], strlen(replies[REPLY_221_END_SESSION]), 0);
			break; // break out of the loop
		}
		/* Unknown command */
		else
		{
			printf("Receivied unknown command.\n");
			send(controlSocket, replies[REPLY_500_UNKNOWN_COMMAND], strlen(replies[REPLY_500_UNKNOWN_COMMAND]), 0);
		}
	}
	
	/* Done */
	printf("Ended FTP session from %s\n", inet_ntoa(remoteAddr.sin_addr));
}
Exemple #14
0
/* Get the next command on the control connection socket
(blocking until it comes), and parses the command */
int GetControlConnectionCmd(int controlSocket, char msgBuf[], int& msgBufLen, int MSG_BUF_MAX_SIZE, char* cmdTokens[], int& numCmdTokens)
{
	/* Receive the next message on the control connection (blocks until next message is received). */
	
	if ( ( msgBufLen = recv(controlSocket, msgBuf, MSG_BUF_MAX_SIZE, 0 ) ) == -1 )
		ExitError("Error receiving control connection data.");
	if ( msgBufLen == 0 ) // recv() returns 0 if the remote side has closed the connection */
		return 1;
	
	printf("Received Data:");
	for (int i = 0; i < msgBufLen; i++)
	{
		//printf("byte %i: " i);
		printf(" '");
		if (msgBuf[i] == '\n')
			printf("<LF>");
		else if (msgBuf[i] == '\r')
			printf("<CR>");
		else if (msgBuf[i] < 32 || msgBuf[i] > 126)
			printf("<0x%x>", msgBuf[i]);
		else
			putchar(msgBuf[i]);
		printf("'");
	}
	printf(".\n");
	
	/* Get rid of the trailing CR LF for processing the commands */
	
	msgBuf[msgBufLen-2] = '\0';
	msgBufLen--;
	
	printf("Command: %s\n", msgBuf);
	
	/* Tokenize strings */
	
	char* token = strtok(msgBuf, " ");
	if (token == NULL) // found no delimiter to tokenize
	{
		/* if there are no space delimiters it
		must be a one word command */
		cmdTokens[0] = msgBuf;
		numCmdTokens = 1;
	}
	else
	{
		/* there are space delimeters so we add all
		the tokens to our array of tokens */
		cmdTokens[0] = token;
		numCmdTokens = 1;
		while ( (token = strtok(NULL, " ")) != NULL )
		{
			cmdTokens[numCmdTokens] = token;
			numCmdTokens++;
		}
	}
	
	printf("Command tokens:");
	for (int i = 0; i < numCmdTokens; i++)
	{
		printf(" \"");
		printf("%s", cmdTokens[i]);
		printf("\"");
	}
	printf(".\n");
	
	return 0;
}