/*      Get and Resume Elite EDition source code


Get and Resume Elite EDition (GREED)
Copyright (C) 1999  Anoakie Turner

This program 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; either version 2 of the License, or
(at your option) any later version.

This program 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 this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

For more information on the GPL, please go to:
http://www.gnu.org/copyleft/gpl.html


        Contact:  Anoakie Turner
                  Anoakie.Turner@asu.edu

                  13240 N. 94th Pl.
                  Scottsdale, AZ 85260
*/


/*
**  To compile, use gcc -O2 -Wall -o greed greed.c
**
**
**  To compile under any non linux OS, use:
**  gcc -O2 -Wall -lsocket -lxnet -o greed greed.c
*/


#include "main.h"
#ifdef __riscos__
#include "riscos.h"
#endif /* __riscos__ */


int CHECKIN;
int STDIN;
#ifndef __riscos__
int TESTFILES;
int FORK;
int BACKGROUND;
#endif /* !__riscos__ */
int IMPORT_GR;
int RECURSE;
int RESUMES_LEFT;
int RESUME;
int NEWRC;
char* GR_FILE;

NODE *curr;

long ROLLBACK;
int TIMEOUT_SEC;
int MINSPEED;
long FTP_WAIT_TIME;
int OUTPUT_LEVEL;
int REFERRER;
int WAIT_RETRY;
bool STDOUT;
bool NOSIZE;
int DEBUG;
int CALL_ME;
char *CALL_ADDR;
char *PROXY;
char *PROXYPORT;
char *DEFAULT_DIR;
int dlstat;
long dldots;
struct sockaddr_in address;
unsigned int dport;
time_t start, end;
fd_set testfds;
char REF[1024];

NODE *list;
NODE *curr;

#ifdef USE_GTK
int filedes[2];
FILE *out, *in;
#endif


void Command (int argc, char *argv[]);
void Stdin ();
void File ();
void GRFile ();
void MailNotifyFinish();
void MailNotify(URLp URL, int valid);
void StartDownload ();


int main (int argc, char *argv[])
/*************************************
**	int main (int, char*)
**
** main() function.
*************************************/
{	int i = 1;
	list = malloc(sizeof(NODE));
	curr = list;
	curr->next = NULL;
	signal(SIGPIPE, SIG_IGN);

	/* Sets default global variables */
	RESUME = 1;
	CHECKIN = 1;
	STDIN = 0;
	FTP_WAIT_TIME = 0;
	OUTPUT_LEVEL = 5;
	STDOUT = 0;
	ROLLBACK = 4096;
	TIMEOUT_SEC = 300;
	MINSPEED = 0;
	REFERRER = 1;
#ifdef __riscos__
        __riscosify_control = __RISCOSIFY_NO_PROCESS;
#else
	TESTFILES = 0;
	FORK = 0;
	BACKGROUND = 0;
#endif /* !__riscos__ */
	IMPORT_GR = 0;
	WAIT_RETRY = 10;
	DEBUG = 0;
	RECURSE = 0;
	CALL_ME = 0;
	RESUMES_LEFT = 0;
	NEWRC = 0;


#ifdef USE_GTK
	gtk_init(&argc, &argv);

	CreateMainWindow();
#endif

	/* Parses the arguments in argv for switches */
	for (i = 1; i < argc; i ++)
		Switches(i, argv);

	/* Reads in configuration file and resets some globals */
	Proxy(NEWRC);

	/* Prints out Version info */
	if (OUTPUT_LEVEL > 0)
		printf("%s  [Get and Resume Elite EDition] - By "
			"Anoakie Turner\r\n\n", CURRENT_VERSION);

#ifndef __riscos__
	/* If the background switch was switched, it forks into the background
		and exits the parent */
	if (BACKGROUND)
	{	OUTPUT_LEVEL = 0;
		TESTFILES = 0;
		if (fork() != 0)	/* If I am the parent */
		{	printf("Forking into background mode!\n");
			exit(0);
		}
	}
#endif /* !__riscos__ */

	/* Parses the URLS in argv */
	if (argc > 1)
		Command (argc, argv);

	/* Parses the URLS read from greed.in */
	if (CHECKIN)
		File ();

	/* Parses the URLS read from a standard GetRight file */
	if (IMPORT_GR)
		GRFile ();

	/* Parses the URLS read in from the standard input */
	if (STDIN)
		Stdin ();

#ifdef USE_GTK
	gtk_main();
#else
	StartDownload ();
#endif

	/* If everything goes well, then exit with EXIT_SUCCESS */
	return(EXIT_SUCCESS);
}


