/* Copyright (C) 1995, 1996 Zlatko Calusic <maverick@fly.cc.fer.hr>
This file is part of DownLoad, FTP Client

The DownLoad is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the Free
Software Foundation.

The DownLoad is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
more details.

You should have received a copy of the GNU General Public License along with
the DownLoad source; see the file COPYING.  If not, write to the Free
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */

#include "dl.h"

/* Global variables */

int logfd, master, control, data, local;			/* file descriptors */

int retry, nofatal;									/* REST */

int foreground, customlog, parsed, input, aborted;	/* flags */
int wildcard, cretry = MAXRETRY, custompass=0, customlogin=0;

char url[1024], host[256], path[1024], file[256];
char localhost[256], localaddr[4];					/* essential data */
char username[16], passwd[256], logfile[256], inputfile[256];
char login[16];

char buffer[BUFFER], *matching;

struct hostent *hptr;

struct sockaddr_in data_in;
int addrlen;

fd_set fdset;

struct timeval ttimer;

struct stat statbuf;

extern char *optarg;								/* getopt's globals */
extern int optind, opterr, optopt;

void fperror(char *string)
{
	perror(string);
	fputs("Aborting download ...\n", stderr);
	exit(-1);
}

void fatal(char *string)
{
	puts(string);
	exit(-1);
}

int getlocalhost(void)
{
	char string[256];
#ifdef AMIGA
	if(strcpy(localhost,getenv("HOSTNAME")))
		return OK;
	return ERROR;
#else
	if (!gethostname(localhost, 256))
	{
		if (!strchr(localhost, '.') && !getdomainname(string, 256) && string[0])
		{
			strcat(localhost, ".");
			strcat(localhost, string);
		}
		return OK;
	}
	else
		return ERROR;
#endif
}

void initialize(int argc, char **argv)
{
	char ch, *cptr;
	int printed = 0, usage = 0;

	strcpy(login,"anonymous");

	while ((ch = getopt(argc, argv, "fl:i:r:n:p:h")) != EOF)
		switch (ch)
		{
			case 'f':
				foreground++;
				break;
			case 'l':
				customlog++;
				strcpy(logfile, optarg);
				break;
			case 'i':
				input++;
				strcpy(inputfile, optarg);
				break;
			case 'r':
				if ((cretry = atoi(optarg)) <= 0)
				{
					printf("Retry count invalid, setting to %d.\n", MAXRETRY);
					cretry = MAXRETRY;
					printed = 1;
				}
				else if (cretry > 500)
				{
					puts("Retry count too big, setting to 500.");
					cretry = 500;
					printed = 1;
				}
				break;
			case 'p':
				custompass++;
				strcpy(passwd, optarg);
				break;
			case 'n':
				customlogin++;
				strcpy(login, optarg);
				break;
			case 'h':
			case '?':
			default:
				usage++;
				break;
		}
	if (argc == optind + 1)
		strcpy(url, argv[optind]);
	else if (argc == optind + 2)
	{
		strcpy(url, argv[optind]);
		strcat(url, ":");
		strcat(url, argv[optind + 1]);
	}
	else if (argc != optind || !input || usage)
	{
#ifdef AMIGA
		puts("Usage: dl [-i inputfile] [-r retrycnt] [-n login] [-p passwd] [-h] [URL]\n");
#else
		puts("Usage: dl [-f] [-l logfile] [-i inputfile] [-r retrycnt] [-p passwd] [-h] [URL]\n");
#endif
		puts("Command line switches:\n");
#ifndef AMIGA
		puts("         -f           download in the foreground");
		puts("         -l logfile   custom logfile name (works in the background)");
#endif
		puts("         -i inputfile load URLs from the inputfile");
		puts("         -r retrycnt  retry count (default 50, max 500)");
#ifdef AMIGA
		puts("         -p passwd    custom (anonymous) password");
		puts("         -n login     custom login");
#else
		puts("         -p passwd    custom anonymous password");
#endif
		puts("         -h           this help\n");
		puts("URL specification (wildcards are allowed):\n");
		puts("         hostname:pathname");
		puts("         hostname pathname");
		puts("         ftp://hostname/pathname\n");
		exit(0);
	}
	if (!printed)
		printf("Retry count set to %d%s", cretry, cretry == 50 ? " (default).\n" : ".\n");
	if (foreground && customlog)
		puts("Ignoring -l switch, program is running in the foreground.");
	if (!getlocalhost() || !(hptr = gethostbyname(localhost)))
		fatal("Can't resolve local hostname, exiting ...");
	memcpy(localaddr, hptr->h_addr_list[0], 4);
#ifdef AMIGA
	if(!(cptr=getenv("USER")))
		cptr = "unknown";
#else
	if (!(cptr = cuserid(NULL)))
		cptr = "unknown";
#endif
	strcpy(username, cptr);
	if (!custompass)
	{
		strcpy(passwd, cptr);
		strcat(passwd, "@");
		strcat(passwd, localhost);
	}

	printf("Using %s as %s password.\n", passwd, login);

	return;
}

