home *** CD-ROM | disk | FTP | other *** search
- /* Public domain. */
-
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <sys/param.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <signal.h>
- #include "dupdup.h"
- #include "malloc.h"
- #include "errno.h"
- #include "username.h"
- #include "hostname.h"
- #include "portname.h"
- #include "env.h"
- #include "getopt.h"
- #include "authuser.h"
- #include "numfiles.h"
-
- #ifndef MAXHOSTNAMELEN
- #define MAXHOSTNAMELEN 64
- #endif
-
- static int flagdo931 = 1;
- static int flagverbose = 1;
- static struct sockaddr_in sa;
- static struct sockaddr_in saloc;
-
- static char errbuf[500];
- void die(n,s) int n; char *s;
- { if (flagverbose) fprintf(stderr,"tcpclient: fatal: %s\n",s); exit(n); }
- void dies(n,s,t) int n; char *s; char *t;
- { if (flagverbose) fprintf(stderr,"tcpclient: fatal: %s%s\n",s,t); exit(n); }
- void diep(n,s) int n; char *s;
- { if (flagverbose) sprintf(errbuf,"tcpclient: fatal: %s",s); perror(errbuf); exit(n); }
- void warnp(s) char *s;
- { if (flagverbose) sprintf(errbuf,"tcpclient: warning: %s",s); perror(errbuf); }
- void warnsp(s,t) char *s; char *t;
- { if (flagverbose) sprintf(errbuf,"tcpclient: warning: %s%s",s,t); perror(errbuf); }
-
- main(argc,argv,envp)
- int argc;
- char *argv[];
- char *envp[];
- {
- int t;
- int *d;
- int tdup;
- int numfiles;
- int i;
- static char tcplocal[200];
- static char tcpremote[300];
- int opt;
- int uid;
- char *uname;
- char lochost[MAXHOSTNAMELEN];
- struct in_addr locinaddr;
- int port;
- int locport;
- int dummy;
- char *ruser;
-
- locport = 0;
-
- while ((opt = getopt(argc,argv,"qQp:rR")) != EOF)
- switch(opt)
- {
- case 'q':
- flagverbose = 0; break;
- case 'Q':
- flagverbose = 1; break;
- case 'p':
- /* XXX: check that optarg is numeric? */
- locport = atoi(optarg);
- break;
- case 'r':
- flagdo931 = 1;
- break;
- case 'R':
- flagdo931 = 0;
- break;
- case '?':
- break; /*XXX*/
- default:
- break; /*XXX*/
- }
- argc -= optind; argv += optind;
-
- if (argc < 3)
- die(1,"need at least three arguments");
-
- uid = getuid();
- if (uid2username(uid,&uname) == -1) /* will never happen */
- die(2,"cannot figure out my own username");
-
- gethostname(lochost,sizeof(lochost));
- if (hostname2inaddr(lochost,&locinaddr) == -1)
- die(2,"cannot figure out my own hostname");
-
- if ((argv[0][0] == '0') && (argv[0][1] == 0))
- sa.sin_addr.s_addr = INADDR_ANY; /* special case "0" */
- else
- {
- if (hostname2inaddr(argv[0],&sa.sin_addr) == -1)
- dies(2,"cannot figure out hostname ",argv[0]);
- }
-
- if (portname2port(argv[1],&port,"tcp") == -1)
- dies(2,"cannot figure out portname ",argv[1]);
- port = port & 65535;
- sa.sin_port = htons((short) port);
-
- close(6);
- close(7); /* XXX: these have implications that should be documented */
-
- signal(SIGPIPE,SIG_IGN);
-
- numfiles = NUMFILES;
- d = (int *) malloc(numfiles * sizeof(int));
- if (!d)
- die(6,"cannot malloc");
- for (i = 0;i < numfiles;++i)
- d[i] = -1;
-
- if (env_init() == -1)
- die(11,"cannot init environment");
- if (env_put("PROTO=TCP") == -1)
- die(11,"out of memory putting PROTO into environment");
-
- t = socket(AF_INET,SOCK_STREAM,0);
- if (t == -1)
- diep(7,"cannot create client socket");
- sa.sin_family = AF_INET;
- if (locport)
- {
- /* attempt to bind to given local port */
- /* could do this in advance in all cases if we were desperate to
- get TCPLOCAL figured out as fast as possible */
- saloc.sin_family = AF_INET;
- saloc.sin_addr.s_addr = INADDR_ANY;
- saloc.sin_port = htons((short) locport);
- if (bind(t,&saloc,sizeof(saloc)) == -1)
- diep(9,"cannot bind to local port");
- }
- if (connect(t,&sa,sizeof(sa)) == -1)
- /* XXX: HRRFC says we should try alternate addresses */
- diep(9,"cannot connect to server");
- dummy = sizeof(saloc);
- if (getsockname(t,&saloc,&dummy) == -1)
- diep(9,"cannot figure out local connection address");
-
- locport = ntohs(saloc.sin_port);
-
- ruser = "";
- if (flagdo931)
- {
- ruser = auth_tcpuser((unsigned long) sa.sin_addr.s_addr
- ,(unsigned short) locport
- ,(unsigned short) port);
- if (!ruser)
- ruser = ""; /* XXX: any other suggestions? */
- }
-
- sprintf(tcplocal,"TCPLOCAL=%s@%s(%s):%d"
- ,uname
- ,inet_ntoa(locinaddr) /* could use saloc.sin_addr */
- ,lochost /* could use hostname of saloc.sin_addr */
- ,locport
- );
- if (env_put(tcplocal) == -1)
- die(11,"out of memory putting TCPLOCAL into environment");
- sprintf(tcpremote,"TCPREMOTE=%s@%s(%s):%d"
- ,ruser
- ,inet_ntoa(sa.sin_addr)
- ,argv[0] /* could do lookup instead, but why bother? */
- ,port
- );
- if (env_put(tcpremote) == -1)
- die(11,"out of memory putting TCPREMOTE into environment");
-
- /* XXX: fork? not necessary here */
-
- tdup = dup(t);
- if (tdup == -1)
- diep(10,"cannot dup connection to server");
-
- /* Now put t into descriptor 6 and tdup into descriptor 7. */
- /* XXX: should check that t and tdup are small enough */
- d[t] = 6;
- d[tdup] = 7;
- if (dupdup(d,numfiles) == -1)
- diep(10,"cannot dup connection to server");
-
- signal(SIGPIPE,SIG_DFL);
- execvp(argv[2],argv + 2);
- warnsp("cannot exec ",argv[2]);
- exit(1);
- }
-