/*
 * This program converts Citadel/UX 3.1X data files to 3.2 format.
 *
 * Only run the program ONCE.
 * BACK UP YOUR OLD FILES before running this program.
 *
 * If you are not upgrading, you do NOT need this program.
 *
 */

#include <stdio.h>
#include "citadel.h"

struct old_usersupp {			/* User record                      */
	int oUSuid;			/* userid (==BBSUID for bbs only)   */
	char opassword[20];		/* password (for BBS-only users)    */
	long olastseen[MAXROOMS];	/* Last message seen in each room   */
	char ogeneration[MAXROOMS];	/* Generation # (for private rooms) */
	char oforget[MAXROOMS];		/* Forgotten generation number      */
	long omailnum[MAILSLOTS];	/* Message #'s of each mail message */
	long omailpos[MAILSLOTS];	/* Disk positions of each mail      */
	unsigned oflags;			/* See US_ flags below              */
	int otimescalled;		/* Total number of logins           */
	int oposted;			/* Number of messages posted (ever) */
	char ofullname[26];		/* Name for Citadel messages & mail */
	char oaxlevel;			/* Access level                     */
	CIT_UBYTE oUSscreenwidth;	/* Screen width                     */
	CIT_UBYTE oUSscreenheight;	/* Screen height                    */
	char ospare[3];			/* spare bytes in the user account  */
	long oeternal;			/* Eternal user number              */
	long olastcall;			/* Last time the user called        */
	char oUSname[30];
	char oUSaddr[25];
	char oUScity[15];
	char oUSstate[3];
	char oUSzip[10];
	char oUSphone[11];
};

struct old_quickroom {
	char oQRname[20];		/* Max. len is 19, plus null term   */
	char oQRpasswd[10];		/* Only valid if it's a private rm  */
	long oQRroomaide;		/* User number of room aide         */
	long oQRhighest;		/* Highest message NUMBER in room   */
	char oQRgen;			/* Generation number of room        */
	unsigned oQRflags;		/* See flag values below            */
	char oQRdirname[15];		/* Directory name, if applicable    */
		};

struct old_registration {
	long oRGeternal;
	char oRGname[30];
	char oRGaddr[25];
	char oRGcity[15];
	char oRGstate[3];
	char oRGzip[6];
	char oRGphone[11];
	};

long ftell();

extern int errno;
struct config config;

FILE *efopen(name,mode)
char *name;
char *mode; {
	FILE *fp;
	fp=fopen(name,mode);
	if (fp!=NULL) return(fp);
	fprintf(stderr,"efopen: cannot open '%s', errno=%d\n",name,errno);
	exit(errno);
	}