NODE *InsertURL (char *U, int recurse)
/**********
**       **
**  NEW  **
**       **
**********/
{	NODE *ptr = list;
	while (ptr->next != NULL)
		ptr = ptr->next;
	ptr->next = malloc(sizeof(NODE));
	ptr = ptr->next;
	ptr->URL.name = U;
	ptr->URL.recurse = recurse;
#ifdef USE_GTK
	ptr->URL.pid = -1;
#endif
	ptr->next = NULL;
	return ptr;
}


#ifdef USE_GTK
void RemoveURL (char *U)
/*************************************
**  void RemoveURL (char *)
**
**  Removes URL from list.
**  Written by Bruno Barberi Gnecco
**************************************/
{	NODE *prev = list, *ptr = list->next;
	while (ptr != NULL) {
		if (ptr->URL.name == NULL)
		{	/* avoid segfault */
			message_box("ERROR", "Found NULL URL.name in RemoveURL.\n"
				"Please report this bug, with the file queue\n"
				"and which one you tried to delete.\n"
				"The application is unstable now. You should quit.");
			return;
		}
		if (strcmp(ptr->URL.name, U) == 0)
			break;
		prev = ptr;
		ptr = ptr->next;
	}
	if (ptr == NULL)
	{	message_box("Error", "Not in list!");
		return;
	}
	prev->next = ptr->next;
	free(ptr->URL.name);
	free(ptr);
}
#endif


void PrintList ()
/**********
**       **
**  NEW  **
**       **
**********/
{	NODE *ptr = list->next;
	while (ptr != NULL)
	{	printf("%s\n", ptr->URL.name);
		ptr = ptr->next;
	}
	printf("\n\n");
}


void Command (int argc, char *argv[])
/*************************************
**	void Command (URLp, int, char*)
**
** Pre:  argc == the number of elements in argv.
** Post: Attempts to retrieve the URLs in argv.
*************************************/
{	int i;
	for (i = 1; i < argc; i ++)
		if (argv[i][0] != '-')
			InsertURL(argv[i], RECURSE);
}


void Stdin ()
/*************************************
**	void Stdin (URLp)
**
** Post: Attempts to retrieve the URLs from STDIN.
** NOTE: currently doesn't support FORK!
*************************************/
{
#ifndef __riscos__
	char *buffer;
	int result;
	buffer = malloc(4096);

	printf("Waiting for input...\n");
	result = scanf("%s", buffer);
	while(result != EOF)
	{
		InsertURL(buffer, RECURSE);
		buffer = malloc(4096);
		result = scanf("%s", buffer);
	}
#else /* __riscos__ */
        /* whatever the above may do on Linux, it doesn't work on RISC OS */
        #define BUF_SIZE 4096
        char *p, *buffer;
        buffer = malloc(BUF_SIZE);

        printf("Waiting for input...\n");
        while (fgets(buffer, BUF_SIZE, stdin)) {
          p = strtok(buffer, " \t\r\n");
          while (p) {
            InsertURL(p, RECURSE);
            p = strtok(NULL, " \t\r\n");
          }
          buffer = malloc(BUF_SIZE);
        }
#endif /* __riscos__ */
}


