#include <exec/types.h>
#include <exec/execbase.h>
#include <exec/memory.h>
#include <dos/dosextens.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dos.h>
#include <time.h>

char *mark="-------------------------------------------------------------";

#define MAXPAGES 100
#define LINELEN  256
#define PAGER_HELP "\
More help:\n\
  Q,q,^c - quit\n\
  r      - restart file\n\
  x      - restart in rot-13 mode\n\
  .      - no more nomore\n\
  f      - skip full page\n\
  b      - back one page\n\
  SPACE  - next page\n\
  CR,LF  - next line\n\
  others - next half page\n"


#define UID_NAME_ARRAY

#include "/lib/iomodes.h"
#include "/lib/users.h"
#include "/lib/misc.h"

#define LEN 80
#define CUID	  ((struct Process *)(SysBase->ThisTask))->pr_Pad

extern struct ExecBase *SysBase;

/* register-program for AXsh. Programmed by Pasi Ojala. */

struct User	user;

char *vers="\0$VER: register 1.22 (13.2.94)\n";
char	Homes[LEN]="AXsh:home/",
		passwdfile[LEN]="AXsh:etc/passwd",
		User[LEN]="",
		ExampleUser[LEN]="AXsh:etc/ExampleUser/",
		Realname[LEN]="",
		Password[LEN]="";
long	quota=50;
UWORD	uid=UID_VISITOR,olduid=0;


FILE *fopen(),*answ=0,*quest=0;

void __regargs __chkabort(void);
void __regargs __chkabort(void){}
void chkabort(void) {}
/* int CXBRK() {return(0);} */
void read_config(void);
int getline(UBYTE *,int,char);
void cat(char *name);


void main(int argc,char *argv[])
{	int i;
	UBYTE in1[LEN],in2[LEN];
	BPTR lock;

	read_config();	/* setting up.. */

	if(lock=Lock("AXsh:etc/register.before",ACCESS_READ))
	{
		UnLock(lock);
		cat("AXsh:etc/register.before");
	}

	while(1)
	{
		printf("Your login name: ");
		fflush(stdout);
		if(getline(in1,16,1))
			exit(2);
		lowercase(in1,in1);
		if(!strcmp(in1,"new"))
		{
			printf("No login name \"new\" allowed!\n");
			continue;
		}
		if(strlen(in1)<3)
		{
			printf("Don't be foolish, your login name can't be that short!\n");
			continue;
		}
		i=0;
		while(in1[i] && ((in1[i]>',' && in1[i]<':') || (in1[i]>'`' && in1[i]<'{')))
			i++;
		if(in1[i])
		{
			printf("Sorry, login name can't contain special characters\n");
			continue;
		}
		if(search_userdata(passwdfile,&user,0,in1)!=-1)
		{
			printf("That login name is already in use, try another one.\n");
			continue;
		}
		else
			break;
	}
	strcpy(User,in1);
	if(lock=Lock("AXsh:etc/register.passwd",ACCESS_READ))
	{
		UnLock(lock);
		cat("AXsh:etc/register.passwd");
	}
	while(1)
	{
		printf("Pick a password: ");
		fflush(stdout);
		if(getline(in1,16,0))
			exit(2);
		printf("Retype the password: ");
		fflush(stdout);
		if(getline(in2,16,0))
			exit(2);
		if(strcmp(in1,in2))
			printf("Passwords differ, type them again.\n");
		else
		{
			if(strlen(in1)<5)
				printf("Too short password, use a longer one.\n");
			else
				break;
		}
	}
	crypt(Password,in1);

	if(lock=Lock("AXsh:etc/register.fullname",ACCESS_READ))
	{
		UnLock(lock);
		cat("AXsh:etc/register.fullname");
	}
	printf("Your full name: ");
	fflush(stdout);
	if(getline(Realname,47,1))
		exit(2);

	if(quest=fopen("AXsh:etc/Questionnaire","rb"))
	{
		if(answ=fopen("AXsh:etc/adm/Answers","ab"))
		{
			printf("And these are the one-liner questions for you.\n");
			fprintf(answ,"User: %s (%s)\n",User,Realname);
			while(!feof(quest))
			{
				if(fgets(in1,LEN-1,quest)==0)
					break;

				if(in1[0])
					in1[strlen(in1)-1]=0;
				if(in1[0])
				{
					printf("%s\n",in1);
					if(getline(in2,LEN-1,1))
					{
						fclose(answ);
						fclose(quest);
						exit(2);
					}
					fprintf(answ,"%s\n",in2);
				}
			}
			fputs("\n",answ);
			fclose(answ);
		}
		else
			printf("Answer file cannot be opened, so I think we just skip the questionnaire\n");
		fclose(quest);
	}
	else
		printf("No questions for you in the questionnaire..\n");

	sprintf(in1,"%s%s/",Homes,User);
	adduser(passwdfile,User,Password,Realname,in1,quota,uid);
	if(search_userdata(passwdfile,&user,0,User)!=-1)
	{
		printf("Now you have an account.\n");
		sprintf(in1,"%s%s",Homes,User);

		olduid=CUID;
		CUID=UID_SUPERUSER | user.UID;
		mkdir(in1);

		sprintf(in1,"c:copy >NIL: %s#? %s%s/",ExampleUser,Homes,User); 
		Execute(in1,0,0);

		if(lock=Lock("AXsh:etc/register.script",ACCESS_READ))
		{
			UnLock(lock);
			sprintf(in1,"execute AXsh:etc/register.script %s",User);
			Execute(in1,0,0);
		}
		CUID=olduid;
	}
	else
		printf("Account create failed!\n");
}


