3 * This file is part of httpd.
5 * 01/25/1996 Michael Temari <Michael@TemWare.Com>
6 * 07/07/1996 Initial Release Michael Temari <Michael@TemWare.Com>
7 * 12/29/2002 Michael Temari <Michael@TemWare.Com>
10 #include <sys/types.h>
11 #include <sys/ioctl.h>
20 #include <net/netlib.h>
22 #include <net/gen/in.h>
23 #include <net/gen/inet.h>
24 #include <net/gen/tcp.h>
25 #include <net/gen/tcp_io.h>
26 #include <net/gen/socket.h>
27 #include <net/gen/netdb.h>
31 _PROTOTYPE(static void release
, (int *fd
));
33 ipaddr_t myipaddr
, rmtipaddr
;
34 tcpport_t myport
, rmtport
;
36 char rmthostname
[256];
37 char rmthostaddr
[3+1+3+1+3+1+3+1];
41 nwio_tcpconf_t tcpconf
;
43 struct hostent
*hostent
;
45 /* Ask the system what our hostname is. */
46 if(gethostname(myhostname
, sizeof(myhostname
)) < 0)
47 strcpy(myhostname
, "unknown");
49 /* lets get our ip address and the clients ip address */
50 s
= ioctl(0, NWIOGTCPCONF
, &tcpconf
);
56 strcpy(rmthostname
, "??Unknown??");
57 strcpy(rmthostaddr
, "???.???.???.???");
61 myipaddr
= tcpconf
.nwtc_locaddr
;
62 myport
= tcpconf
.nwtc_locport
;
63 rmtipaddr
= tcpconf
.nwtc_remaddr
;
64 rmtport
= tcpconf
.nwtc_remport
;
66 /* Look up the host name of the remote host. */
67 hostent
= gethostbyaddr((char *) &rmtipaddr
, sizeof(rmtipaddr
), AF_INET
);
69 strncpy(rmthostname
, inet_ntoa(rmtipaddr
), sizeof(rmthostname
)-1);
71 strncpy(rmthostname
, hostent
->h_name
, sizeof(rmthostname
)-1);
73 strcpy(rmthostaddr
, inet_ntoa(rmtipaddr
));
75 rmthostname
[sizeof(rmthostname
)-1] = '\0';
80 static void release(fd
)
89 void daemonloop(service
)
93 struct nwio_tcpcl tcplistenopt
;
94 struct nwio_tcpconf tcpconf
;
95 struct nwio_tcpopt tcpopt
;
96 struct servent
*servent
;
98 int tcp_fd
, client_fd
, r
;
102 if((servent
= getservbyname(service
, "tcp")) == NULL
) {
106 p
= strtoul(service
, &end
, 0);
107 if(p
<= 0 || p
> 0xFFFF || *end
!= 0) {
108 fprintf(stderr
, "httpd: %s: Unknown service\n", service
);
111 port
= htons((tcpport_t
) p
);
113 port
= servent
->s_port
;
119 if((tcp_device
= getenv("TCP_DEVICE")) == NULL
)
120 tcp_device
= TCP_DEVICE
;
121 if ((tcp_fd
= open(tcp_device
, O_RDWR
)) < 0) {
122 fprintf(stderr
, "httpd: Can't open %s: %s",
123 tcp_device
, strerror(errno
));
124 if (errno
== ENOENT
|| errno
== ENODEV
131 tcpconf
.nwtc_flags
= NWTC_LP_SET
| NWTC_UNSET_RA
| NWTC_UNSET_RP
;
132 tcpconf
.nwtc_locport
= port
;
134 if (ioctl(tcp_fd
, NWIOSTCPCONF
, &tcpconf
) < 0) {
135 fprintf(stderr
, "httpd: Can't configure TCP channel",
141 tcpopt
.nwto_flags
= NWTO_DEL_RST
;
143 if (ioctl(tcp_fd
, NWIOSTCPOPT
, &tcpopt
) < 0) {
144 fprintf(stderr
, "httpd: Can't set TCP options",
150 if (client_fd
!= -1) {
151 /* We have a client, so start a server for it. */
154 tcpopt
.nwto_flags
= 0;
155 (void) ioctl(client_fd
, NWIOSTCPOPT
, &tcpopt
);
160 /* Create a pipe to serve as an error indicator. */
162 fprintf(stderr
, "httpd: pipe", strerror(errno
));
166 /* Fork twice to daemonize child. */
169 fprintf(stderr
, "httpd: fork", strerror(errno
));
178 fprintf(stderr
, "httpd: fork",
180 write(pfd
[1], &errno
, sizeof(errno
));
192 /* Break out of the daemon loop, continuing with
193 * the normal httpd code to serve the client.
201 r
= read(pfd
[0], &errno
, sizeof(errno
));
203 if (r
!= 0) goto bad
;
208 /* Wait for a new connection. */
209 tcplistenopt
.nwtcl_flags
= 0;
211 while (ioctl(tcp_fd
, NWIOTCPLISTEN
, &tcplistenopt
) < 0) {
212 if (errno
!= EAGAIN
) {
213 fprintf(stderr
, "httpd: Unable to listen: %s",
219 /* We got a connection. */
223 /* All is well, no need to stall. */
228 /* All is not well, release resources. */
232 /* Wait a bit if this happens more than once. */