/****************************************************************
 * This software is Copyright (C) 1986-1998 by                  *
 *                                                              *
 * F6FBB - Jean-Paul ROUBELAT,  jpr@f6fbb.org                   *
 * 6, rue George Sand                                           *
 * 31120 - Roquettes - France                                   *
 *                                                              *
 * License to copy and use this software is granted for         *
 * non-commercial use provided that it is identified as         *
 *                                                              *
 * "FBB packet-radio BBS software by Jean-Paul ROUBELAT, F6FBB" *
 *                                                              *
 * in all material mentioning or referencing this software      *
 * or this function.                                            *
 *                                                              *
 * These notices must be retained in any copies of any part of  *
 * this documentation and/or software.                          *
 *                                                              *
 * Parts of code have been taken from many other softwares.     *
 * Thanks for the help.                                         *
 ****************************************************************/

#include <serv.h>

static int no_init_error = 1;

void err_init (int lig)
{
	no_init_error = 0;
#if defined(__WINDOWS__) || defined(__LINUX__)
	ShowError ("INIT.SRV", "Error line", lig);
	fbb_quit (0);
#endif
#ifdef __FBBDOS__

#ifdef ENGLISH
	cprintf ("Error file INIT.SRV line %d     \r\n\a", lig);
#else
	cprintf ("Erreur fichier INIT.SRV ligne %d\r\n\a", lig);
#endif
	curon ();
	sleep (10);
	exit (0);
#endif
}


static char *test_back_slash (char *chaine, int nolig)
{
#ifdef __LINUX__
	if (chaine[strlen (chaine) - 1] != '/')
		err_init (nolig);
#else
	if (chaine[strlen (chaine) - 1] != '\\')
		err_init (nolig);
#endif
	return (chaine);
}

void end_admin (void)
{
	Msysop *sptr;

	while (mess_sysop)
	{
		sptr = mess_sysop;
		mess_sysop = mess_sysop->next;
		m_libere (sptr, sizeof (Msysop));
	}
	libere_serveurs ();
}

int init_admin (void)
{
	static int first = 1;
	FILE *fp;
	int ntemp;
	char ligne[256];
	char stemp[256];
	char *ptr = ligne;
	char *scan;
	Msysop *sptr = NULL;
	int i, j;
	int val;
	int nolig = 0, init = 1;
	int fond_haut = 0, fond_milieu = 0, fond_bas = 0, fond_menu = 0;
	char *initname;

	balbul = 0;
	nb_ovr = 0;

	/* Ne pas reinitialiser */
	if (first)
	{
		for (i = 0; i < 10; i++)
			varx[i] = m_alloue (81);

		for (i = 1; i < NBPORT; i++)
			t_balise[i] = 900;
	}

#ifdef __FBBDOS__
	initname = "init_d.srv";
#endif
#ifdef __WINDOWS__
	initname = "init_w.srv";
#endif
#ifdef __LINUX__
	initname = "init_l.srv";
#endif
	if ((fp = fopen (initname, "r")) == NULL)
	{
		if ((fp = fopen ("init.srv", "r")) == NULL)
		{
#if defined(__WINDOWS__) || defined(__LINUX__)
			no_init_error = 0;
			ShowError ("INIT.SRV", "Cannot open file", 0);
			window_init ();
			fbb_quit (0);
			return (0);
#endif

#ifdef __FBBDOS__
#ifdef ENGLISH
			cprintf ("Cannot open file INIT.SRV        \r\n\a");
#else
			cprintf ("Erreur ouverture fichier INIT.SRV\r\n\a");
#endif
			err_init (0);
			curon ();
			exit (0);
#endif
		}
	}
	i = 0;
#ifdef ENGLISH
	cprintf ("Parameters set-up            \r\n");
#else
	cprintf ("Initialisation des parametres\r\n");
#endif
	if (fgets (ligne, 250, fp))
	{
		char ver[80];

		++nolig;
#if 0
		ptr = sup_ln (ligne);
#else
		ptr = strupr (sup_ln (ligne));
#endif
		if (*ptr != '#')
		{
#ifdef ENGLISH
			cprintf ("*** Error : No version number in first line        \r\n");
#else
			cprintf ("*** Erreur : Pas de num‚ro de version en 1Šre ligne\r\n");
#endif
			err_init (nolig);
		}
		sscanf (ptr, "#%s", stemp);
#ifdef __FBBDOS__
		cprintf ("INIT.SRV version %s\r\n", stemp);
		sleep (2);
#endif
		/*if (isgraph(LETTRE))
		   sprintf(ver, "FBB%d.%02d%c", MAJEUR, MINEUR, LETTRE);
		   else */
		sprintf (ver, "FBB%d.%02d", MAJEUR, MINEUR);
		if (strncmp (strupr (ver), stemp, strlen (ver)) != 0)
		{
#ifdef __WINDOWS__
			char txt[80];

			ferme (fp, 57);
			wsprintf (txt, "Error : Waiting for INIT.SRV version %s", ver);
			WinMessage (5, txt);
			window_init ();
			fbb_quit (0);
			return (0);
#else
			ferme (fp, 57);
#ifdef ENGLISH
			cprintf ("*** Error : Waiting for INIT.SRV version %s \r\n", ver);
#else
			cprintf ("*** Erreur : Version de INIT.SRV attendue %s\r\n", ver);
#endif
#endif
			err_init (nolig);
		}
	}

	while (fgets (ligne, 250, fp))
	{
		++nolig;
		ptr = sup_ln (ligne);
		if ((*ligne == '#') || (*ligne == '\032'))
			continue;
		i++;
		if (init)
		{
			switch (i)
			{
			case 1:
				strn_cpy (39, mypath, ptr);
				if ((j = strlen (mypath)) && (mypath[j - 1] == '.'))
					mypath[j - 1] = '\0';
				break;
			case 2:
				myssid = (char) atoi (ptr);
				break;
			case 3:
				strn_cpy (6, qra_locator, strupr (ptr));
				break;
			case 4:
				n_cpy (19, my_city, ptr);
				break;
			case 5:
				strn_cpy (80, DISK, test_back_slash (ptr, nolig));
				break;
			case 6:
				strn_cpy (80, MESS, test_back_slash (ptr, nolig));
				break;
			case 7:
				strn_cpy (80, MBIN, test_back_slash (ptr, nolig));
				break;
			case 8:
				for (j = 1; j < 8; j++)
				{
					*PATH[j] = '\0';
				}
				scan = strtok (ptr, " ,\t");
				if ((scan) && (isalpha (*scan)))
					strn_cpy (80, PATH[0], test_back_slash (scan, nolig));
				for (j = 1; j < 8; j++)
				{
					scan = strtok (NULL, " ,\t");
					if (scan == NULL)
						break;
#ifdef __LINUX__
					if (*scan == '/')
					{
						strn_cpy (80, PATH[j] + 2, slash2back (test_back_slash (scan, nolig)));
						PATH[j][0] = getdisk () + 'A';
						PATH[j][1] = ':';
					}
#else
					if (isalpha (*scan))
						strn_cpy (80, PATH[j], test_back_slash (scan, nolig));
#endif
				}
				break;
			case 9:
				strn_cpy (80, YAPPDIR, test_back_slash (ptr, nolig));
				break;
			case 10:
				strn_cpy (80, DOCS, test_back_slash (ptr, nolig));
				ptr = DOCS + strlen (DOCS) - 1;
				if (*ptr == '\\')
					*ptr = '\0';
				break;
			case 11:
				n_cpy (12, my_name, ptr);
				break;
			case 12:
				strn_cpy (6, admin, ptr);
				break;
			case 13:
				scan = strtok (ptr, " ,\t");
				/* Delete la liste existante eventuellement */
				while (mess_sysop)
				{
					sptr = mess_sysop;
					mess_sysop = mess_sysop->next;
					m_libere (sptr, sizeof (Msysop));
				}

				if ((scan) && (isalpha (*scan)))
				{
					sptr = mess_sysop = (Msysop *) m_alloue (sizeof (Msysop));
					strn_cpy (20, sptr->call, scan);
				}
				while ((scan = strtok (NULL, " ,\t")) != NULL)
				{
					sptr->next = (Msysop *) m_alloue (sizeof (Msysop));
					sptr = sptr->next;
					strn_cpy (20, sptr->call, scan);
				}
				break;
			case 14:
				strn_cpy (80, MAILIN, ptr);
				scan = strrchr (ptr, '\\');
				if (scan)
					*++scan = '\0';
				else
					*ptr = '\0';
				sprintf (LOCK_IN, "%sLOCK.IN", ptr);
				break;
			case 15:
				BLK_TO = 10;
				if (sscanf (ptr, "%u %u", &stype, &BLK_TO) > 2)
					err_init (nolig);
				blank = BLK_TO;
				stype = atoi (ptr);
				break;
			case 16:
				comlog = (toupper (*ptr) == 'O');
				break;
			case 17:
				direct = (toupper (*ptr) == 'O');
#ifdef __FBBDOS__
				directvideo = direct;
#endif
				break;
			case 18:
				ok_aff = (toupper (*ptr) == 'O');
				break;
			case 19:
				DEBUG = (toupper (*ptr) == 'O');
				miniserv = 0xffff;
				watchport = 0;
				sscanf (ptr, "%*s %d", &watchport);
				break;
			case 20:
				fbb_fwd = (toupper (*ptr) == 'O');
				/*
				   1  : Espace obligatoire avant le @ dans l'adresse
				   2  : Ne teste pas la limite a 6 des champs de l'adresse
				   4  : Ne tronque pas le header a l'espace < 79 caracteres
				   8  : Header MBL/RLI
				   16 : Si pas de champ BBS envoie l'indicatif de ma BBS (->PMS)
				   32 : Supprime les messages data au SYSOP
				   64 : N'utilise pas le BID cree a partir des headers si pas de BID
				   128: N'accepte le forward que des BBS declarees.
				   256: Les messages WP ne sont pas HOLD
				   512: XWFD has priority on FBB
				   1024: Alternate BID generation
				   2048: XFWD with checksum
				   4096: Simple check for callsigns (3 to 6 chars, 1 digit, 1 alpha).
				 */
				std_header = 0;
				sscanf (ptr, "%*s %d", &std_header);
				break;
			case 21:
				/*
				   1  : Protocole de niveau 1
				 */
				bin_fwd = (toupper (*ptr) == 'O');
				/*
				   1  : Binaire FBB version 1
				   2  : Binaire RLI
				 */
				ntemp = -1;
				sscanf (ptr, "%*s %d", &ntemp);
				if ((bin_fwd) & (ntemp != -1) && (ntemp & 1))
				{
					bin_fwd = 2;
				}
				prot_fwd = FWD_MBL;
				if (fbb_fwd)
				{
					prot_fwd |= FWD_FBB;
					if (bin_fwd)
					{
						prot_fwd |= FWD_BIN;
						if (bin_fwd == 2)
							prot_fwd |= FWD_BIN1;
					}
				}
				if ((ntemp == -1) || (ntemp & 2))
					prot_fwd |= FWD_XPRO;

				break;
			case 22:
				if (operationnel <= 0)
					h_ok = (toupper (*ptr) == 'O');
				break;
			case 23:
				info_ok = (toupper (*ptr) == 'O');
				break;
			case 24:
				def_mask = (unsigned) atoi (ptr);
				break;
			case 25:
				if (sscanf (ptr, "%u %u %u", &d_droits, &ds_droits, &dss_droits) != 3)
					err_init (nolig);
				break;
			case 26:
				w_mask = (unsigned) atoi (ptr);
				break;
			case 27:
				h_maint = atoi (ptr);
				break;
			case 28:
				if (sscanf (ptr, "%d %d", &time_n, &time_b) != 2)
					err_init (nolig);
				time_n *= 60;
				time_b *= 60;
				break;
			case 29:
				if (sscanf (ptr, "%d %d", &max_yapp, &max_mod) != 2)
					err_init (nolig);
				break;
			case 30:			/* tzone = 3600 * -atol(ptr) ; */
				if (getenv ("TZ") == NULL)
				{
					/*
					   memset(_tzname[1], 0, 4);
					   strcpy(_tzname[0],"GMT");
					   _timezone = 3600L * -atol(ptr) ;
					   _daylight = 0;       stime
					 */
					/* Ne pas liberer... Sinon ca plante a l'appel suivant. */
					char *tzl = malloc (20);

					sprintf (tzl, "TZ=GMT%d", -atoi (ptr));
					j = putenv (tzl);
				}
				tzset ();
				break;
			case 31:
				if (toupper (*ptr) == 'B')
				{
					balbul = 1;
					do
					{
						++ptr;
					}
					while (!ISGRAPH (*ptr));
				}
				max_indic = atoi (ptr);
				break;
			case 32:
				winbuf.totlig = conbuf.totlig = monbuf.totlig = 100;
				sscanf (ptr, "%d %d %d",
						&winbuf.totlig, &conbuf.totlig, &monbuf.totlig);
				break;
			case 33:
				txtfwd[0] = '\0';
				n_cpy (51, txtfwd + 1, ptr);
				if (txtfwd[1])
					txtfwd[0] = ' ';
				break;
			case 34:
				maxbbid = atoi (ptr);
				if (maxbbid < 0)
					maxbbid = 2000;
				break;
			case 35:
				multi_prive = 0;
				sscanf (ptr, "%ld %d", &nb_jour_val, &multi_prive);
				if (nb_jour_val < 1L)
					nb_jour_val = 1L;
				break;
			case 36:
				ems_aut = atoi (ptr);
#ifdef __WINDOWS__
				if (ems_aut)
					ems_aut = 2;
#endif
				in_exms = 0;
				if (ems_aut < 0 || ems_aut > 2)
					ems_aut = 0;
				strtok (ptr, " ,\t");
				if (ems_aut == 0)
					break;
				while ((scan = strtok (NULL, " ,\t")) != NULL)
				{
					strupr (scan);
					for (j = 0; j < NB_EMS; j++)
					{
						if (strcmp (t_ems[j].ctype, scan) == 0)
						{
							in_exms |= t_ems[j].flag;
							/* dprintf("Valide le flag %x\r\n", t_ems[j].flag); */
							break;
						}
					}
					/*
					   if (j == NB_EMS)
					   err_init(nolig);
					 */
				}
				break;
			case 37:
				strn_cpy (79, wp_line, ptr);
				break;
			case 38:
				n_cpy (8, my_zip, ptr);
				break;
			case 39:
				nb_unproto = 300L;
				val = 6;
				mute_unproto = ack_unproto = via_unproto = priv_unproto = 0;
				sscanf (ptr, "%ld %d %s", &nb_unproto, &val, stemp);

				scan = strupr (stemp);
				while (*scan)
				{
					switch (*scan)
					{
					case 'V':
						via_unproto = 1;
						break;

					case 'P':
						priv_unproto = 1;
						break;

					case 'A':
						ack_unproto = 1;
						break;

					case 'M':
						mute_unproto = 1;
						break;
					}
					++scan;
				}

				def_time_bcl = (val * 18);
				break;
			case 40:
				internal_int = 0xff;
				tf_int = 0xfd;
				sscanf (ptr, "%x %x", &internal_int, &tf_int);
				if ((internal_int < 0x10) || (internal_int > 0xff))
				{
					internal_int = 0xff;
				}
				if ((tf_int < 0x10) || (tf_int > 0xff))
				{
					tf_int = 0xfd;
				}
				break;
			case 41:
				n_cpy (79, BBS_UP, ptr);
				break;
			case 42:
				n_cpy (79, BBS_DW, ptr);
				break;
			case 43:
				fond_haut = atoi (ptr);
				break;
			case 44:
				fond_milieu = atoi (ptr);
				break;
			case 45:
				fond_bas = atoi (ptr);
				FOND_VOIE = fond_bas;
				break;
			case 46:
				fond_menu = atoi (ptr);
				break;
			case 47:
#ifdef __FBBDOS__
				TOUR = WHITE;
#endif
				++i;
			case 48:
				DEF = (fond_haut << 4) + atoi (ptr);
				break;
			case 49:
				STA = (fond_milieu << 4) + atoi (ptr);
				break;
			case 50:
				INIT = (fond_menu << 4) + atoi (ptr);
				break;
			case 51:
				SEND = (fond_bas << 4) + atoi (ptr);
				break;
			case 52:
				RECV = (fond_bas << 4) + atoi (ptr);
				break;
			case 53:
				HEADER = (fond_bas << 4) + atoi (ptr);
				break;
			case 54:
				UI = (fond_bas << 4) + atoi (ptr);
				break;
			case 55:
				CONS = (fond_bas << 4) + atoi (ptr);
				break;
			case 56:
				INDIC = (fond_bas << 4) + atoi (ptr);
				break;
			case 57:
				VOIE = (fond_bas << 4) + atoi (ptr);
				break;
			case 58:
				if (*ligne != '-')
					err_init (nolig);
				init = 0;
				/* Libere la liste des serveurs existante */
				libere_serveurs ();
				break;
			}
		}
		else
		{
			if (*ligne == '-')
				break;
			init_serveur (ligne, nolig);
		}
	}
	ferme (fp, 57);
	init_serveur ("WP     * Request White pages info", 0);
	init_serveur ("REQCFG * Request configuration   ", 0);
	init_serveur ("REDIST * Bulletin redistribution ", 0);
	if (init)
		err_init (nolig);
	i = 0;

	ptr = mypath;
	while (isalnum (*ptr))
	{
		mycall[i] = *ptr++;
		if (++i == 6)
			break;
	}
	mycall[i] = '\0';

	ind_console (1, mycall);
	strcpy (my_call, cons_call.call);
#ifdef __WINDOWS__
	if (first)
		window_init ();
	set_win_colors ();
#endif
#ifdef __LINUX__
	if (first)
		window_init ();
	set_win_colors ();
#endif
#ifdef __FBBDOS__
	set_dos_colors ();
#endif

	first = 0;

	return (no_init_error);
}

static void cree_etat (void)
{
	FILE *fichier;

	if ((fichier = fopen (d_disque ("ETAT.SYS"), "wt")) == NULL)
	{
		fbb_error (ERR_CREATE, d_disque ("ETAT.SYS"), 0);
	}
	fprintf (fichier, "%-6s-%d\n", mycall, myssid);
	ind_console (1, mycall);
	fprintf (fichier, "Mise en service par %s-%d le %s\n",
			 cons_call.call, cons_call.num, strdate (time (NULL)));
	fclose (fichier);
}


void init_etat (void)
{
	FILE *fichier;
	char s[81];

	if ((fichier = fopen (d_disque ("ETAT.SYS"), "r+t")) == NULL)
	{
		if (err_ouvert ("ETAT.SYS"))
		{
			cree_etat ();
			arret = FALSE;
		}
		else
			fbb_error (ERR_OPEN, d_disque ("ETAT.SYS"), 0);
	}
	else
	{
		fgets (s, 80, fichier);
		ind_console (1, sup_ln (s));
		if (fgetc (fichier) == 'A')
			arret = TRUE;
		else
			arret = FALSE;
		fclose (fichier);
	}
}
