/* mini-inetd: Waits on a TCP socket, spawns a subprocess for each incoming connection to handle the connection. Can be used to test servers that expect to be launched from inetd. Copyright (C) 1997, 2000 Jamie Lokier. This file is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this file; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include #include #include #include #include #define PERROR(p) do { fprintf (stderr, "%s: %s: %s\n", argv [0], \ (p), strerror (errno)); exit (EXIT_FAILURE); } while (0) #define ERROR(e) do { fprintf (stderr, "%s: %s\n", argv [0], (e)); \ exit (EXIT_FAILURE); } while (0) void do_wait (void) { waitpid (-1, 0, WNOHANG); } int main (int argc, char ** argv) { struct protoent * proto; int s, port; if (argc < 4) { fprintf (stderr, "Usage: %s tcp-port executable argv0 args...\n", argv [0]); exit (EXIT_FAILURE); } proto = getprotobyname ("tcp"); if (proto == 0) PERROR ("getprotobyname"); s = socket (AF_INET, SOCK_STREAM, proto->p_proto); if (s == -1) PERROR ("socket"); { char * eptr; long lport = strtol (argv [1], &eptr, 0); if (*eptr == 0) { if (lport < 0 || lport > 65535) ERROR ("port number out of range"); port = htons (lport); } else { struct servent * serv = getservbyname (argv [1], "tcp"); if (serv == 0) ERROR ("unknown TCP service name"); port = serv->s_port; /* This is already in network byte order. */ } } { struct sockaddr_in addr; memset (&addr, 0, sizeof (addr)); addr.sin_family = AF_INET; addr.sin_port = port; if (bind (s, (struct sockaddr *) &addr, sizeof (addr)) != 0) PERROR ("bind"); } if (listen (s, 128) == -1) PERROR ("listen"); atexit (do_wait); while (1) { struct sockaddr addr; int addrlen = sizeof (addr); int fd = accept (s, &addr, &addrlen); int pid; if (fd == -1) PERROR ("accept"); waitpid (-1, 0, WNOHANG); /* We've got a connection in socket `fd'. Spawn a subprocess to handle it. */ pid = fork (); if (pid == -1) PERROR ("fork"); if (pid == 0) { if ((fd != 0 && dup2 (fd, 0) == -1)) ERROR ("dup2"); if ((fd != 1 && dup2 (fd, 1) == -1)) ERROR ("dup2"); if (fd != 0 && fd != 1) close (fd); close (2); execve (argv [2], argv + 3, __environ); PERROR ("execve"); } close (fd); } return EXIT_SUCCESS; }