#include <stdio.h>
#include <sys/types.h>
#include <sys/file.h>
#ifdef sun
#include <sys/fcntl.h>
#endif
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pwd.h>
#include <errno.h>
extern int errno;
#include "authuser.h"

main()
{
 int s;
 int t;
 int u;
 struct sockaddr_in sa;
 int salen;
 int localport;
 unsigned long in;
 unsigned short local;
 unsigned short remote;
 char *user;
 struct passwd *pw;
 int ok;

 ok = 1;

#define ZOT(x) { fprintf(stderr,"test: fatal: %s\n",x); exit(37); }

 s = socket(AF_INET,SOCK_STREAM,0);
 if (s == -1)
   ZOT("cannot create server socket")

 localport = 0; /* meaning pick a port, we don't care which */

 sa.sin_family = AF_INET;
 sa.sin_port = htons(localport);
 sa.sin_addr.s_addr = INADDR_ANY;

 if (bind(s,&sa,sizeof(sa)) == -1)
   ZOT("cannot bind server socket")

 salen = sizeof(sa);
 if (getsockname(s,&sa,&salen) == -1)
   ZOT("cannot get name of server socket")

 if (listen(s,5) == -1)
   ZOT("cannot listen for connections") /* XXX: impossible */

 u = socket(AF_INET,SOCK_STREAM,0);
 if (u == -1)
   ZOT("cannot create client socket")

 /* we could bind now if we wanted to pick a local port, or to know */
 /* our local port before connection */

 /* if connect() blocked then we'd never get a chance to accept() */
 if (fcntl(u,F_SETFL,O_NDELAY) == -1) /* XXX: FNDELAY? */
   ZOT("cannot set client socket to non-blocking mode")

 /* sa is already initialized above to the address we want to connect to */
 if (connect(u,&sa,sizeof(sa)) != -1)
   ; /* XXX: this is slightly screwy, though common, behavior */
 else
   if (errno != EINPROGRESS)
     ZOT("connect failed") /* XXX: should retry if EINTR */

 salen = sizeof(sa);
 if ((t = accept(s,&sa,&salen)) == -1)
   ZOT("cannot accept connection")

 printf("system says host is %s\n",inet_ntoa(sa.sin_addr));

 /* now let's see what the server can figure out about the client */

 if (auth_fd(t,&in,&local,&remote) == -1)
   ZOT("authuser cannot figure out connection information")

 if (sa.sin_addr.s_addr != in)
  {
   ok = 0;
   sa.sin_addr.s_addr = in;
  }
 printf("authuser says host is %s\n",inet_ntoa(sa.sin_addr));

 pw = getpwuid(getuid());
 if (pw)
   printf("system says username is %s\n",pw->pw_name);
 else
  {
   ok = 0;
   printf("system cannot figure out your username\n");
  }

 user = auth_tcpuser(in,local,remote);
 if (user)
   printf("authd says username is %s\n",user);
 else
  {
   ok = 0;
   printf("authd cannot figure out your username\n");
  }

 if (ok)
   if (!strcmp(user,pw->pw_name))
     printf("Everything looks okay to me.\n");
   else
     ok = 1;

 exit(!ok);
}
