home *** CD-ROM | disk | FTP | other *** search
/ The Hacker's Encyclopedia 1998 / hackers_encyclopedia.iso / hacking / unix / portmsg.c < prev    next >
Encoding:
C/C++ Source or Header  |  2003-06-11  |  5.3 KB  |  188 lines

  1. /*
  2.  *    portmsg - generate a message on a port, then close connection
  3.  *
  4.  *    Usage:  portmsg file port
  5.  *
  6.  *        When a telnet client connects to the specified port, the
  7.  *        text from the file will be echoed to the user.  After a
  8.  *        short delay the connection will close.
  9.  *
  10.  * Derived from ftpd by Klaas @ {RUD, LPSwat}, original ftpd copyright
  11.  * message follows:
  12.  *
  13.  * Copyright (c) 1985, 1988, 1990 Regents of the University of California.
  14.  * All rights reserved.
  15.  *
  16.  * Redistribution and use in source and binary forms, with or without
  17.  * modification, are permitted provided that the following conditions
  18.  * are met:
  19.  * 1. Redistributions of source code must retain the above copyright
  20.  *    notice, this list of conditions and the following disclaimer.
  21.  * 2. Redistributions in binary form must reproduce the above copyright
  22.  *    notice, this list of conditions and the following disclaimer in the
  23.  *    documentation and/or other materials provided with the distribution.
  24.  * 3. All advertising materials mentioning features or use of this software
  25.  *    must display the following acknowledgement:
  26.  *      This product includes software developed by the University of
  27.  *      California, Berkeley and its contributors.
  28.  * 4. Neither the name of the University nor the names of its contributors
  29.  *    may be used to endorse or promote products derived from this software
  30.  *    without specific prior written permission.
  31.  *
  32.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  33.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  34.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  35.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  36.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  37.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  38.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  39.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  40.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  41.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  42.  * SUCH DAMAGE.
  43.  */
  44.  
  45. #include <stdio.h>
  46. #include <sys/types.h>
  47. #include <sys/stat.h>
  48. #include <sys/file.h>
  49. #include <sys/ioctl.h>
  50. #include <errno.h>
  51. #include <sys/socket.h>
  52. #include <netinet/in.h>
  53. #include <sys/param.h>
  54. #include <signal.h>
  55. #include <sys/wait.h>
  56.  
  57. wait_on_child()
  58. {
  59.     union wait status;
  60.  
  61.     while (wait3(&status, WNOHANG, (struct rusage *) 0) > 0)
  62.     ;
  63. }
  64.  
  65. lostconn()
  66. {
  67.     exit(1);
  68. }
  69.  
  70. main(argc, argv)
  71.         int argc;
  72.         char *argv[];
  73. {
  74.     int msgfd, fd, n;
  75.     struct stat statBuf;
  76.     int port;
  77.     char *msg;
  78.     int sockfd, newsockfd;
  79.     int addrlen; int opt;
  80.     struct sockaddr_in tcp_srv_addr;
  81.     struct sockaddr_in their_addr;
  82.  
  83.     if (argc != 3) {
  84.     fprintf(stderr, "Usage: portmsg file port\n");
  85.     exit(1);
  86.     }
  87.  
  88.     port = atoi(argv[2]);
  89.     if (port == 0) {
  90.     fprintf(stderr, "error: bad port number [%s]\n", argv[2]);
  91.     exit(1);
  92.     }
  93.     if ((msgfd = open(argv[1], O_RDONLY)) < 0) {
  94.     fprintf(stderr, "error: cannot open message file [%s]\n", argv[1]);
  95.     exit(1);
  96.     }
  97.     /* read the message */
  98.     fstat(msgfd, &statBuf);
  99.     if (statBuf.st_size <= 0) {
  100.     fprintf(stderr, "error: message file [%s] is empty\n", argv[1]);
  101.     exit(1);
  102.     }
  103.     msg = (char *)malloc(statBuf.st_size);
  104.     if (read(msgfd, msg, statBuf.st_size) != statBuf.st_size) {
  105.     fprintf(stderr, "error: cannot read message file [%s]\n", argv[1]);
  106.     exit(1);
  107.     }
  108.  
  109.     /* become a daemon */
  110.     switch(fork()) {
  111.     case -1:
  112.     fprintf(stderr, "error: can't fork\n");
  113.     exit(1);
  114.     case 0:
  115.     break;
  116.     default:
  117.     exit(0);
  118.     }
  119.     if (setpgrp(0, getpid()) == -1) {
  120.     fprintf(stderr, "error: can't change process group\n");
  121.     exit(1);
  122.     }
  123.     if ((fd = open("/dev/tty", O_RDWR)) >= 0) {
  124.     ioctl(fd, TIOCNOTTY, NULL);
  125.     close(fd);
  126.     }
  127.  
  128.     (void)signal(SIGCLD, wait_on_child);
  129.     bzero((char *) &tcp_srv_addr, sizeof(tcp_srv_addr));
  130.     tcp_srv_addr.sin_family = AF_INET;
  131.     tcp_srv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  132.     tcp_srv_addr.sin_port = htons(port);
  133.  
  134.     if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
  135.     fprintf(stderr, "can't create stream socket\n");
  136.     exit(-1);
  137.     }
  138.     opt = 1;
  139.     if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
  140.          (char *) &opt, sizeof(opt)) < 0) {
  141.     perror("setsockopt");
  142.     exit(1);
  143.     }
  144.     if (bind(sockfd, (struct sockaddr *)&tcp_srv_addr,
  145.          sizeof(tcp_srv_addr)) < 0) {
  146.     fprintf(stderr, "can't bind local address\n");
  147.     exit(-1);
  148.     }
  149.     listen(sockfd, 5);
  150.  
  151. main_again:
  152.     addrlen = sizeof (their_addr);
  153.     newsockfd = accept(sockfd, (struct sockaddr *) &their_addr, &addrlen);
  154.     if (newsockfd < 0) {
  155.     if (errno == EINTR)
  156.         goto main_again;
  157.     fprintf(stderr, "accept error\n");
  158.     exit(-1);
  159.     }
  160.  
  161.     switch(fork()) {
  162.     case -1:
  163.     fprintf(stderr, "server can't fork\n");
  164.     exit(-1);
  165.     case 0:
  166.     dup2(newsockfd, 0);
  167.     dup2(newsockfd, 1);
  168.     for (n = 3; n < NOFILE; n++)
  169.         close(n);
  170.     break;
  171.     default:
  172.     close(newsockfd);
  173.     goto main_again;
  174.     }
  175.  
  176.     /* daemon child arrives here */
  177.     (void)signal(SIGPIPE, lostconn);
  178.     (void)signal(SIGCHLD, SIG_IGN);
  179.  
  180.     fprintf(stdout, msg);
  181.     (void)fflush(stdout);
  182.     sleep(5);
  183.     exit(0);
  184. }
  185.  
  186.  
  187.  
  188.