int getline(UBYTE *a,int b,char echo)
{	register int i=0,found=0;

	setmode(MODE_RAW);
	while(!found)
	{
		if(WaitForChar(Input(),10000000))
		{
			if(Read(Input(),&a[i],1)<=0)
			{
				a[i]=0;
				setmode(MODE_CONSOLE);
				return -1;
			}
			if(a[i]==0x0a || a[i]==0x0d)
			{
				found=1;
				a[i]=0;
			}
			else
			{
				if(a[i]==0x7f || a[i]==0x08)
				{
					if(i>0)
					{
						if(echo)
							printf("\010 \010");
						i--;
					}
				}
				else
				{
					if(a[i]==0x03 || (SetSignal(0L,SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C))
					{
						printf("**Break\n");
						a[i]=0;
						setmode(MODE_CONSOLE);
						return -1;
					}
					else
					if(i<b-1 && a[i]>0x1f && (a[i]<0x80 || a[i]>0x9f))
					{
						if(echo)
							Write(Output(),&a[i],1);
						i++;
					}
				}
			}
			fflush(stdout);
		}
		else
		{
			if(carrier_lost() || (SetSignal(0L,SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C))
			{
				printf("**Break\n");
				a[i]=0;
				setmode(MODE_CONSOLE);
				return -1;
			}
		}
	}
	printf("\n");
	setmode(MODE_CONSOLE);
	return 0;
}

void read_config()
{	FILE *handle;
	char line[LEN];
	register int i,found=0,mask=0;

	if(handle=fopen("AXsh:etc/rc","rb"))	/* luetaan config */
	{
		while(!feof(handle))
		{
			if(fgets(line,LEN-1,handle)==0)
				break;

			if(i=strlen(line))
				line[i-1]=0;

			if(!found)
			{
				if(!strncmp(line,"%home:",6))
					found=1;
				else
				if(!strncmp(line,"%exampleuser:",13))
					found=2;
				else
				if(!strncmp(line,"%defuserlevel:",14))
					found=3;
				else
				if(!strncmp(line,"%defquota:",10))
					found=4;
				else
				if(!strncmp(line,"%passwdfile:",12))
					found=5;
			}
			else
			{
				switch(found)
				{
				case 1:
					strcpy(Homes,line);
					mask|=1<<1;
					break;
				case 2:
					strcpy(ExampleUser,line);
					mask|=1<<2;
					break;
				case 3:
					i=0;
					while(UID_Name[i] && strcmp(UID_Name[i],line))
						i++;
					if(UID_Name[i])
						uid=i<<UID_ACCESSSHIFT;
					mask|=1<<3;
					break;
				case 4:
					quota=atol(line);
					mask|=1<<4;
					break;
				case 5:
					strncpy(passwdfile,line,LEN);
					mask|=1<<5;
					break;
				}
				found=0;
				if(mask==0x1f)
					break;	/* found them all already */
			}
		}
		fclose(handle);
	}
	else
		printf("AXsh:etc/rc not found!\n");
}

/* the following hacks were done by bruins@hal9000.apana.org.au */

#ifdef USE_CAT
void cat(char *name)
{	long handle;
	UBYTE buffer[256],c;
	int len;

	if(handle=Open(name,MODE_OLDFILE))
	{
		while((len=Read(handle,buffer,256))>0)
		{
			Write(Output(),buffer,len);
			if(WaitForChar(Input(),1))
			{
				Read(Input(),&c,1);
				if(c==0x03 || c=='q')
					break;
			}
		}
		Close(handle);
	}
	else
		printf("Can't open file '%s'\n",name);
}
#else
void cat(char *file)
{	char line[LINELEN],a,inte=IsInteractive(Output()),nomore=0,rot=0,clearscreen=0;
	int i,lines=0,skip=0,Rows=24,Columns=80,c,len,esc=0,j;
	FILE *handle;
	long pages[MAXPAGES];
	int  page=0;

	pages[0]=0;
	setmode(MODE_RAW);
	if(who(COM_GET,NULL,"rows",line))	Rows=24; /* default value */
	else								Rows=atoi(line);
	if(Rows<5)		Rows=25;
	if(Rows>100)	Rows=100;
	if(who(COM_GET,NULL,"columns",line))	Columns=80; /* default value */
	else									Columns=atoi(line);
	if(Columns<5)		Columns=80;
	if(Columns>500)		Columns=500;

	if(handle=fopen(file,"rb"))
	{
		line[i=0]=0;
		while(!feof(handle))
		{
			i=strlen(line);
			if(fgets(line+i,LINELEN-2-i,handle)==0)
				break;

			i=len=0;
			while(c=line[i])
			{
				if(len>=Columns-1)
				{
					if(c!=0x0a)
					{
						c=0x0a;
						esc=strlen(line+i)+1;
						while(esc--)
								line[i+1+esc]=line[i+esc];
					}
					esc=0;
				}
				if(esc)
				{
					if(c!=';' && (c<'0' || c>'9'))
						esc=0;
				}
				else
				{
					switch(c)
					{
					case 0x0c:
						printf("^L\n");
						lines=Rows-1;	/* fall through */
					case 0x0a:
					case 0x0d:
						line[i]=0;
						if(line[0])
						{
							printf("%s\n",line);
						}
						else
							printf("\n");

						if((++lines>Rows-3 && !nomore && inte) || WaitForChar(Input(),1))
						{
							if(SetSignal(0,0) & SIGBREAKF_CTRL_C)
							{
								printf("\n***Break***\n");
								setmode(MODE_CONSOLE);
								fclose(handle);
								exit(0);
							}
							if(page<MAXPAGES)
							{
								pages[++page]=ftell(handle);
							}
							else
							{
								for(j=0;j<MAXPAGES-1;j++)
									pages[j]=pages[j+1];
								pages[page-1]=ftell(handle);
							}
							do
							{
								fflush(stdout);
								if(WaitForChar(Input(),1))
									Read(Input(),&a,1);
								else
								{
									printf("\033[7mMore?\033[m");
									fflush(stdout);
									if(WaitForChar(Input(),120000000))
										Read(Input(),&a,1);
									else
										a=0x0a;
									printf("\b\b\b\b\b\033[K");
									fflush(stdout);
								}
								if(a=='h')
								{
									printf(PAGER_HELP);
								}
							}
							while(a=='h');

							switch(a)
							{
							case 'b':
								if(clearscreen)
									printf("\014");
								if(page>1)
								{
									printf("-- Back one page --\n");
									fseek(handle,pages[page-2],NULL);
									page-=2;
								}
								else
								{
									printf("-- Restart page --\n");
									fseek(handle,pages[page-1],NULL);
									page--;
								}
								lines=0;
								break;
							case 'x':
								if(clearscreen)
									printf("\014");
								fseek(handle,0,NULL);
								page=0;
								lines=0;
								rot=TRUE;
								break;
							case 'r':
								if(clearscreen)
									printf("\014");
								fseek(handle,0,NULL);
								page=0;
								lines=0;
								rot=FALSE;
								break;
							case '.':
								nomore=TRUE;
								break;
							case ' ':
								lines-=Rows-2;
								if(clearscreen)
									printf("\014");
								break;
							case 'f':
								if(clearscreen)
									printf("\014");
								printf("-skipped one page-\n");
								skip=Rows-2;
								lines-=Rows-2;
								break;
							case 0x0a:
							case 0x0d:
								lines--;
								break;
							case 'd':
								lines-=(Rows-2)/2;
								break;
							case 0x03:
							case 'q':
							case 'Q':
								printf("\n***Quit***\n");
								setmode(MODE_CONSOLE);
								fclose(handle);
								exit(0);
								break;
							default:
								lines-=(Rows-2)/2+1;	/* half page */
								break;
							}
						}
						if(lines<0)
							lines=0;

						if(line[i+1])
						{	strcpy(line,line+i+1);
							i=-1;
						}
						else
							line[0]=0;
						len=0;
						/* line was cut */
						break;
					case 0x08:
					case 0x7f:
						if(len)
							--len;
						break;
					case 0x09:
						len=(len/8)*8+8;
						break;
					case 0x9b:
					case 0x1b:
						esc=-1;
						break;
					default:
						if(rot)
						{
							if(c>0x3f && c<0x5b)
								c=((c-0x40)+13)%26+0x40;
							if(c>0x5f && c<0x7b)
								c=((c-0x60)+13)%26+0x60;
							line[i]=c;
						}
						++len;
						break;
					}
				}
				i++;
			}
		}
		fclose(handle);
		if(i>1)
		{
			line[i-1]=0;
			printf("%s\n",line);
		}
		lines=Rows-4;
	}
	else
		fprintf(stderr,"Can't open file '%s'\n",file);
}

#endif
