13.6 daemon_inetd Function


13.6 daemon_inetd Function

Figure 13.11 shows a function named daemon_inetd that we can call from a server we know is invoked by inetd .

Figure 13.11 daemon_inetd function: daemonizes process run by inetd .

daemon_inetd.c

 1 #include "unp.h" 2 #include <syslog.h> 3 extern int daemon_proc; /* defined in error.c */ 4 void 5 daemon_inetd(const char *pname, int facility) 6 { 7 daemon_proc = 1; /* for our err_XXX() functions */ 8 openlog(pname, LOG_PID, facility); 9 } 

This function is trivial compared to daemon_init , because all of the daemonization steps are performed by inetd when it starts. All that we do is set the daemon_proc flag for our error functions (Figure D.3) and call openlog with the same arguments as the call in Figure 13.4.

Example: Daytime Server as a Daemon Invoked by inetd

Figure 13.12 is a modification of our daytime server from Figure 13.5 that can be invoked by inetd .

Figure 13.12 Protocol-independent daytime server that can be invoked by inetd .

inetd/daytimetcpsrv3.c

 1 #include "unp.h" 2 #include <time.h> 3 int 4 main(int argc, char **argv) 5 { 6 socklen_t len; 7 struct sockaddr *cliaddr; 8 char buff[MAXLINE]; 9 time_t ticks; 10 daemon_inetd(argv[0], 0); 11 cliaddr = Malloc(sizeof(struct sockaddr_storage)); 12 len = sizeof(struct sockaddr_storage); 13 Getpeername(0, cliaddr, &len); 14 err_msg("connection from %s", Sock_ntop(cliaddr, len)); 15 ticks = time(NULL); 16 snprintf (buff, sizeof(buff), "%.24s\r\n", ctime (& ticks )); 17 Write(0, buff, strlen(buff)); 18 Close(0); /* close TCP connection */ 19 exit(0); 20 } 

There are two major changes in this program. First, all the socket creation code is gone: the calls to tcp_listen and to accept . Those steps are done by inetd and we reference the TCP connection using descriptor 0 (standard input). Second, the infinite for loop is gone because we are invoked once per client connection. After servicing this client, we terminate.

Call getpeername

11 “14 Since we do not call tcp_listen , we do not know the size of the socket address structure it returns, and since we do not call accept , we do not know the client's protocol address. Therefore, we allocate a buffer for the socket address structure using sizeof(struct sockaddr_storage) and call getpeername with descriptor 0 as the first argument.

To run this example on our Solaris system, we first assign the service a name and port, adding the following line to /etc/services :

 
 mydaytime 9999/tcp 

We then add the following line to /etc/inetd.conf :

 
 mydaytime stream tcp nowait andy /home/andy/daytimetcpsrv3 daytimetcpsrv3 

(We have wrapped the long line.) We place the executable in the specified location and send the SIGHUP signal to inetd , telling it to reread its configuration file. The next step is to execute netstat to verify that a listening socket has been created on TCP port 9999.

 
 solaris %  netstat -na  grep 9999  *.9999 *.* 0 0 49152 0 LISTEN 

We then invoke the server from another host.

 
 linux %  telnet solaris 9999  Trying 192.168.1.20... Connected to solaris. Escape character is '^]'. Tue Jun 10 11:04:02 2003 Connection closed by foreign host. 

The /var/adm/messages file (where we have directed the LOG_USER facility messages to be logged in our /etc/syslog.conf file) contains the following entry:

 
 Jun 10 11:04:02 solaris daytimetcpsrv3[28724]: connection from 192.168.1.10.58145 


UNIX Network Programming Volume 1, Third Edition
Unix Network Programming, Volume 1: The Sockets Networking API (3rd Edition)
ISBN: 0131411551
EAN: 2147483647
Year: 2003
Pages: 441

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net