main (int argc, char *argv[])
{
int index;
register struct tftphdr *tp;
int on, n;
struct sockaddr_storage sin;
char *temp;
int tempint;
struct stat stbuf;
user = xstrdup (DEFAULT_USER);
set_program_name (argv[0]);
iu_argp_init ("tftpd", default_program_authors);
argp_parse (&argp, argc, argv, 0, &index, NULL);
openlog ("tftpd", LOG_PID, LOG_FTP);
if (index < argc)
{
struct dirlist *dirp;
/* Get list of directory prefixes. Skip relative pathnames. */
for (dirp = dirs; index < argc && dirp < &dirs[MAXDIRS]; index++)
{
if (argv[index][0] == '/')
{
dirp->name = argv[index];
dirp->len = strlen (dirp->name);
dirp++;
}
}
}
on = 1;
if (ioctl (0, FIONBIO, &on) < 0)
{
syslog (LOG_ERR, "ioctl(FIONBIO): %m");
exit (EXIT_FAILURE);
}
fstat(0,&stbuf);
if ((stbuf.st_mode & S_IFMT) == S_IFSOCK)
syslog (LOG_INFO, "stbuf.st_mode = S_IFSOCK" );
fromlen = sizeof (from);
n = recvfrom (0, buf, sizeof (buf), 0, (struct sockaddr *) &from, &fromlen);
temp=inet_ntoa(((struct sockaddr_in*)&from)->sin_addr);
tempint=ntohs (((struct sockaddr_in *)&from)->sin_port);
syslog (LOG_INFO, "sin_addr = %s,sin_port = %d" ,temp,tempint);
if (n < 0)
{
syslog (LOG_ERR, "recvfrom: %m\n");
if ((stbuf.st_mode & S_IFMT) == S_IFCHR)
syslog (LOG_INFO, "stbuf.st_mode = S_IFCHR" );
fprintf(stderr,"fd = 0 is not a socket\n");
exit (EXIT_FAILURE);
}
蓝色部分是自己加的。
如果不加,查看/var/log/syslog只会看到一条信息
Dec 13 08:57:14 ch-Founder-PC tftpd[10451]: recvfrom: Socket operation on non-socket
意思是recvfrom函数的参数0不是一个套接字。
再然后就exit了。如果用ps也看不到tftpd进程。
下面是加了蓝色部分的日志信息
Dec 13 08:57:14 ch-Founder-PC tftpd[10451]: sin_addr = 0.0.0.0,sin_port = 0
Dec 13 08:57:14 ch-Founder-PC tftpd[10451]: recvfrom: Socket operation on non-socket
Dec 13 08:57:14 ch-Founder-PC tftpd[10451]: stbuf.st_mode = S_IFCHR
如果用./inetd -d来启动tftpd服务的话,日志信息是:
Dec 13 08:38:27 ch-Founder-PC tftpd[10221]: stbuf.st_mode = S_IFSOCK
Dec 13 08:38:27 ch-Founder-PC tftpd[10221]: sin_addr = 172.22.24.150,sin_port = 34722
Dec 13 08:38:27 ch-Founder-PC tftpd[10222]: 172.22.24.150 (IPv4): read request for /home/ch/tftpboot/test: success
看来inetd.c中肯定有dup2函数把stdin设置为了一个socket。
果然是这样,相关的代码是:
void
run_service (int ctrl, struct servtab *sep)
{
struct passwd *pwd;
struct group *grp = NULL;
char buf[50];
if (sep->se_bi)
{
(*sep->se_bi->bi_fn) (ctrl, sep);
}
else
{
if (debug)
fprintf (stderr, "%d execl %s\n", (int) getpid (), sep->se_server);
dup2 (ctrl, 0);
close (ctrl);
dup2 (0, 1);
dup2 (0, 2);