/* This file is part of the zmail system, zrecv.c.  It contains all
 * the code necessary for the receiving part of zmail.
 *
 * Written by Barry Jaspan (bjaspan@athena.mit.edu), MIT Project Athena
 * and MIT Student Information Processing Board
 */

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/file.h>
#include <sys/signal.h>
#include <sys/param.h>
#include <netinet/in.h>
#include <ctype.h>
#include <netdb.h>

int	sock, silent;
char	*whoami;

char *upstr(s)
   char *s;
{
     char	*t;

     t=s;
     while (*s) {
	  if (islower(*s)) *s = toupper(*s);
	  s++;
     }
     return t;
}

int exit_cleanly()
{
     close(sock);
     exit(1);
}

void connect_to_server(name, port)
   char *name;
   int	port;
{
     struct sockaddr_in	server;
     struct hostent *hp, *gethostbyname();

     if ((sock = socket(AF_INET, SOCK_STREAM, 0))<0) {
	  if (! silent) {
	       fprintf(stderr,"%s: while opening socket: ",whoami);
	       perror(""); }
	  exit_cleanly(); }

     server.sin_family = AF_INET;
     if ((hp = gethostbyname(name))==0) {
	  if (! silent) {
	       fprintf(stderr,"%s: getting host: ",whoami);
	       perror("");
	  }
	  exit_cleanly(); }
     
     bcopy(hp->h_addr, &server.sin_addr, sizeof(struct in_addr));
     server.sin_port = htons(port);
     if (connect(sock, &server, sizeof(server))<0) {
	  if (! silent) {
	       fprintf(stderr,"%s: connecting to host: ",whoami);
	       perror("");
	  }
	  exit_cleanly(); }
}

void read_binary_file(bin)
   int	bin;
{
     char	file[BUFSIZ];
     int	length;
     
     while ((length=read(sock,file,BUFSIZ))>0)
	  if (write(bin,file,length)<length) {
	       if (! silent) fprintf(stderr,"%s: Writing file: ",whoami);
	       if (! silent) perror("");
	       exit_cleanly();
	  }
     close(bin);
}

int usage()
{
     printf("Usage: %s [-h host] [-p port] [-f outfile] [-n] [-s]\n",whoami);
     exit_cleanly();
}
     
main(argc, argv)
   int	argc;
   char	**argv;
{
     FILE 	*out;
     char	c, *host, *outfile;
     int	port, nocheck, arg, binfile, silent;

     whoami = argv[0];
     signal(SIGTERM, exit_cleanly);
     signal(SIGINT, exit_cleanly);
     host = outfile = '\0';
     port = nocheck = silent = 0;

     arg = 1;
     while (argv[arg]) {
	  switch (*(argv[arg]+1)) {
	  case 'h':
	       host = upstr(argv[arg+1]);
	       arg += 2;
	       break;
	  case 'p':
	       port = atoi(argv[arg+1]);
	       arg += 2;
	       break;
	  case 'n':
	       nocheck = 1;
	       arg += 2;
	       break;
	  case 'f':
	       outfile = argv[arg+1];
	       arg += 2;
	       break;
	  case 's':
	       silent = 1;
	       arg++;
	       break;
	  default:
	       if (silent) exit_cleanly();
	       fprintf(stderr,"%s: Unknown command argument: %s\n",whoami,
		       argv[arg]);
	       exit_cleanly();
	       break;
	  }
     }

     if ((! *host) | (! port)) {
	  if (! silent) usage();
	  exit_cleanly();
     }

     if (outfile[0]=='.') {
	  outfile[0] = '%';
	  if (! silent) fprintf(stderr,"%s: Changing output filename to: %s\n",
				whoami, outfile);
     }
     
     connect_to_server(host, port);
     if (*outfile) {
	  if ((binfile = open(outfile,(nocheck) ? (O_CREAT|O_WRONLY) :
			      (O_CREAT|O_EXCL|O_WRONLY), 0777))<0) {
	       if (! silent) fprintf(stderr,"%s: Cannot open file: %s\n",
				     whoami,outfile);
	       exit_cleanly();
	  }
     }
     else binfile = 1;
     
     if (! silent)
	  fprintf(stderr,"%s: Receiving a file from %s...\n",whoami,
		 upstr(host));
     read_binary_file(binfile);
     close(sock);
     if (! silent) fprintf(stderr,"Done.\n");
}
