?? ftpd_c.txt
字號:
recvurg = 0;
transflag = 0;
return(-1);
}
/*
* Transfer data from peer to "outstr" using the appropriate encapulation of
* the data subject to Mode, Structure, and Type.
*
* N.B.: Form isn't handled.
*/
static int
receive_data(FILE *instr, FILE *outstr)
{
int c;
int cnt;
char buf[BUFSIZ];
struct sigaction sa, sa_saved;
volatile int bare_lfs = 0;
transflag++;
switch (type) {
case TYPE_I:
case TYPE_L:
memset(&sa, 0, sizeof(sa));
sigfillset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
sa.sa_handler = lostconn;
(void) sigaction(SIGALRM, &sa, &sa_saved);
do {
(void) alarm ((unsigned) timeout);
cnt = read(fileno(instr), buf, sizeof(buf));
(void) alarm (0);
if (recvurg)
goto got_oob;
if (cnt > 0) {
if (write(fileno(outstr), buf, cnt) != cnt)
goto file_err;
byte_count += cnt;
}
} while (cnt > 0);
(void) sigaction(SIGALRM, &sa_saved, NULL);
if (cnt < 0)
goto data_err;
transflag = 0;
return (0);
case TYPE_E:
reply(553, "TYPE E not implemented.");
transflag = 0;
return (-1);
case TYPE_A:
while ((c = getc(instr)) != EOF) {
if (recvurg)
goto got_oob;
byte_count++;
if (c == '\n')
bare_lfs++;
while (c == '\r') {
if (ferror(outstr))
goto data_err;
if ((c = getc(instr)) != '\n') {
(void) putc ('\r', outstr);
if (c == '\0' || c == EOF)
goto contin2;
}
}
(void) putc(c, outstr);
contin2: ;
}
fflush(outstr);
if (ferror(instr))
goto data_err;
if (ferror(outstr))
goto file_err;
transflag = 0;
if (bare_lfs) {
lreply(226,
"WARNING! %d bare linefeeds received in ASCII mode",
bare_lfs);
printf(" File may not have transferred correctly.\r\n");
}
return (0);
default:
reply(550, "Unimplemented TYPE %d in receive_data", type);
transflag = 0;
return (-1);
}
data_err:
transflag = 0;
reply(426, "Data Connection");
return (-1);
file_err:
transflag = 0;
reply(452, "Error writing file");
return (-1);
got_oob:
myoob();
recvurg = 0;
transflag = 0;
return (-1);
}
void
statfilecmd(char *filename)
{
FILE *fin;
int c;
int atstart;
char line[LINE_MAX];
(void)snprintf(line, sizeof(line), "/bin/ls -lgA %s", filename);
fin = ftpd_popen(line, "r");
lreply(211, "status of %s:", filename);
atstart = 1;
while ((c = getc(fin)) != EOF) {
if (c == '\n') {
if (ferror(stdout)){
perror_reply(421, "control connection");
(void) ftpd_pclose(fin);
dologout(1);
/* NOTREACHED */
}
if (ferror(fin)) {
perror_reply(551, filename);
(void) ftpd_pclose(fin);
return;
}
(void) putc('\r', stdout);
}
if (atstart && isdigit(c))
(void) putc(' ', stdout);
(void) putc(c, stdout);
atstart = (c == '\n');
}
(void) ftpd_pclose(fin);
reply(211, "End of Status");
}
void
statcmd(void)
{
union sockunion *su;
u_char *a, *p;
char hbuf[MAXHOSTNAMELEN];
int ispassive;
int error;
lreply(211, "%s FTP server status:", hostname);
error = getnameinfo((struct sockaddr *)&his_addr, his_addr.su_len,
hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST);
printf(" Connected to %s", remotehost);
if (error == 0 && strcmp(remotehost, hbuf) != 0)
printf(" (%s)", hbuf);
printf("\r\n");
if (logged_in) {
if (guest)
printf(" Logged in anonymously\r\n");
else
printf(" Logged in as %s\r\n", pw->pw_name);
} else if (askpasswd)
printf(" Waiting for password\r\n");
else
printf(" Waiting for user name\r\n");
printf(" TYPE: %s", typenames[type]);
if (type == TYPE_A || type == TYPE_E)
printf(", FORM: %s", formnames[form]);
if (type == TYPE_L)
#if NBBY == 8
printf(" %d", NBBY);
#else
printf(" %d", bytesize); /* need definition! */
#endif
printf("; STRUcture: %s; transfer MODE: %s\r\n",
strunames[stru], modenames[mode]);
ispassive = 0;
if (data != -1)
printf(" Data connection open\r\n");
else if (pdata != -1) {
printf(" in Passive mode\r\n");
su = (union sockunion *)&pasv_addr;
ispassive++;
goto printaddr;
} else if (usedefault == 0) {
size_t alen;
int af, i;
su = (union sockunion *)&data_dest;
printaddr:
/* PASV/PORT */
if (su->su_family == AF_INET) {
if (ispassive)
printf("211- PASV ");
else
printf("211- PORT ");
a = (u_char *)&su->su_sin.sin_addr;
p = (u_char *)&su->su_sin.sin_port;
printf("(%u,%u,%u,%u,%u,%u)\r\n",
a[0], a[1], a[2], a[3],
p[0], p[1]);
}
/* LPSV/LPRT */
alen = 0;
switch (su->su_family) {
case AF_INET:
a = (u_char *)&su->su_sin.sin_addr;
p = (u_char *)&su->su_sin.sin_port;
alen = sizeof(su->su_sin.sin_addr);
af = 4;
break;
case AF_INET6:
a = (u_char *)&su->su_sin6.sin6_addr;
p = (u_char *)&su->su_sin6.sin6_port;
alen = sizeof(su->su_sin6.sin6_addr);
af = 6;
break;
default:
af = 0;
break;
}
if (af) {
if (ispassive)
printf("211- LPSV ");
else
printf("211- LPRT ");
printf("(%u,%llu", af, (unsigned long long)alen);
for (i = 0; i < alen; i++)
printf(",%u", a[i]);
printf(",%u,%u,%u)\r\n", 2, p[0], p[1]);
}
/* EPRT/EPSV */
switch (su->su_family) {
case AF_INET:
af = 1;
break;
case AF_INET6:
af = 2;
break;
default:
af = 0;
break;
}
if (af) {
char pbuf[10];
union sockunion tmp = *su;
if (tmp.su_family == AF_INET6)
tmp.su_sin6.sin6_scope_id = 0;
if (getnameinfo((struct sockaddr *)&tmp, tmp.su_len,
hbuf, sizeof(hbuf), pbuf, sizeof(pbuf),
NI_NUMERICHOST | NI_NUMERICSERV) == 0) {
if (ispassive)
printf("211- EPSV ");
else
printf("211- EPRT ");
printf("(|%u|%s|%s|)\r\n",
af, hbuf, pbuf);
}
}
} else
printf(" No data connection\r\n");
reply(211, "End of status");
}
void
fatal(char *s)
{
reply(451, "Error in server: %s", s);
reply(221, "Closing connection due to server error.");
dologout(0);
/* NOTREACHED */
}
void
reply(int n, const char *fmt, ...)
{
char *buf, *p, *next;
int rval;
va_list ap;
va_start(ap, fmt);
rval = vasprintf(&buf, fmt, ap);
va_end(ap);
if (rval == -1 || buf == NULL) {
printf("412 Local resource failure: malloc\r\n");
fflush(stdout);
dologout(1);
}
next = buf;
while ((p = strsep(&next, "\n\r"))) {
printf("%d%s %s\r\n", n, (next != '\0') ? "-" : "", p);
if (debug)
syslog(LOG_DEBUG, "<--- %d%s %s", n,
(next != '\0') ? "-" : "", p);
}
(void)fflush(stdout);
free(buf);
}
void
reply_r(int n, const char *fmt, ...)
{
char *p, *next;
char msg[BUFSIZ];
char buf[BUFSIZ];
va_list ap;
struct syslog_data sdata = SYSLOG_DATA_INIT;
sdata.log_fac = LOG_FTP;
va_start(ap, fmt);
vsnprintf(msg, sizeof(msg), fmt, ap);
va_end(ap);
next = msg;
while ((p = strsep(&next, "\n\r"))) {
snprintf(buf, sizeof(buf), "%d%s %s\r\n", n,
(next != '\0') ? "-" : "", p);
write(STDOUT_FILENO, buf, strlen(buf));
if (debug) {
buf[strlen(buf) - 2] = '\0';
syslog_r(LOG_DEBUG, &sdata, "<--- %s", buf);
}
}
}
void
lreply(int n, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
(void)printf("%d- ", n);
(void)vprintf(fmt, ap);
va_end(ap);
(void)printf("\r\n");
(void)fflush(stdout);
if (debug) {
va_start(ap, fmt);
syslog(LOG_DEBUG, "<--- %d- ", n);
vsyslog(LOG_DEBUG, fmt, ap);
va_end(ap);
}
}
static void
ack(char *s)
{
reply(250, "%s command successful.", s);
}
void
nack(char *s)
{
reply(502, "%s command not implemented.", s);
}
/* ARGSUSED */
void
yyerror(char *s)
{
cbuf[strcspn(cbuf, "\n")] = '\0';
reply(500, "'%s': command not understood.", cbuf);
}
void
delete(char *name)
{
struct stat st;
LOGCMD("delete", name);
if (stat(name, &st) < 0) {
perror_reply(550, name);
return;
}
if ((st.st_mode&S_IFMT) == S_IFDIR) {
if (rmdir(name) < 0) {
perror_reply(550, name);
return;
}
goto done;
}
if (unlink(name) < 0) {
perror_reply(550, name);
return;
}
done:
ack("DELE");
}
void
cwd(char *path)
{
FILE *message;
if (chdir(path) < 0)
perror_reply(550, path);
else {
if ((message = fopen(_PATH_CWDMESG, "r")) != NULL) {
char line[LINE_MAX];
while (fgets(line, sizeof(line), message) != NULL) {
line[strcspn(line, "\n")] = '\0';
lreply(250, "%s", line);
}
(void) fflush(stdout);
(void) fclose(message);
}
ack("CWD");
}
}
void
replydirname(const char *name, const char *message)
{
char *p, *ep;
char npath[MAXPATHLEN * 2];
p = npath;
ep = &npath[sizeof(npath) - 1];
while (*name) {
if (*name == '"') {
if (ep - p < 2)
break;
*p++ = *name++;
*p++ = '"';
} else {
if (ep - p < 1)
break;
*p++ = *name++;
}
}
*p = '\0';
reply(257, "\"%s\" %s", npath, message);
}
void
makedir(char *name)
{
LOGCMD("mkdir", name);
if (mkdir(name, 0777) < 0)
perror_reply(550, name);
else
replydirname(name, "directory created.");
}
void
removedir(char *name)
{
LOGCMD("rmdir", name);
if (rmdir(name) < 0)
perror_reply(550, name);
else
ack("RMD");
}
void
pwd(void)
{
char path[MAXPATHLEN];
if (getcwd(path, sizeof(path)) == NULL)
perror_reply(550, "Can't get current directory");
else
replydirname(path, "is current directory.");
}
char *
renamefrom(char *name)
{
struct stat st;
if (stat(name, &st) < 0) {
perror_reply(550, name);
return ((char *)0);
}
reply(350, "File exists, ready for destination name");
return (name);
}
void
renamecmd(char *from, char *to)
{
LOGCMD2("rename", from, to);
if (rename(from, to) < 0)
perror_reply(550, "rename");
else
ack("RNTO");
}
static void
dolog(struct sockaddr *sa)
{
char hbuf[sizeof(remotehost)];
if (getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf), NULL, 0, 0) == 0)
(void) strlcpy(remotehost, hbuf, sizeof(remotehost));
else
(void) strlcpy(remotehost, "unknown", sizeof(remotehost));
#ifdef HASSETPROCTITLE
snprintf(proctitle, sizeof(proctitle), "%s: connected", remotehost);
setproctitle("%s", proctitle);
#endif /* HASSETPROCTITLE */
if (logging)
syslog(LOG_INFO, "connection from %s", remotehost);
}
/*
* Record logout in wtmp file and exit with supplied status.
* NOTE: because this is called from signal handlers it cannot
* use stdio (or call other functions that use stdio).
*/
void
dologout(int status)
{
transflag = 0;
if (logged_in) {
sigprocmask(SIG_BLOCK, &allsigs, NULL);
ftpdlogwtmp(ttyline, "", "");
if (doutmp)
ftpd_logout(utmp.ut_line);
}
/* beware of flushing buffers after a SIGPIPE */
_exit(status);
}
/*ARGSUSED*/
static void
sigurg(int signo)
{
recvurg = 1;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -