home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume36 / port-lpr / part03 / unix-tcp.c < prev    next >
C/C++ Source or Header  |  1993-03-11  |  5KB  |  197 lines

  1. /*
  2.  * lpr interface for UNIX (i.e. BSD-ish) tcp
  3.  */
  4.  
  5. #include "common.h"
  6. #include <stdio.h>
  7. #include <ctype.h>
  8. #include <sys/types.h>
  9. #include <sys/stat.h>
  10. #include <pwd.h>
  11. #include <netdb.h>
  12. #include <sys/socket.h>
  13. #include <errno.h>
  14. #include <netinet/in.h>
  15.  
  16. #ifndef MAKE_EMAIL_ADDRESS
  17. #define MAKE_EMAIL_ADDRESS(buf,user,dom) sprintf (buf, "%s@%s", user, dom)
  18. #endif
  19.  
  20.  
  21. struct hostent *
  22. gethostbynameoraddr (hostname)
  23. char *hostname;
  24. {
  25.     if (isdigit (*hostname)) {
  26.     static struct hostent x;
  27.     static char *alias_list[1];
  28.     static unsigned long *addr_list[2];
  29.     static unsigned long ip_address;
  30.  
  31.     ip_address = inet_addr (hostname);
  32.  
  33.     addr_list[0] = &ip_address;
  34.     addr_list[1] = NULL;
  35.     alias_list[0] = NULL;
  36.  
  37.     x.h_name = hostname;
  38.     x.h_aliases = alias_list;
  39.     x.h_addrtype = AF_INET;
  40.     x.h_length = sizeof (unsigned long);
  41.     x.h_addr_list = (char **) addr_list;
  42.     return &x;
  43.     }
  44.     return gethostbyname (hostname);
  45. }
  46.  
  47. void sysdep()
  48. {
  49.     struct passwd *pwd;
  50.     char *p;
  51.     struct hostent *hp;
  52.     char *getenv ();
  53.  
  54.     gethostname (hostname, sizeof hostname);
  55.  
  56.     if (pwd = getpwuid (getuid ()))
  57.     strcpy (username, pwd->pw_name);
  58.     else {
  59.     fprintf (stderr, "lpr: system problem: can't get your username!\n");
  60.     exit (1);
  61.     }
  62.     endpwent ();
  63.  
  64.     hp = gethostbyname (hostname);
  65.     MAKE_EMAIL_ADDRESS(email_address, username, hp ? hp->h_name : hostname);
  66. }
  67.  
  68.  
  69. /*
  70.  * Allocate a socket and bind it to a local privileged port
  71.  * We have to be running set-uid to root to do this.
  72.  */
  73.  
  74. int
  75. get_priv_tcp_socket ()
  76. {
  77.     int fd;
  78.     int port;
  79.     struct sockaddr_in s;
  80.  
  81.     if ((fd = socket (AF_INET, SOCK_STREAM, 0)) == EOF) {
  82.     perror ("socket");
  83.     return EOF;
  84.     }
  85.     for (port = IPPORT_RESERVED-1; port > IPPORT_RESERVED / 2; port--) {
  86.     extern int errno;
  87.     s.sin_family = AF_INET;
  88.     s.sin_addr.s_addr = INADDR_ANY;
  89.     s.sin_port = htons (port);
  90.     if (bind (fd, (struct sockaddr *) &s, sizeof (s)) == 0)
  91.         return fd;
  92.     if (errno == EACCES) {
  93.         fprintf (stderr, "lpr warning: bind: cannot bind to privileged port\n");
  94.         return fd;
  95.     }
  96.     }
  97.     close (fd);
  98.     return EOF;
  99. }
  100.  
  101. /*
  102.  * Open a TCP connection to an lpd-server.
  103.  * This requires that this program be run set-uid to root in order to be able
  104.  * to bind a socket to a privileged port.
  105.  */
  106.  
  107. int
  108. open_lpd (server)
  109. char *server;
  110. {
  111.     int fd;
  112.     int i;
  113.     int last_connect_failed;
  114.     struct hostent *hp;
  115.     struct servent *sp;
  116.     struct sockaddr_in s;
  117.  
  118.     if (server == NULL || *server == '\0') {
  119.     fprintf (stderr, "lpr: no server host was specified.\n");
  120.     fprintf (stderr, "     Supply one with the -S option, or\n");
  121.     fprintf (stderr, "     by setting the LPD_SERVER environment variable\n");
  122.     return EOF;
  123.     }
  124.     if ((hp = gethostbynameoraddr (server)) == NULL) {
  125.     fprintf (stderr, "lpr: can't find network address for %s\n",
  126.          server);
  127.     fflush (stderr);
  128.     return EOF;
  129.     }
  130.  
  131.     s.sin_family = AF_INET;
  132.     if ((sp = getservbyname ("printer", "tcp")) == NULL)
  133.     s.sin_port = htons (515);
  134.     else
  135.     s.sin_port = sp->s_port;
  136.  
  137.     /*
  138.      * On some systems h_addr is a macro that is defined to be h_addr_list[0]
  139.      * On other (ancient) systems, h_addr is a member of the hostent structure.
  140.      * So if h_addr is defined as a macro, then we must have the list...
  141.      */
  142.  
  143. #ifdef h_addr
  144.     for (i = 0; hp->h_addr_list[i] ; ++i) {
  145.     fd = get_priv_tcp_socket ();
  146.     disable_special_privileges ();
  147.     if (fd < 0)
  148.         return EOF;
  149.     bcopy (hp->h_addr_list[i], &s.sin_addr, sizeof (s.sin_addr));
  150.     if (debug)
  151.         fprintf (stderr, "Trying %s...", inet_ntoa (s.sin_addr));
  152.     last_connect_failed = 0; /* "I'm ashamed of this." - SMK */
  153.     if (connect (fd, &s, sizeof s) == 0) {
  154.         if (debug)
  155.         fprintf (stderr, "open\n");
  156.         break;
  157.     }
  158.     else {
  159.         close (fd);        /* reuse fd */
  160.         if (debug)
  161.         perror ("");
  162.         last_connect_failed = 1;
  163.     }
  164.     }
  165.     if (last_connect_failed) {
  166.     perror ("connect");
  167.     return EOF;
  168.     }
  169. #else
  170.     fd = get_priv_tcp_socket ();
  171.     disable_special_privileges ();
  172.     if (fd < 0)
  173.     return EOF;
  174.     bcopy (hp->h_addr, (char *) &s.sin_addr, sizeof(s.sin_addr));
  175.     if (connect (fd, &s, sizeof s) < 0) {
  176.     perror ("connect");
  177.     close (fd);
  178.     return EOF;
  179.     }
  180. #endif
  181.  
  182.     max_net_read = max_net_write = 32767;
  183.     return fd;
  184. }
  185.  
  186. /*
  187.  * Turn off set-uid privileges.
  188.  * We have to be running set-uid to root in order to bind to a privileged
  189.  * port.  In order to minimize the security risk, this function is called
  190.  * from open_job() immediately after open_lpd() returns.
  191.  */
  192.  
  193. disable_special_privileges ()
  194. {
  195.     setuid (getuid ());
  196. }
  197.