/* netprint.c
      send stdin or named file to a network port. Assume IP address
      is the same one the tty session is coming from. Assume the
      port is 9100.
*/
 
#define PROGVERSION "netprint version 1.02"
 
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <fcntl.h>
#include <utmp.h>
#ifdef UTMPX
#include <utmpx.h>
#endif
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
 
#ifndef INADDR_NONE
#define INADDR_NONE 0xffffffff
#endif
 
#ifdef UTMPX_FILE
#define PATH UTMPX_FILE
#else
#ifdef _PATH_UTMP
#define PATH _PATH_UTMP
#else
#define PATH UTMP_FILE
#endif
#endif
 
typedef unsigned long in_addr_t;
 
int debugl;
 
extern  int h_errno;
 
main(ac,av)
int ac;
char    *av[];
{
    int     s;
    struct  sockaddr_in sin;
    int     c;
    struct  hostent *hp;
    struct  hostent he;
    char    *pmyaddr;
    /*unsigned long myaddr;*/
    in_addr_t myaddr;
    char    buf[1024];
    int     bufr,bufw;
    char    *hostname;
    int     port;
    int     eret;
    char    *iam;
#ifdef UTMPX
    struct utmpx u;
#else
    struct utmp u;
#endif
    FILE    *u_file;
    char    myhostname[100];
    char    mytty[100];
    char    *p;
    int     mypid;
    int     trycount = 5;
 
    iam = av[0];
    hostname = (char *)0;
    port = 9100;
    mypid = getpid();
 
#ifndef NODYNAMIC
    u_file = fopen(PATH, "r");
    strcpy(mytty, ttyname(1));
    p = &mytty[5];  /* past "/dev/" */
    if (u_file) {
       while (fread(&u, sizeof(u), 1, u_file)) {
          /*printf(u.ut_line); printf(inet_ntop(u.ut_addr_v6)); printf("\n\r");*/
          if (strcmp(u.ut_line, p) == 0 && u.ut_type == USER_PROCESS)
          {
#ifdef HAVEADDR6
             inet_ntop(AF_INET, u.ut_addr_v6, myhostname, sizeof(myhostname));
#else
             strcpy(myhostname, u.ut_host);
#endif
             hostname = myhostname;
             break;
          }
       }
       fclose(u_file);
    }
#endif    /* NODYNAMIC */
 
    while(ac>1) {
       av++;
       ac--;
       if (ac%2 != 0)
           break;
       if (strcmp(*av,"-d")==0) {
          debugl = atoi(*++av);
          ac--;
          if (debugl) {
             fprintf(stderr, "%s\n", PROGVERSION);
             fprintf(stderr,"debugl = %d\n",debugl);
           }
       } else if (strcmp(*av,"-h")==0) {
          hostname = *++av;
          ac--;
          if (debugl)
             fprintf(stderr,"hostname = %s\n",hostname);
       } else if (strcmp(*av,"-p")==0) {
          port = atoi(*++av);
          ac--;
          if (debugl)
             fprintf(stderr,"port = %d\n",port);
       }
    }
    if (ac!=1 || hostname==0 || port<0) {
       fprintf(stderr, "%s\n", PROGVERSION);
       fprintf(stderr,"usage: %s [-d n] -h hostname -p portnumber\n",iam);
       return(1);
    }
 
    eret=0;
 
    setbuf(stderr,NULL);
 
    /* try to resolve a numeric IP first */
    hp = &he;
    he.h_addr_list = &pmyaddr;
    pmyaddr = (char *)&myaddr;
#ifdef AF_INET6
    if (inet_pton(AF_INET6, hostname, hp->h_addr)) {
       hp->h_addrtype = AF_INET6;
       hp->h_length = 16;
       if (debugl)
          fprintf(stderr, "using address (IPv6) %s\n", hostname);
    } else
#endif
    if (inet_addr(hostname) != INADDR_NONE) {
#ifdef OLDAIX
       myaddr.s_addr = ((struct in_addr)inet_addr(hostname)).s_addr;
#else
       myaddr = inet_addr(hostname);
#endif
       hp->h_addrtype = AF_INET;
       hp->h_length = 4;
       /* if (debugl)
          fprintf(stderr, "using address (IPv4) %s\n", inet_ntoa((struct in_addr)(&myaddr)));  */
    } else
    {
       hp = gethostbyname(hostname);
/*       if (debugl && hp) {
 #ifdef AF_INET6
          inet_ntop(AF_INET, hp->h_addr, buf, sizeof(buf));
          fprintf(stderr,"gethostbyname()=%s\n",buf);
 #else
          fprintf(stderr,"gethostbyname()=%s\n",inet_ntoa(*(unsigned long *)hp->h_addr));
 #endif
       } */
       if (!hp) {
          herror(hostname);
          return(2);
       }
    }
 
    for (;;) {
       s=socket(AF_INET, SOCK_STREAM, 0);
       if (debugl)
          fprintf(stderr,"socket()=%d\n",s);
       if(s<0) {
          perror("Can't open socket");
          return(2);
       }
 
       memcpy( (char *)&sin.sin_addr.s_addr, hp->h_addr, hp->h_length);
       sin.sin_family = hp->h_addrtype;
       sin.sin_port = htons(port);
       if (debugl)
#ifdef AF_INET6
          fprintf(stderr,"sin.sin_addr.s_addr=%s\n",
             inet_ntop(sin.sin_family,&sin.sin_addr.s_addr,buf,sizeof(buf)));
#else
          fprintf(stderr,"sin.sin_addr.s_addr==%s\n",
             inet_ntoa(sin.sin_addr));
#endif
       c = connect(s,(struct sockaddr *)&sin,sizeof(sin));
       if (debugl)
          fprintf(stderr,"connect()=%d\n",c);
 
       if (c) {  /* failed to connect */
          if (debugl) {
             sprintf(buf,"Connect to port %d on %s",port,hostname);
             perror(buf);
          }
          close(s);
          if (--trycount == 0) /* try only 5 times */
             return(1);
          sleep(5);
       } else {
          break;
       }
    }
 
    if (fcntl(s, F_SETFL, fcntl(s,F_GETFL,0) & O_SYNC) == -1) {
       if (debugl)
          perror("fcntl(O_SYNC)");
    }
 
    while ((bufr = read(0,buf,sizeof(buf)))>0) {
       if (debugl)
          fprintf(stderr,"read()=%d\n",bufr);
       bufw = write(s,buf,bufr);
       if (debugl)
          fprintf(stderr,"write()=%d\n",bufw);
       if (bufr != bufw) {
          if (debugl)
             fprintf(stderr,"short write!\n");
          eret=2;
          break;
       }
    }
 
    close(s);
 
    return(0);
}
 
 
