-#endif
- for (;;) {
- int fromlen;
-
- f = socket(AF_INET, SOCK_DGRAM, 0, 0);
- if (f < 0) {
- perror("tftpd: socket");
- close(f);
- sleep(5);
- continue;
- }
- while (bind(f, (caddr_t)&sin, sizeof (sin), 0) < 0) {
- perror("tftpd: bind");
- close(f);
- sleep(5);
- continue;
+ /*
+ * Now that we have read the message out of the UDP
+ * socket, we fork and exit. Thus, inetd will go back
+ * to listening to the tftp port, and the next request
+ * to come in will start up a new instance of tftpd.
+ *
+ * We do this so that inetd can run tftpd in "wait" mode.
+ * The problem with tftpd running in "nowait" mode is that
+ * inetd may get one or more successful "selects" on the
+ * tftp port before we do our receive, so more than one
+ * instance of tftpd may be started up. Worse, if tftpd
+ * break before doing the above "recvfrom", inetd would
+ * spawn endless instances, clogging the system.
+ */
+ {
+ int pid;
+ int i, j;
+
+ for (i = 1; i < 20; i++) {
+ pid = fork();
+ if (pid < 0) {
+ sleep(i);
+ /*
+ * flush out to most recently sent request.
+ *
+ * This may drop some request, but those
+ * will be resent by the clients when
+ * they timeout. The positive effect of
+ * this flush is to (try to) prevent more
+ * than one tftpd being started up to service
+ * a single request from a single client.
+ */
+ j = sizeof from;
+ i = recvfrom(0, buf, sizeof (buf), 0,
+ (caddr_t)&from, &j);
+ if (i > 0) {
+ n = i;
+ fromlen = j;
+ }
+ } else {
+ break;
+ }