void File ()
/*************************************
**	void File (URLp)
**
** Post: Attempts to retrieve the URLs from greed.in.
** NOTE: currently doesn't support FORK!
*************************************/
{	FILE *GD;
	int i;
	char *buffer;

	buffer = malloc(4096);
	GD = fopen("greed.in", "r");
	i = 0;


	if (GD != NULL)
	{	while(!feof(GD))
		{	fread(buffer + i, 1, 1, GD);

			/* If we hit a space or return in the buffer then
			   we have a supposed URL! */
			if(buffer[i] == ' ' || buffer[i] == '\n')
			{	buffer[i] = '\0';
				InsertURL(buffer, RECURSE);
				buffer = malloc(4096);

				i = 0;
			}
			else
				i++;
		}
		unlink("greed.in");

		fclose(GD);
	}
}


void GRFile ()
/*************************************
**	void GRFile ()
**
** Post: Attempts to retrieve the URLs from a standard .GRX file.
** NOTE: currently doesn't support FORK!
*************************************/
{	FILE *GD = fopen(GR_FILE, "r");
	int i = 0;
	char *buffer = malloc(4096);

	if (GD != NULL)
	{	while(!feof(GD))
		{	fread(buffer + i, 1, 1, GD);

		/* If we hit a '\n' or return in the buffer and it doesn't
		   start with a '/', then we have a supposed URL! */
			if(buffer[0] != '/' && (buffer[i] == '\r' || buffer[i] == '\n'))
			{	buffer[i+1] = '\0';
				if (strstr(buffer, "URL: ") != NULL &&
					strstr(buffer, "PageURL: ") == NULL)
				{	buffer[i] = '\0';

					InsertURL(buffer, RECURSE);
					buffer = malloc(4096);

					printf("**** %s ****",curr->URL.name);
				}
				else if (strstr(buffer, "PageURL: ") != NULL)
				{	buffer[i] = '\0';
					strcpy(REF, buffer + 15);
				}
				else if (buffer [0] == '\r' || buffer[0] == '\n')
					i = 0;
				i = 0;
			}
			else
			{	i++;
				if (buffer[i - 1] == '\r' || buffer[i - 1] == '\n')
					i = 0;
			}
		}
		fclose(GD);
	}
}


#ifndef USE_GTK
void StartDownload ()
{
#ifndef __riscos__
	int j;
	int status = 0;
	pid_t childpid = 0;
#endif /* !__riscos__ */
	curr = list->next;

#ifndef __riscos__
	if (FORK)
	{	for (j = 1; j < FORK + 1 && !status && curr->next != NULL; j++)
		{	childpid = fork();
			if (childpid == 0)
			{	status = 1;
				curr = curr->next;
			}
		}
	}
#endif /* !__riscos__ */

	while (curr != NULL)
	{	if(Parse(&curr->URL))
			DownloadLoop(&curr->URL);
		else if(OUTPUT_LEVEL > 0)
			printf("Unable to parse %s", curr->URL.name);
#ifndef __riscos__
		for (j = 0; j < FORK && curr->next != NULL; j++)
			curr = curr->next;
#endif /* !__riscos__ */

		curr = curr->next;
	}

	/* If it's the child, then it exits, else it waits until the other
		children have finished what they are doing */
#ifndef __riscos__
	if (!childpid)
	{
	  if (CALL_ME && !FORK)
#else /* __riscos__ */
	  if (CALL_ME)
#endif /* __riscos__ */
			MailNotifyFinish();
		if (OUTPUT_LEVEL > 0)
			printf("Exiting...\n");
		fflush(NULL);
		exit(EXIT_SUCCESS);
#ifndef __riscos__
	}
	if (childpid == wait(&status) && OUTPUT_LEVEL > 0)
		printf("Waiting for children processes to finish downloading\n");
	while(childpid == wait(&status) && wait(&status) != -1)
		if((childpid == -1) && (errno != EINTR))
			break;
#endif /* !__riscos__ */
}
#endif



