/* external.c - handle an external login
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif				/* HAVE_CONFIG_H */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pwd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include "terminal.h"
#include "bbs.h"

extern char *crypt();

extern uo_info_t *uo_list;
extern int uo_list_len;
extern int bbs__satellite;

void uo_genlist(void);
int cf_global(void);
int cf_local(void);
void wipe_environ(void);


/* Display a login prompt for external BBS users and log them in if possible.
 *
 * Returns nonzero on error.
 */
int bbs_external_login(void)
{
	struct stat sb;
	char buf[1024];
	char key[64];
	char salt[3];
	FILE *fptr;
	char *a;
	char *b;
	int fd;
	int i, j, u;

	home_dir = strdup("/tmp");
	setenv("HOME", home_dir, 1);

	uo_genlist();

	printf("\nNumber of users currently logged in: %d\n", uo_list_len);

	if (uo_list_len >= cf_int("extlim")) {
		printf
		    ("The BBS is currently full. Please try again later.\n");
		sleep(2);
		return (1);
	}

	for (i = 0; i < 3; i++) {	    /* try 3 times */
		printf("\n Account: ");
		fflush(stdout);
		buf[0] = 0;
		fgets(buf, sizeof(buf) - 1, stdin);
		a = strchr(buf, '\n');
		if (a)
			*a = 0;
		a = strchr(buf, '\r');
		if (a)
			*a = 0;

		if (buf[0] == 0)
			strcpy(buf, " ");

		current_user = strdup(buf); /* set current username */

		cf_global();
		cf_local();		    /* reload configuration */

		fptr = fopen(cf_str("udb"), "r");	/* check account exists */
		if (!fptr) {
			a = getpass("Password: ");	/* get password */
			printf("\a");	    /* (for appearances' sake) */
			fflush(stdout);
			continue;
		}
		fclose(fptr);

		wipe_environ();		    /* wipe environment */
		udb_load();		    /* load UDB */

		key[0] = 0;
		a = getenv("BBS_PASS");
		if (!a)
			a = "*";
		if (strcmp(a, "") != 0) {
			a = getpass("Password: ");
			if (a)
				strncpy(key, a, sizeof(key));
		} else {		    /* no password set */
			if (strcmp(buf, "guest") != 0) {	/* not a guest acct */
				printf
				    ("\n *** No password set for this account. *** \n\n"
				     "Internal users must set a BBS password to be able to log "
				     "in externally.\n"
				     "Do this by logging in internally and doing [ESC][Y][P].\n");
				fflush(stdout);
				continue;
			}
		}

		a = getenv("BBS_PASS");
		if (!a)
			a = "";

		salt[0] = a[0];
		salt[1] = a[1];
		salt[2] = 0;
		b = crypt(key, salt);
		if (strcmp(b, a) != 0) {    /* password incorrect */
			printf("\a");
			fflush(stdout);
			continue;
		}

		sprintf(buf, "/tmp/mbbs-%s-%d.XXXXXX", current_user,
			bbs__satellite);

		fd = mkstemp(buf);	    /* temp file creation failed */
		if (fd < 0) {
			printf("\a");
			fflush(stdout);
			continue;
		}

		close(fd);
		remove(buf);
		setenv("MVIEW_EDIT_TMP", buf, 1);

		if (strcmp(current_user, "guest") != 0) {	/* check duplicate sessions */

			uo_genlist();

			u = 0;

			for (j = 0; j < uo_list_len; j++) {
				if ((uo_list[j].username) &&
				    (!strcmp
				     (current_user, uo_list[j].username)))
					u = 1;
			}

			if (u) {	    /* duplicate session - prompt user */
				printf("\nYou are already logged in.\n");
				printf
				    ("Disconnect existing session? (yes|no) ");
				fflush(stdout);
				buf[0] = 0;
				fgets(buf, sizeof(buf) - 1, stdin);
				if (buf[0] == 'y' || buf[0] == 'Y') {	/* disconnect */
					sprintf(buf, "%s/%s",
						cf_str("status"),
						current_user);
					mkdir(buf, S_IRWXU | S_IRWXG);
					printf("Disconnecting...");
					fflush(stdout);
					for (j = 1; j < 30; j++) {	/* wait for success */
						sleep(1);
						t_bored(1);
						if (stat(buf, &sb))
							j = 99;	/* dir gone - succeeded */
					}
					t_bored(0);
					rmdir(buf);
					printf("\n");
				}
			}

		}

		return (0);
	}

	printf("\nToo many login attempts - aborting.\n\n");

	return (1);
}

/* EOF */