int main(int argc, char **argv)
{
	printf("%s v%s by %s %s, %s\n", PROGRAM, VERSION, AUTHOR, EMAIL, DATE);
#ifdef AMIGA
	printf("Ported to Amiga by Niksa Franceschi <nfrances@zems.fer.hr>, 24 Jul 1996\n");
#endif
	sleep(1);
	initialize(argc, argv);
	fflush(stdout);
#ifndef AMIGA
	if (!foreground)
	{
		int i = 0;
		pid_t pid;

		if (!customlog)
		{
#ifdef AMIGA
			sprintf(logfile, "dl_log.%s", username);
#else
			sprintf(logfile, "/tmp/dl_log.%s", username);
#endif
			while (stat(logfile, &statbuf) == 0) {
#ifdef AMIGA
				sprintf(logfile, "dl_log.%d", ++i);
#else
				sprintf(logfile, "dl_log.%s.%d", username, ++i);
#endif
			}
		}
		if ((logfd = open(logfile, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0)
			fatal("Can't open log file, exiting ...");
#ifndef AMIGA
		dup2(logfd, 2);
#endif
		close(logfd);
		fputs("****************************************************************\n", stderr);
		fprintf(stderr, "Log file generated by %s v%s\n", PROGRAM, VERSION);
		fprintf(stderr, "Send bug reports to %s %s\n", AUTHOR, EMAIL);
#ifdef AMIGA
		fprintf(stderr, "Ported  to Amiga by Nick <nfrances@zems.fer.hr>\n");
#endif
		fputs("****************************************************************\n", stderr);
		printf("Log file is %s\n", logfile);
		signal(SIGCLD, SIG_IGN);
		switch ((pid = fork()))
		{
			case -1:
				fatal("Fork failed, try running in the foreground ...");
			case 0:
				sleep(2);
				setsid();
				break;
			default:
				printf("Continuing in the background (pid %d) ...", (int) pid);
				fflush(stdout);
				sleep(1);
				puts("\n");
				exit(0);
		}
	}
	else
		dup2(1, 2);
#endif
	if (!input)
		download();
	else
	{
		FILE *inputfp;

		if (!(inputfp = fopen(inputfile, "r")))
		{
			fputs("Can't open input file, exiting ...\n", stderr);
			exit(-1);
		}
		if (argc == optind + 1)
			download();
		while (fgets(url, 256, inputfp))
		{
			char *cptr;

			if ((cptr = strchr(url, '\n')))
				*cptr = 0;
			download();
		}
		fclose(inputfp);
	}
	exit(0);
}

int download(void)
{
	char *current;

	aborted = parsed = wildcard = 0;
	current = NULL;
	fprintf(stderr, "\nDOWNLOAD -> [%s]\n", url);
	for (retry = 1; retry <= cretry; retry++)
	{
		if (aborted)
			return ERROR;
		if (!parsed && !parse())
		{
			fputs("Error parsing hostname and/or pathname, aborting ...\n", stderr);
			return ERROR;
		}
		sleep(5);
		fputc('\n', stderr);
		if (!establish_connection())
			continue;
		if (!ftprequest("USER %s\r\n", login) || !ftprequest("PASS %s\r\n", passwd))
			continue;
		if (*path)
			if (!ftprequest("CWD %s\r\n", path))
				continue;
		if (!wildcard && (strchr(file, '*') || strchr(file, '?') || strchr(file, '[')) && !get_list())
			continue;
		if (!ftprequest("TYPE I\r\n", NULL))
			continue;
next_file:
		if (!retrieve_file())
			continue;
		if (wildcard && (current = strtok(NULL, "\r")))
		{
			strcpy(file, current);
			retry = 1;
			goto next_file;
		}
		ftprequest("QUIT\r\n", NULL);
		return OK;
	}
	fprintf(stderr, "Maximum retry count reached (%d), aborting ...\n", cretry);
	return ERROR;
}
