📄 ftplib.c
字号:
/********************************************************************************* ftpReplyGet - get an FTP command reply** This routine gets a command reply on the specified control socket.* All the lines of a reply are read (multi-line replies are* indicated with the continuation character "-" as the fourth character* of all but the last line).** The three-digit reply code from the first line is saved and interpreted.* The left-most digit of the reply code identifies the type of code* (see RETURNS below).** The caller's error status is set to the complete three-digit reply code* (see the manual entry for errnoGet()).* If the reply code indicates an error, the entire reply* is printed on standard error.** If an EOF is encountered on the specified control socket, but no EOF was* expected (<expecteof> == FALSE), then ERROR is returned.** RETURNS:* 1 = FTP_PRELIM (positive preliminary)* 2 = FTP_COMPLETE (positive completion)* 3 = FTP_CONTINUE (positive intermediate)* 4 = FTP_TRANSIENT (transient negative completion)* 5 = FTP_ERROR (permanent negative completion)** ERROR if there is a read/write error or an unexpected EOF.*/int ftpReplyGet ( int ctrlSock, /* control socket fd of FTP connection */ BOOL expecteof /* TRUE = EOF expected, FALSE = EOF is error */ ) { char c; FAST int codeType; FAST int code; FAST int dig; int continuation; int origCode; BOOL eof; /* read all lines of a reply: * do * while not eof and not eol * process char * while not eof and not last line of reply */ origCode = 0; codeType = 0; do { /* read all characters of a line */ dig = 0; code = 0; continuation = FALSE; while (!(eof = (read (ctrlSock, &c, 1) == 0)) && (c != '\n')) { dig++; if (dig == 1) /* char 1 is code type */ codeType = c - '0'; if (dig <= 3) /* chars 1-3 are code */ { if (!isdigit (c)) code = -1; else if (code != -1) code = code * 10 + (c - '0'); } if (dig == 4) /* char 4 is continuation marker */ continuation = (c == '-'); if ((c != '\r') && ((ftpVerbose || ((codeType == FTP_ERROR) && (dig > 4))) && !ftpErrorSuppress)) write (STD_ERR, &c, 1); } /* print newline if we've been printing this reply */ if ((ftpVerbose || (codeType == FTP_ERROR)) && !ftpErrorSuppress) printErr ("\n"); /* save the original reply code */ if (origCode == 0) origCode = code; } /* while not eof and not last line of reply */ while (!eof && !((dig >= 3) && (code == origCode) && !continuation)); errnoSet (origCode); /* set status to entire reply code */ /* return error if unexpected eof encountered */ if (eof & !expecteof) return (ERROR); else return (origCode / 100); /* return most signif digit of reply */ }/********************************************************************************* ftpHookup - get a control connection to the FTP server on a specified host** This routine establishes a control connection to the FTP server on the* specified host. This is the first step in interacting with a remote FTP* server at the lowest level. (For a higher-level interaction with a remote* FTP server, see the manual entry for ftpXfer().)** RETURNS:* The file descriptor of the control socket, or ERROR if the Internet* address or the host name is invalid, if a socket could not be created, or* if a connection could not be made.** SEE ALSO: ftpLogin(), ftpXfer()*/int ftpHookup ( char *host /* server host name or inet address */ ) { FAST int ctrlSock; FAST int inetAddr; SOCKADDR_IN ctrlAddr; if (((inetAddr = (int) inet_addr (host)) == ERROR) && ((inetAddr = hostGetByName (host)) == ERROR)) return (ERROR); /* make our control socket */ ctrlSock = socket (AF_INET, SOCK_STREAM, 0); if (ctrlSock < 0) return (ERROR); /* bind a name with no inet address and let system pick port; * this is just so we can find our socket address later */ ctrlAddr.sin_family = AF_INET; ctrlAddr.sin_addr.s_addr = INADDR_ANY; ctrlAddr.sin_port = htons (0); if (bind (ctrlSock, (struct sockaddr *)&ctrlAddr, sizeof (ctrlAddr)) < 0) { close (ctrlSock); return (ERROR); } /* connect to other side */ ctrlAddr.sin_addr.s_addr = inetAddr; ctrlAddr.sin_port = htons (FTP_PORT); if (connect (ctrlSock, (struct sockaddr *)&ctrlAddr, sizeof (ctrlAddr)) < 0) { close (ctrlSock); return (ERROR); } ftpReplyGet (ctrlSock, FALSE); /* read startup message from server */ return (ctrlSock); }/********************************************************************************* ftpLogin - log in to a remote FTP server** This routine logs in to a remote server with the specified user name,* password, and account name, as required by the specific remote host. This* is typically the next step after calling ftpHookup() in interacting with a* remote FTP server at the lowest level. (For a higher-level interaction* with a remote FTP server, see the manual entry for ftpXfer()).** RETURNS:* OK, or ERROR if the routine is unable to log in.** SEE ALSO: ftpHookup(), ftpXfer()*/STATUS ftpLogin ( FAST int ctrlSock, /* fd of login control socket */ char *user, /* user name for host login */ char *passwd, /* password for host login */ char *account /* account for host login */ ) { FAST int n; n = ftpCommand (ctrlSock, "USER %s", (int)user,0,0,0,0,0); if (n == FTP_CONTINUE) n = ftpCommand (ctrlSock, "PASS %s", (int)passwd,0,0,0,0,0); if (n == FTP_CONTINUE) n = ftpCommand (ctrlSock, "ACCT %s", (int)account,0,0,0,0,0); if (n != FTP_COMPLETE) return (ERROR); return (OK); }/********************************************************************************* ftpDataConnInit - initialize an FTP data connection** This routine sets up the client side of a data connection for the* specified control connection. It creates the data port, informs the* remote FTP server of the data port address, and listens* on that data port. The server will then connect to this data port* in response to a subsequent data-transfer command sent on the* control connection (see the manual entry for ftpCommand()).** This routine must be called \f2before\fP the data-transfer command is sent;* otherwise, the server's connect may fail.** This routine is called after ftpHookup() and ftpLogin() to establish a* connection with a remote FTP server at the lowest level. (For a* higher-level interaction with a remote FTP server, see ftpXfer().)** RETURNS: The file descriptor of the data socket created, or ERROR.** SEE ALSO: ftpHookup(), ftpLogin(), ftpCommand(), ftpXfer()*/int ftpDataConnInit ( int ctrlSock /* fd of associated control socket */ ) { FAST int dataSock; int result; int len; int optval; SOCKADDR_IN ctrlAddr; SOCKADDR_IN dataAddr; /* find out our inet address */ len = sizeof (ctrlAddr); if (getsockname (ctrlSock, (struct sockaddr *)&ctrlAddr, &len) < 0) return (ERROR); /* first try - try to send port */ dataSock = socket (AF_INET, SOCK_STREAM, 0); if (dataSock < 0) return (ERROR); dataAddr = ctrlAddr; /* set our inet address */ dataAddr.sin_port = htons (0); /* let system pick port num */ if (bind (dataSock, (struct sockaddr *)&dataAddr, sizeof (dataAddr)) < 0) { close (dataSock); return (ERROR); } if (listen (dataSock, 1) < 0) { close (dataSock); return (ERROR); } /* try to send socket address to other side */ len = sizeof (dataAddr); if (getsockname (dataSock, (struct sockaddr *)&dataAddr, &len) < 0) { close (dataSock); return (ERROR); }#define UCA(n) (((int)(((char *)&dataAddr.sin_addr)[n])) & 0xff)#define UCP(n) (((int)(((char *)&dataAddr.sin_port)[n])) & 0xff) result = ftpCommand (ctrlSock, "PORT %d,%d,%d,%d,%d,%d", UCA(0), UCA(1), UCA(2), UCA(3), UCP(0), UCP(1)); if (result != FTP_ERROR) { if (result != FTP_COMPLETE) { close (dataSock); return (ERROR); } else return (dataSock); } /* second try - try to get port # correct by default */ close (dataSock); dataSock = socket (AF_INET, SOCK_STREAM, 0); if (dataSock < 0) return (ERROR); optval = 1; if ((setsockopt (dataSock, SOL_SOCKET, SO_REUSEADDR, (caddr_t) &optval, sizeof (optval)) < 0) || (bind (dataSock, (struct sockaddr *)&ctrlAddr, sizeof (ctrlAddr)) < 0)) { close (dataSock); return (ERROR); } if (listen (dataSock, 1) < 0) { close (dataSock); return (ERROR); } return (dataSock); }/********************************************************************************* ftpDataConnGet - get a completed FTP data connection** This routine completes a data connection initiated by a call to* ftpDataConnInit(). It waits for a connection on the specified socket from* the remote FTP server. The specified socket should be the one returned by* ftpDataConnInit(). The connection is established on a new socket, whose* file descriptor is returned as the result of this function. The original * socket, specified in the argument to this routine, is closed.** Usually this routine is called after ftpDataConnInit() and ftpCommand() to* initiate a data transfer from/to the remote FTP server.** RETURNS:* The file descriptor of the new data socket, or ERROR if the connection* failed.** SEE ALSO: ftpDataConnInit(), ftpCommand()*/int ftpDataConnGet ( int dataSock /* fd of data socket on which to await connection */ ) { int newDataSock; SOCKADDR_IN from; int fromlen = sizeof (from); newDataSock = accept (dataSock, (struct sockaddr *) &from, &fromlen); close (dataSock); return (newDataSock); }/********************************************************************************* ftpLs - list directory contents via FTP** This routine lists the contents of a directory. The content list* is obtained via an NLST FTP transaction.** The local device name must be the same as the remote host name* with a colon ":" as a suffix. (For example "wrs:" is the device* name for the "wrs" host.)** RETURNS : OK, or ERROR if could not open directory.*/STATUS ftpLs ( char * dirName /* name of directory to list */ ) { DEV_HDR * pDevHdr; char fullFileName [MAX_FILENAME_LENGTH]; char hostName [MAXHOSTNAMELEN]; int hostLength; char usr [MAX_IDENTITY_LEN]; char passwd [MAX_IDENTITY_LEN]; int dataSock; int cntrlSock; char * buffer [BUFSIZ]; int nChars; /* Get device header and complete filename */ ioFullFileNameGet (dirName, &pDevHdr, fullFileName); /* Get the host name, and remove the trailing ":" */ strcpy (hostName, pDevHdr->name); hostLength = strlen (hostName); hostName [hostLength - 1] = EOS; /* Get user ID information */ remCurIdGet (usr, passwd); if (ftpXfer (hostName, usr, passwd, "", "NLST", fullFileName, "", &cntrlSock, &dataSock) != OK) { printErr ("Can't open directory \"%s\"\n", dirName); return (ERROR); } /* Write out the listing */ while ((nChars = read (dataSock, (char *) buffer, BUFSIZ)) > 0) write (STD_OUT, (char *) buffer, nChars); /* Close the sockets opened by ftpXfer */ close (cntrlSock); close (dataSock); return (OK); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -