home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume26 / port-lpr / part01 / unix-tcp.c < prev    next >
C/C++ Source or Header  |  1993-04-09  |  5KB  |  198 lines

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