main() {
	int a,in,out,merged;
	char buf[64];
	long pos;
	
	FILE *from,*to;

	struct old_quickroom qrf;
	struct quickroom qrt;
	struct old_usersupp usf;
	struct usersupp ust;
	struct old_registration ref;

	printf("This program converts your data files from version 3.1X\n");
	printf("to version 3.2.  BACK UP YOUR DATA FIRST, and then run\n");
	printf("program ONCE.  If this is a new installation, and you\n");
	printf("are not upgrading, then you do not need to run this\n");
	printf("program.\n\nDo you still wish to continue? ");
	gets(buf);

	if (tolower(buf[0])!='y') exit(0);
	
	printf("\n*** Phase 1 - convert room index (quickroom)\n");

	from = efopen("quickroom","r");
	to = efopen("quickroom.new","w");
	in = 0;
	out = 0;
	for (a=0; a<MAXROOMS; ++a) {
		in = in + 
			fread((char *)&qrf,sizeof(struct old_quickroom),1,from);
		strcpy(qrt.QRname,qrf.oQRname);
		strcpy(qrt.QRpasswd,qrf.oQRpasswd);
		qrt.QRroomaide = qrf.oQRroomaide;
		qrt.QRhighest = qrf.oQRhighest;
		qrt.QRgen = qrf.oQRgen;
		qrt.QRflags = qrf.oQRflags;
		strcpy(qrt.QRdirname,qrf.oQRdirname);
		out = out + fwrite((char *)&qrt,sizeof(struct quickroom),1,to);
		}
	fclose(from);
	fclose(to);
	printf("    Records read:    %d\n",in);
	printf("    Records written: %d\n",out);
	if (in==out) {
		system("mv quickroom quickroom.31");
		system("mv quickroom.new quickroom");
		printf("    Old format file saved as 'quickroom.31'\n");
		}

	printf("\n*** Phase 2 - convert userlog (usersupp/registration)\n");

	from = efopen("usersupp","r");
	to = efopen("usersupp.new","w");
	in = 0;
	out = 0;
	while (fread((char *)&usf,sizeof(struct old_usersupp),1,from)>0) {
		++in;
		ust.USuid = usf.oUSuid;	
		for (a=0; a<20; ++a) ust.password[a] = usf.opassword[a];
		for (a=0; a<MAXROOMS; ++a) {
			ust.lastseen[a] = usf.olastseen[a];
			ust.generation[a] = usf.ogeneration[a];
			ust.forget[a] = usf.oforget[a];
			}
		for (a=0; a<MAILSLOTS; ++a) {
			ust.mailnum[a] = usf.omailnum[a];
			ust.mailpos[a] = usf.omailpos[a];
			}
		ust.flags = usf.oflags;
		ust.timescalled = usf.otimescalled;
		ust.posted = usf.oposted;
		strcpy(ust.fullname,usf.ofullname);
		strcpy(ust.USname,usf.oUSname);
		strcpy(ust.USaddr,usf.oUSaddr);
		strcpy(ust.UScity,usf.oUScity);
		strcpy(ust.USstate,usf.oUSstate);
		strcpy(ust.USzip,usf.oUSzip);
		strcpy(ust.USphone,usf.oUSphone);
		ust.axlevel = usf.oaxlevel;
		ust.eternal = usf.oeternal;
		ust.lastcall = usf.olastcall;
		ust.USscreenwidth = usf.oUSscreenwidth;
		ust.USscreenheight = usf.oUSscreenheight;
		
		out = out + fwrite((char *)&ust,sizeof(struct usersupp),1,to);
		}
	fclose(from);
	fclose(to);
	printf("    Records read:    %d\n",in);
	printf("    Records written: %d\n",out);
	if (in==out) {
		system("mv usersupp usersupp.31");
		system("mv usersupp.new usersupp");
		printf("    Old format file saved as 'usersupp.31'\n");
		}

	printf("\n*** Phase 3 - merge info file pointers\n");
	in = 0;
	out = 0;
	merged = 0;
	to=efopen("quickroom","r+");
	for (a=0; a<MAXROOMS; ++a) {
		fseek(to,(long)a*sizeof(struct quickroom),0);
		in = in + fread((char *)&qrt,sizeof (struct quickroom),1,to);

		sprintf(buf,"./info/%d.ptr",a);
		from=fopen(buf,"r");
		if (from!=NULL) {
			fscanf(from,"%ld",&qrt.QRinfo);
			++merged;
			fclose(from);
			}

		fseek(to,(long)a*sizeof(struct quickroom),0);
		out = out + fwrite((char *)&qrt,sizeof(struct quickroom),1,to);
		}
	fclose(to);
	printf("    Records read:    %d\n",in);
	printf("    Records written: %d\n",out);
	printf("    Records merged:  %d\n",merged);

	printf("\n*** Phase 4 - merge registration into userlog\n");
	in = 0;
	out = 0;
	merged = 0;
	to=efopen("usersupp","r+");
	from=efopen("registration","r");

	while (pos=ftell(to),
	      fread((char *)&ust,sizeof(struct usersupp),1,to)==1) {
		in = in + 1;

		fseek(from,0L,0);
		while (fread((char *)&ref,
		      sizeof(struct old_registration),1,from)>0) {
			if (ref.oRGeternal == ust.eternal) {
				strcpy(ust.USname,ref.oRGname);
				strcpy(ust.USaddr,ref.oRGaddr);
				strcpy(ust.UScity,ref.oRGcity);
				strcpy(ust.USstate,ref.oRGstate);
				strcpy(ust.USzip,ref.oRGzip);
				strcpy(ust.USphone,ref.oRGphone);
				++merged;
				}
			}

		fseek(to,pos,0);
		out = out + fwrite((char *)&ust,(sizeof(struct usersupp)),1,to);
		fseek(to,pos+(long)sizeof(struct usersupp),0);
		}
	fclose(to);
	fclose(from);
	printf("    Records read:    %d\n",in);
	printf("    Records written: %d\n",out);
	printf("    Records merged:  %d\n",merged);

	exit(0);
	}