void DownloadLoop (URLp URL)
/*************************************
**	void DownloadLoop (URLp)
**
** Pre:  URL has been Parse()'d
** Post: Connects to server and downloads the file
*************************************/
{	int ARCHIVES;

	while(URL->retry == 1 /* || (RESUMES_LEFT != 0 && !URL->done && URL->retry) */)
	{	URL->done = 0;
		ARCHIVES = 0;
		if (RESUMES_LEFT > 0)
			RESUMES_LEFT --;

		if (Connect(URL))
		{	FD_ZERO(&testfds);
			FD_SET(URL->sockfd, &testfds);
			if ((URL->protocol == FTP && ReadFTPListing(URL)) ||
				(URL->protocol == HTTP && ReadHTTPHeader(URL)))
			{	start = time((time_t *)0);
				end = time((time_t *)0);
				FD_ZERO(&testfds);
				FD_SET(URL->sockfd, &testfds);
				while (!URL->done) {
					Download(URL);
				}
#ifdef __riscos__
                                if (filetype)
                                    set_type(URL->filename, filetype);
#endif /* __riscos__ */
			}
		}

#ifndef USE_GTK
		if (OUTPUT_LEVEL > 0)
			printf("\n");
#endif

		close (URL->sockfd);

		if (URL->retry == 1 || (RESUMES_LEFT != 0 && !URL->done))
		{	if (OUTPUT_LEVEL > 1)
#ifdef USE_GTK
				fprintf(out, "%d: Retrying in %d seconds...\n\n",
					URL->pid, WAIT_RETRY);
#else
				printf("Retrying in %d seconds...\n\n", WAIT_RETRY);
#endif
			sleep(WAIT_RETRY);
#ifndef __riscos__
		} else if (TESTFILES)
		{	if (strstr(strrchr(URL->filename, '.'), "gz") || strstr(strrchr(URL->filename, '.'), "tgz"))
			{	strcpy(COMMAND, "gzip -t ");
				ARCHIVES = 1;
			} else if (strstr(strrchr(URL->filename, '.'), "tar"))
			{	strcpy(COMMAND, "tar -t ");
				ARCHIVES = 1;
			} else if (strstr(strrchr(URL->filename, '.'), "zip"))
			{	strcpy(COMMAND, "unzip -t ");
				ARCHIVES = 1;
			} else if (strstr(strrchr(URL->filename, '.'), "arj"))
			{	strcpy(COMMAND, "unarj t ");
				ARCHIVES = 1;
			} else if (strstr(strrchr(URL->filename, '.'), "ace"))
			{	strcpy(COMMAND, "unace -t ");
				ARCHIVES = 1;
			} else if (strstr(strrchr(URL->filename, '.'), "rar"))
			{	strcpy(COMMAND, "unrar -t ");
				ARCHIVES = 1;
			} else if (strstr(strrchr(URL->filename, '.'), "bz2"))
			{	strcpy(COMMAND, "bzip2 -t ");
				ARCHIVES = 1;
			} else if (strstr(strrchr(URL->filename, '.'), "rpm"))
			{	strcpy(COMMAND, "rpm --nopgp --checksig ");
				ARCHIVES = 1;
			}

			if (ARCHIVES)
				if(system(strcat(COMMAND, URL->filename)) == 0)
#ifdef USE_GTK
				{	fprintf(out, "%d: Saving as %s", URL->pid,
						URL->filename);
#else
				{	printf("**** %s is a valid archive!\n\n\n", URL->filename);
#endif
					if (CALL_ME)
						MailNotify(URL,1);
				} else
#ifdef USE_GTK
				{	fprintf(out, "%d: %s has errors", URL->pid,
						URL->filename);
#else
				{	printf("!!!! %s HAS ERRORS!!!\n\n\n", URL->filename);
#endif
					if (CALL_ME)
						MailNotify(URL,0);
				} else if (CALL_ME)
					MailNotify(URL,-1);
#endif /* !__riscos__ */
		}
	}
}


void MailNotifyFinish()
/*************************************
**    void MailNotify(URLp URL, int valid)
**
** Pre:  downloading finished
** Post: a mail is sent
**	Written by Eric Gaudet.
*************************************/
{	FILE *fp;
	char tmpstrmail[1024];
#ifdef __riscos__
	char tmpname[256];
#endif /* __riscos__ */
	NODE *ptr = list->next;

	if (OUTPUT_LEVEL > 6)
#ifdef USE_GTK
		message_box("Mail", "Sending mail");
#else
		printf("Sending mail\n");
#endif

#ifndef __riscos__
	sprintf(tmpstrmail,"mail -s \"[GREED] Your files have been downloaded\" %s > /dev/null", CALL_ADDR);
	fp=popen(tmpstrmail,"w");
#else /* __riscos__ */
	tmpnam(tmpname);
	sprintf(tmpstrmail,"mail -s \"[GREED] Your files have been downloaded\" %s < <Wimp$ScrapDir>.%s > null:", CALL_ADDR, tmpname+5);
        fp=fopen(tmpname,"w");
#endif /* __riscos__ */

	fprintf(fp,"You're download is complete!\nFiles retrieved:\n");
	while (ptr != NULL)
	{	if (ptr->URL.filename == NULL)
			fprintf(fp,"* From the directory: %s\n", ptr->URL.name);
		else
			fprintf(fp,"> %s (%ld bytes)\n", ptr->URL.filename, ptr->URL.ltotal);
		ptr = ptr->next;
	}
	fprintf(fp,"\n\n");

	fprintf(fp,"\n%s  [Get and Resume Elite EDition] - By "
		"Anoakie Turner\r\n", CURRENT_VERSION);
#ifndef __riscos__
	pclose(fp);
#else /* __riscos__ */
        fclose(fp);
	system(tmpstrmail);
	remove(tmpname);
#endif /* __riscos__ */
}

void MailNotify(URLp URL, int valid)
/*************************************
**    void MailNotify(URLp URL, int valid)
**
** Pre:  downloading finished
** Post: a mail is sent
**	Written by Eric Gaudet.
*************************************/
{	FILE *fp;
	char tmpstrmail[1024];
#ifdef __riscos__
	char tmpname[256];
#endif /* __riscos__ */

	if (OUTPUT_LEVEL > 6)
#ifdef USE_GTK
		message_box("Mail", "Sending mail");
#else
		printf("Sending mail\n");
#endif

	if (URL)
	{
#ifndef __riscos__
		sprintf(tmpstrmail,"mail -s \"[GREED] %s downloaded\" %s > /dev/null", URL->filename,CALL_ADDR);
		fp=popen(tmpstrmail,"w");
#else /* __riscos__ */
		tmpnam(tmpname);
		sprintf(tmpstrmail,"mail -s \"[GREED] %s downloaded\" %s < <Wimp$ScrapDir>.%s > null:", URL->filename, CALL_ADDR, tmpname+5);
        	fp=fopen(tmpname,"w");
#endif /* __riscos__ */

		switch (valid)
		{	case 1:
				fprintf(fp,"The following archive has been sucessfully downloaded and tested :\n");
				break;
			case 0:
				fprintf(fp,"The following archive has been downloaded, but appears to be invalid :\n");
				break;
			default:
				fprintf(fp,"The following file has been downloaded :\n");
				break;
		}
		fprintf(fp,"%s (%ld bytes)\n", URL->filename, URL->ltotal);
	}
	else
	{
#ifndef __riscos__
		sprintf(tmpstrmail,"mail -s \"[GREED] running\" %s > /dev/null",CALL_ADDR);
		fp=popen(tmpstrmail,"w");
#else /* __riscos__ */
		tmpnam(tmpname);
		sprintf(tmpstrmail,"mail -s \"[GREED] running\" %s < <Wimp$ScrapDir>.%s > null:", CALL_ADDR, tmpname+5);
        	fp=fopen(tmpname,"w");
#endif /* __riscos__ */
	}

	fprintf(fp,"\n%s  [Get and Resume Elite EDition] - By "
		"Anoakie Turner\r\n", CURRENT_VERSION);
#ifndef __riscos__
	pclose(fp);
#else /* __riscos__ */
        fclose(fp);
	system(tmpstrmail);
	remove(tmpname);
#endif /* __riscos__ */
}


void SendBug()
/*************************************
*************************************/
{	FILE *fp;
	char *buffer;
	char mail[64000];
	char email[600];
	char tmpstrmail[1024];
	int result;
	buffer = mail;


	printf(
"*** IMPORTANT ***\nBefore you try to send mail, make SURE you have sendmail set up correcly!!!\n"
"If not, the mail will"
" never get to me!\nIf you don't think you have sendmail set up or if you're not really sure (or if you run RedHat or"
" Mandrake),\nthen just send it with a regular e-mail program!\nThis is only for people who know what they are"
" doing!\nA copy of this e-mail will be mailed to yourself for verification that the mail was sent...\nIf you don't"
" get it, then you don't have sendmail installed\ncorrectly and you'll need to send me the bug through a regular"
" e-mail program!\n***\n\n");
	printf("E-mail address: ");
	result = scanf("%s", email);
	printf("Please describe the bug as well as you can, how it happened, if it's reproducable, "
		"what OS you are running, what compiler you're using, and any other in"
		"formation that will help me find and remove this bug from future versions of greed."
		"\n\nPress CTRL-D on a blank line when finished.\n****\n\n");
	while(result != EOF)
	{	result = scanf("%s", buffer);
		buffer += strlen(buffer);
		buffer[0] = ' ';
		buffer ++;
		buffer[0] = '\0';
	}

#ifndef __riscos__
	sprintf(tmpstrmail,"mail -s \"[GREED] BUG REPORT! [GREED]\" %s > /dev/null", "Anoakie.Turner@asu.edu");
#else /* __riscos__ */
	sprintf(tmpstrmail,"mail -s \"[GREED] BUG REPORT! [GREED]\" %s > null:", "Anoakie.Turner@asu.edu");
#endif /* __riscos__ */
	fp=popen(tmpstrmail,"w");

	fprintf(fp,"E-mail from: %s\r\n\r\n", email);
	fprintf(fp,"Problem:\n%s", mail);
	fprintf(fp,"\n\n");

	fprintf(fp,"\n%s  [Get and Resume Elite EDition] - By "
		"Anoakie Turner\r\n", CURRENT_VERSION);
	printf("\n\nThank you for reporting this bug!  Without the help of the many GREED users, "
		"GREED wouldn't be as great as it is now!\nExiting...\n\n");
	pclose(fp);
}


void Switches (int i, char *argv[])
/*************************************
**	void Switches (int, char*)
**
** Post: Parses strings in argv and set global variables accordingly.
*************************************/
{	if (argv[i][0] == '-')
	{	switch (argv[i][1])
		{	case '*': /* For developpers only : DO NOT print in usage. */
				printf("*** Debug Info Mode On\n");
				DEBUG=1;
				break;
			case '0':
				RESUME = 0;
				break;
			case 'N':
			case 'n':
				argv[i] = GGR;
				break;
			case 'M':
			case 'm':
				CALL_ME = 1;
				CALL_ADDR = argv[i] + 2;
				printf("%s will be notified by mail\n", CALL_ADDR);
				/* MailNotify(0,1); */
				break;
			case 'O':
			case 'o':
				if (argv[i][2] >= '0' || argv[i][2] <= '9')
					OUTPUT_LEVEL = argv[i][2] - '0';
				break;
			case 'R':
			case 'r':
				if (argv[i][2] == '\0')
					REFERRER = 0;
				else
					strcpy(REF, argv[i] + 2);
				break;
			case 'S':
			case 's':
				STDOUT = 1;
				break;
#ifndef __riscos__
			case 'T':
			case 't':
				TESTFILES = 1;
				break;
#endif /* !__riscos__ */
			case 'V':
			case 'v':
				printf("%s  [Get and Resume Elite EDition] - By "
				 "Anoakie Turner\r\n", CURRENT_VERSION);
				exit(EXIT_SUCCESS);
				break;
			case 'F':
			case 'f':
				CHECKIN = 0;
				break;
			case 'G':
			case 'g':
				IMPORT_GR = 1;
				GR_FILE = argv[i] + 2;
				break;
			case 'I':
			case 'i':
				STDIN = 1;
				break;
			case 'L':
			case 'l':
				RECURSE = atoi(argv[i] + 2);
				break;
#ifndef __riscos__
			case 'D':
			case 'd':
				if (argv[i][2] != '\0')
					FORK = atoi(argv[i] + 2);
				else
					FORK = 1;
				break;
#endif /* !__riscos__ */
			case 'C':
			case 'c':
				argv[i] += 2;
				printf("\n\n<-- %s\n", argv[i]);
				unescape_url(argv[i]);
				printf("--> %s!\n\n", argv[i]);
				break;
#ifndef __riscos__
			case 'B':
			case 'b':
				BACKGROUND = 1;
				break;
#endif /* !__riscos__ */
			case 'Z':
			case 'z':
				SendBug();
				exit(0);
				break;
			case 'W':
			case 'w':
				NEWRC = 1;
				break;
			default:
				printf("\n\n\t\t*** Unknown switch [%s]! ***\n\n", argv[i]);
			case '?':
				printf("%s  [Get and Resume Elite EDition] - By "
				"Anoakie Turner\r\n", CURRENT_VERSION);
				printf("\n\nUSEAGE: greed URL(1) URL(2) ... URL(N)\n"
				"i.e.: greed %s ftp://some.where/out/there.tar.gz\n\n", GGR);
printf("Options:\n"
#ifndef __riscos__
"-b\tSends greed into background downloading mode.\n"
#endif /* !__riscos__ */
"-c<url>\tchanges the %%##'s in a URL to characters.\n"
#ifndef __riscos__
"-d\tTells greed to download 2 files at once.\n"
"-d<#>\tTells greed to download # files at once.\n"
#endif /* !__riscos__ */
"-f\tIgnores the greed.in (default download list) file if it exists.\n"
"-g<FL>\tImports a windows GetRight file (*.GRX).\n"
"\t\ti.e. greed -gMyDownloads.grx\n"
"-i\tReads URLs from standard input.\n"
"\t\ti.e. greed -I < download.lst\n"
"-l<#>\tSets the level of recursion for FTP transfers.\n"
"-m<adr>\tsend a mail to [adr] (by sendmail) when a download is complete\n"
"-n\tDownloads the newest version of GREED!\n"
"-o<#>\tSets the level of output (default 5, no output = 0).\n"
"-r\tSets the referrer OFF.\n"
"-r<URL>\tSets the referrer to URL.\n"
"-s\tPrints the file that is being downloaded to the screen instead of a file.\n"
#ifndef __riscos__
"-t\tTests archives after download to see if they are valid.\n"
"-w\tCreates new .greedrc in ${HOME}/.greedrc.\n"
#else
"-w\tCreates new greedrc file in <Choices$Write>.\n"
#endif /* __riscos__ */
"-z\tSend me a bug!\n"
"-0\tRestarts file at 0 bytes\n"
"...\tUsage: greed URL...FILE, where URL is the url and FILE is the file retrieved.\n"
"\t\tNOTE: This only works if you have the correct programs to test with!.\n"
"\n\nALL OTHER OPTIONS (including proxy support) CAN BE FOUND IN ~/.greedrc\n");
				exit(0);
				break;
		}
	}
}
