/*
 *	init.c
 *	15.3.99 tn
 *
 *
 *  Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
 *
 *  This file is part of xcdroast.
 *
 *  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.
 */

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif

#include "largefile.h"

#include <locale.h>
#include "gettext.h"

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <string.h>
#include <strings.h>
#if defined(linux) || defined(__CYGWIN32__)
#include <getopt.h>
#endif


#if ENABLE_NLS
# define _(String) gettext (String)
# define N_(String) gettext_noop (String)
#else
# define _(String) (String)
# define N_(String) (String)
#endif

#include <gtk/gtk.h>
#include <gdk/gdk.h>
#include "xcdrdata.h"
#include "xcdroast.h"
#include "main.h"


static gint check_mode_suid(gchar *tmp);
static gint set_suid_bit_wrapper(gchar *wrapper);


GList *imagelist;
GList *tocfiles;
track_read_set_t trackreadset;

extern setup_data_t setupdata;
extern writerreader_devices_t **writerreaderdevs;
extern current_set_t curset;
extern cd_info_t cdinfo;
extern track_info_t **trackinfo;
extern GList *writelist;
extern write_track_param_t writeparams;
extern gint wav_in;
extern gint debug;
extern gchar xcdroast_version_loaded[MAXLINE];
extern master_param_t masterparam;
extern gint no_versioncheck;
extern GtkWidget *toplevel;
extern gchar **charset_types;
extern img_logo_t img;

gchar *system_platform;
gchar hostname[MAXLINE];
gchar username[MAXLINE];
gchar configdir[MAXLINE];
gchar sharedir[MAXLINE];
gchar rootconfig[MAXLINE];
gchar prefixdir[MAXLINE];
gint c_locale_is_utf8;
gchar *language = NULL;

/*
 * give the setupdata-structure valid startvalues
 */
static void init_setupdata() {
gchar tmp[MAXLINE];
gint fullaccess;

	setupdata.writer_devnr = -1;
	setupdata.reader_devnr = -1;

	setupdata.image_dirs = NULL;
	
	setupdata.dsp_device = g_strdup("");
	setupdata.mix_device = g_strdup("");
	setupdata.notify_via = 1;
	setupdata.notify_at = 0;

	setupdata.cddb_host = g_strdup("freedb.freedb.org");
	setupdata.cddb_port = 888;
	setupdata.cddb_proxy_host = g_strdup("");
	setupdata.cddb_proxy_port = 8080;
	setupdata.cddb_use_http = 0;
	setupdata.cddb_use_proxy = 0;

	g_snprintf(tmp,MAXLINE,"%s/%s", CONFIGDIR, LOGFILE);
	setupdata.logfile = g_strdup(tmp);
	setupdata.loglevel = 0;

	setupdata.language = g_strdup("");	

	setupdata.option_tooltips = 1;
	setupdata.option_autoraise = 0;
	setupdata.option_savepos = 0;
	setupdata.option_personimage = 0;
	setupdata.option_overwritewarn = 1;
	setupdata.option_autodelete = 0;
	setupdata.option_titleprogress = 0;
	setupdata.option_displaycdtext = 1;

	setupdata.root_users_access = 0;
	setupdata.root_users_lists = NULL;
	setupdata.root_hosts_access = 0;
	setupdata.root_hosts_lists = NULL;

	fullaccess = 1;

        setupdata.root_option_change_writer = fullaccess;
        setupdata.root_option_change_writeparam = fullaccess;
        setupdata.root_option_change_reader = fullaccess;
        setupdata.root_option_change_readparam = fullaccess;
        setupdata.root_option_change_imagedirs = fullaccess;
        setupdata.root_option_change_logoptions = fullaccess;

	setupdata.mainwindow.x = -1;
	setupdata.mainwindow.y = -1;
	setupdata.mainwindow.width = -1;
	setupdata.mainwindow.height = -1;

	setupdata.burnwindow.x = -1;
	setupdata.burnwindow.y = -1;
	setupdata.burnwindow.width = -1;
	setupdata.burnwindow.height = -1;
}


/*
 * init 'currently set' structure
 */
static void init_curset() {
gint cdrtypes[] = CDR_TYPES_MIN;
gint i;

	curset.isProDVD = 0;
	curset.writer_devnr = -1;
	curset.reader_devnr = -1;
	curset.image_index = -1;
	curset.proc_view = 2;
	curset.file_prefix = g_strdup("");
	curset.tocfile = g_strdup("");
	curset.writesimul = 0;
	curset.writeeject = 1;
	curset.writepad = 1;
	curset.writeswap = 0;
	curset.nofixate = 0;
	curset.multisession = 0;
	curset.writecdtext = 0;
	curset.writeoverburn = 0;
	curset.writeburnfree = 1;
	curset.writeaudiomaster = 0;
	curset.writeforcespeed = 0;
	curset.writevarirec = 100; 	/* -1 or 0 belong to valid values */
	curset.writeignsize = 0;
	curset.writeimmed = 0;
	curset.blankmode = 1;
	curset.blank_force = 0;
	curset.blank_eject = 1;
	curset.noaudioverify = 0;
	curset.verifyfailabort = 0;
	curset.indexscan = 1;		/* also scans subchannel Q for preemphasis */
	curset.deemphasize = 0;
	curset.sync_cdtext_artist = 0;
	curset.mstr_auto_calc = 1;
	curset.sudo_passwd = NULL;

	/* find out default value for cdrtype */
	curset.cdrtype = 0;
	i = 0;
	while (cdrtypes[i] != 0) {
		if (cdrtypes[i] < 0) {
			curset.cdrtype = abs(cdrtypes[i]);
		}
		i++;
	}	
}


/*
 * init cdinfo and trackinfo-structure
 */
static void init_cdinfo() {

	cdinfo.nr_tracks = 0;
	cdinfo.total_size = 0;
	strcpy(cdinfo.cddb_discid,"00000000");
	cdinfo.have_cdtext = 0;
	cdinfo.have_cdextra = 0;
	cdinfo.title = NULL;
	cdinfo.artist = NULL;
	cdinfo.cddb_dtitle = NULL;
	cdinfo.leadout = 0;	

	/* allocate tracks */
	trackinfo = g_new0(track_info_t *,MAXTRACKS);
}


/*
 * init trackreadset-variable
 */
static void init_trackreadset() {

	trackreadset.nrtracks = 0;
	trackreadset.tocfile = g_strdup("");
	trackreadset.cdtitle = g_strdup("");
	trackreadset.cd_discid = g_strdup("");
	trackreadset.trackparams = NULL;
}


/*
 * init writeparams-structure
 */
static void init_writeparams() {

	writeparams.nrtracks = 0;
	writeparams.simulation = 0;
	writeparams.tracktype = NULL;
	writeparams.frames = NULL;
	writeparams.pct_so_far_arr = NULL;
	writeparams.pct_this_track_arr = NULL;
}


/*
 * init master-parameters
 */
static void init_masterparams() {
int i;

	masterparam.mstr_redir = NULL;
	masterparam.exclude_paths = NULL;
	masterparam.show_only_dirs = 1;
	masterparam.show_hidden_files = 0;
	masterparam.image_type = -1;
	for (i=0; i<22; i++) 
		masterparam.opt[i] = 0;	
	masterparam.bootable = 0;
	masterparam.boot_image = g_strdup("");
	masterparam.boot_catalog = g_strdup(DEF_BOOT_CATALOG);
	masterparam.boot_type = 0;
	masterparam.boot_load_size = -1;
	masterparam.boot_info_table = 0;
	masterparam.sparc_boot = g_strdup("");
	masterparam.volid = g_strdup("");
	masterparam.publisher = g_strdup("");
	masterparam.preparer = g_strdup("");
	masterparam.application = g_strdup("");
	masterparam.abstract = g_strdup("");
	masterparam.biblio = g_strdup("");
	masterparam.copyright = g_strdup("");
	masterparam.image_filename = g_strdup("");
	masterparam.old_session_size = 0;
	masterparam.session_size = 0;
	masterparam.charset = 0;
	masterparam.cust_charset = g_strdup(ICONV_CUSTOM_CHARSET);
	masterparam.outcharset = 0;
	masterparam.cust_outcharset = g_strdup(ICONV_CUSTOM_CHARSET);
	masterparam.redirtype = 2;
	masterparam.lastredirpath = g_strdup("");
	masterparam.redirtype2 = 0;
	masterparam.lastredirpath2 = g_strdup("");
	masterparam.last_session_start = -1;
	masterparam.next_session_start = -1;
}


/*
 * make a stat on a file return 1 if it does exist, 0 if not
 */
gint stat_file(gchar *file) {
struct stat buf;
gchar tmp[MAXLINE];
gchar tmp2[MAXLINE];
gchar *p;

	/*
	 * first strip off anything after
	 * a space in filename (arguments)
	 */
	strcpy(tmp,file);
	p = strtok(tmp," ");
	if (p != NULL) {
		strcpy(tmp2,p);
		strcpy(tmp,tmp2);
	}

	/* file does exist? */
	if (stat(tmp,&buf) == 0) {
		if (!(buf.st_mode & S_IEXEC)) {
			g_warning("%s not executable\n", file);
			gtk_exit(1);
		}
		return 1;
	} 
	return 0;
}


/*
 * check if a given file got the suid-bit set
 * return 0 if not set, 1 if set
 */
static gint suid_set(gchar *file) {
struct stat buf;

	/* file does exist? */
	if (stat(file,&buf) == 0) {
		if (!(buf.st_mode & S_ISUID)) {
			return 0;
		}
	}

	return 1;
}

/*
 * stat a file and see if its a binary
 */
static gint check_executable(gchar *file, gchar *altfile, gint share, gint exit_on_fail) {
gint second;

	second = 0;
	if (altfile != NULL) {
		second = stat_file(altfile);
	}

	if (stat_file(file) == 0 && !second) {
		if (altfile == NULL) 
			g_warning("No %s installed\n", file);
		else
			g_warning("No %s or %s installed\n", file, altfile);
			
		if (share) 
			g_warning("(Invalid lib-directory? Check -l option)\n");
		if (exit_on_fail)
			gtk_exit(1);
		else	
			return(1);
	}

	return 0;
}

/*
 * check if needed binaries are installed and have the right permissions
 * Allow user to set the SUID-Bit on the wrapper if needed
 * return if proDVD version found
 */
static gint check_binaries(gint noversioncheck) {
gchar tmp[MAXLINE];
gchar tmp2[MAXLINE*5];
gchar ver[MAXLINE];
gchar link[MAXLINE];
gint isProDVD;
gchar version_cdrecord[MAXLINE];
gchar version_mkisofs[MAXLINE];
gchar version_readcd[MAXLINE];
gchar version_cdda2wav[MAXLINE];
gint stat_cdrecord;
gint stat_mkisofs;
gint stat_cdda2wav;
gint stat_readcd;
gint set_suid_cdrecord;
gint set_suid_cdda2wav;
gint set_suid_readcd;
gint set_suid_wrapper;
gint suid_setup_ok;
gint ret;
	
	isProDVD = 0;
	check_executable(UNAME,UNAME2,0,1);
	check_executable(DF,DF2,0,1);

	get_spawn_path(CDRECORD,tmp);
	if (check_islink(tmp, link)) {
		dodebug(3, "%s is a link to %s\n", tmp, link); 
	}
	if (stat_file(tmp) == 0) {
		toplevel = gtk_window_new(GTK_WINDOW_TOPLEVEL);
		gtk_widget_realize(toplevel);
		set_wm_icon();
		g_snprintf(ver,MAXLINE, _("Failed to access %s.\nPlease install the cdrtools."), tmp);
                show_dialog(ICO_WARN, ver, T_EXIT, NULL, NULL, 0);
		gtk_exit(1);
	}
	stat_cdrecord = check_version_cdrecord(CDRECORD_VERSION, version_cdrecord, &isProDVD);
	dodebug(10, "Found version %s for %s\n", version_cdrecord, CDRECORD); 

	dodebug(10, "Checking suid-bit/owner on %s\n", tmp); 
	if (!check_mode_suid(tmp)) 
		set_suid_cdrecord = FALSE;
	else	
		set_suid_cdrecord = TRUE;

	get_spawn_path(MKISOFS,tmp);
	if (check_islink(tmp, link)) {
		dodebug(3, "%s is a link to %s\n", tmp, link); 
	}
	if (stat_file(tmp) == 0) {
		toplevel = gtk_window_new(GTK_WINDOW_TOPLEVEL);
		gtk_widget_realize(toplevel);
		set_wm_icon();
		g_snprintf(ver,MAXLINE, _("Failed to access %s.\nPlease install the cdrtools."), tmp);
                show_dialog(ICO_WARN, ver, T_EXIT, NULL, NULL, 0);
		gtk_exit(1);
	}
	stat_mkisofs = check_version_mkisofs(MKISOFS_VERSION,version_mkisofs);
	dodebug(10, "Found version %s for %s\n", version_mkisofs, MKISOFS); 

	get_spawn_path(READCD,tmp);
	if (check_islink(tmp, link)) {
		dodebug(3, "%s is a link to %s\n", tmp, link); 
	}
	if (stat_file(tmp) == 0) {
		toplevel = gtk_window_new(GTK_WINDOW_TOPLEVEL);
		gtk_widget_realize(toplevel);
		set_wm_icon();
		g_snprintf(ver,MAXLINE, _("Failed to access %s.\nPlease install the cdrtools."), tmp);
                show_dialog(ICO_WARN, ver, T_EXIT, NULL, NULL, 0);
		gtk_exit(1);
	}
	stat_readcd = check_version_readcd(READCD_VERSION,version_readcd);
	dodebug(10, "Found version %s for %s\n", version_readcd, READCD); 

	dodebug(10, "Checking suid-bit/owner on %s\n", tmp); 
	if (!check_mode_suid(tmp)) 
		set_suid_readcd = FALSE;
	else	
		set_suid_readcd = TRUE;

	get_spawn_path(CDDA2WAV,tmp);
	if (check_islink(tmp, link)) {
		dodebug(3, "%s is a link to %s\n", tmp, link); 
	}
	if (stat_file(tmp) == 0) {
		toplevel = gtk_window_new(GTK_WINDOW_TOPLEVEL);
		gtk_widget_realize(toplevel);
		set_wm_icon();
		g_snprintf(ver,MAXLINE, _("Failed to access %s.\nPlease install the cdrtools."), tmp);
                show_dialog(ICO_WARN, ver, T_EXIT, NULL, NULL, 0);
		gtk_exit(1);
	}
	stat_cdda2wav = check_version_cdda2wav(CDDA2WAV_VERSION,version_cdda2wav);
	dodebug(10, "Found version %s for %s\n", version_cdda2wav, CDDA2WAV); 

	dodebug(10, "Checking suid-bit/owner on %s\n", tmp); 
	if (!check_mode_suid(tmp)) 
		set_suid_cdda2wav = FALSE;
	else	
		set_suid_cdda2wav = TRUE;

	/* check total cdrtools versions */
	if (!noversioncheck) {
		if (stat_cdrecord != 0 || stat_mkisofs != 0 || stat_readcd != 0 || stat_cdda2wav != 0) {

			g_snprintf(tmp2,MAXLINE,_("Outdated version of the cdrtools detected:\n\n"));
			if (stat_cdrecord != 0)  {
				g_snprintf(tmp, MAXLINE, _("  %s version found: %s  - expected at least: %s\n"), "cdrecord", version_cdrecord, CDRECORD_VERSION);
				strcat(tmp2, tmp);
			}
			if (stat_mkisofs != 0)  {
				g_snprintf(tmp, MAXLINE, _("  %s version found: %s  - expected at least: %s\n"), "mkisofs", version_mkisofs, MKISOFS_VERSION);
				strcat(tmp2, tmp);
			}
			if (stat_readcd != 0)  {
				g_snprintf(tmp, MAXLINE, _("  %s version found: %s  - expected at least: %s\n"), "readcd", version_readcd, READCD_VERSION);
				strcat(tmp2, tmp);
			}
			if (stat_cdda2wav != 0)  {
				g_snprintf(tmp, MAXLINE, _("  %s version found: %s  - expected at least: %s\n"), "cdda2wav", version_cdda2wav, CDDA2WAV_VERSION);
				strcat(tmp2, tmp);
			}
			g_snprintf(tmp,MAXLINE,_("\nIt is not recommended to continue..."));
			strcat(tmp2, tmp);

			toplevel = gtk_window_new(GTK_WINDOW_TOPLEVEL);
			gtk_widget_realize(toplevel);
			set_wm_icon();
                	ret = show_dialog(ICO_WARN, tmp2, T_ANYWAY, T_EXIT, NULL, 1);
			if (ret == 1)
				gtk_exit(1);

			dodebug(1, "-> Continuing with invalid versions...\n");
		}
	} else  {
		if (stat_cdrecord != 0 || stat_mkisofs != 0 || stat_readcd != 0 || stat_cdda2wav != 0) {
			dodebug(1, "-> Continuing with invalid versions...\n");
		}
	}

	g_snprintf(tmp,MAXLINE,"%s/%s", sharedir, WAVPLAY);
	check_executable(tmp,NULL,1,1);
	g_snprintf(tmp,MAXLINE,"%s/%s", sharedir, RMTOOL);
	check_executable(tmp,NULL,1,1);
	g_snprintf(tmp,MAXLINE,"%s/%s", sharedir, VRFYTOOL);
	check_executable(tmp,NULL,1,1);
	g_snprintf(tmp,MAXLINE,"%s/%s", sharedir, CDDBTOOL);
	check_executable(tmp,NULL,1,1);

	/* now check the suid rights of the cdrtools and the wrapper */
	g_snprintf(tmp,MAXLINE,"%s/%s", sharedir, WRAPPER);
	check_executable(tmp,NULL,1,1);

	dodebug(10, "Checking suid-bit/owner on %s\n", tmp); 
	if (!check_mode_suid(tmp)) 
		set_suid_wrapper = FALSE;
	else	
		set_suid_wrapper = TRUE;

	suid_setup_ok = FALSE;
	/* we are good if have the suid bits on the cdrtools */
	if (set_suid_cdrecord && set_suid_cdda2wav && set_suid_readcd)
		suid_setup_ok = TRUE;

	/* we are also good if the wrapper has the suid bit set */
	if (set_suid_wrapper)
		suid_setup_ok = TRUE;

	if (!suid_setup_ok)
	{
		dodebug(3, "Invalid Setting of SUID bits on cdrtools or wrapper.\n"); 

		/* allow the user to set the suid bit via graphical sudo wrapper */
		toplevel = gtk_window_new(GTK_WINDOW_TOPLEVEL);
		gtk_widget_realize(toplevel);
		set_wm_icon();
		g_snprintf(tmp2, MAXLINE,_("Invalid file permissions on the X-CD-Roast binaries.\nNo SUID-Bit on the file \"%s\".\n\nShall X-CD-Roast try to fix this automatically?\n"), tmp);
 
#if (USER_HOST_MODE == 0) 
		if (isroot())
                	ret = show_fancy_dialog(_("Warning:"), tmp2, T_OK, T_ANYWAY, 1);
		else
                	ret = show_fancy_dialog(_("Warning:"),  tmp2, T_OK, T_EXIT, 1);

		if (ret == 1 && !isroot())
			gtk_exit(1);

		/* we are root and clicked on "continue anyway" */
		if (ret == 1 && isroot())
			return isProDVD;
#else
		/* force this in user-host-mode */
                ret = show_fancy_dialog(_("Warning:"),  tmp2, T_OK, T_EXIT, 1);
		if (ret == 1)
			gtk_exit(1);
#endif

		set_suid_bit_wrapper(tmp);
		
		/* check again, if we fixed the problem */
		if (check_mode_suid(tmp)) {
			show_dialog(ICO_INFO,_("Permissions successfully set."),T_OK,NULL,NULL,0);
		} else  {
			g_snprintf(tmp2, MAXLINE,_("The automatic set of the permissions failed.\nYou can set them manually by running this command in a terminal:\n\nsudo chmod 4711 %s"), tmp);
                	show_dialog(ICO_WARN, tmp2, T_EXIT, NULL, NULL, 0);
			gtk_exit(1);
		}
	} 

	return isProDVD;
}


/*
 * check the wrapper binary
 * return 1 when user got no permission
 * return 2 if rootconfig not readable
 */
static gint check_wrapper_binary() {
gchar tmp[MAXLINE];
gint stat;

	g_snprintf(tmp,MAXLINE,"%s/%s", sharedir, WRAPPER);
	check_executable(tmp,NULL,1,1);

	/* security check. If this fails then the wrapper is wrong */
	stat = check_version_wrapper(tmp);
	if (stat == 1) {
		fprintf(stderr, "Aborting...\n");
		gtk_exit(1);
	}
	if (stat == 2) {
		/* this user is not allowed to start the wrapper */
		return 1;
	}
	if (stat == 3) {
		/* no rootconfig readable */
		return 2;
	}

	return 0;
}


/*
 * check if we have at least 800x600 screen size
 * for bigfonts we need 1024x720
 * (see xcdroast.h & main.c)
 */
gint check_screensize(gint bigfonts) {
gint xsize, ysize;

	xsize = gdk_screen_width();
	ysize = gdk_screen_height();
	dodebug(10, "Screen size: %d x %d, bigfonts = %d\n", xsize, ysize, bigfonts);

	if (bigfonts == 0) {
		if (xsize < 800 || ysize < 600) 
			return 1;
	} else {
		if (xsize < 1024 || ysize < 720) 
			return 1;
	}
	return 0;
}


/*
 * graphical interface for suid set the wrapper
 * return 0 on success
 */
static gint set_suid_bit_wrapper(gchar *wrapper) {
gchar tmp[MAXLINE];
gchar cmd_chmod[MAXLINE];
gint ret;
gchar *env;

        get_chmod_cmd(cmd_chmod);
        if (cmd_chmod[0] == '\0') {
                fprintf(stderr, "Error: No chmod command found.");
                return 1;
        }

	/* we are root, set permissions directly */
	if (isroot())
	{
		g_snprintf(tmp, MAXLINE, "%s 4711 %s", cmd_chmod, wrapper);
		ret = exec_sudo(tmp);
		dodebug(3, "Return-code: %d.\n", ret); 

		return ret;
	}

	/* find tools for sudo call */
	if (stat_file(GKSUDO_BINARY)) {
		g_snprintf(tmp, MAXLINE, "%s -u root -D '%s' %s 4711 %s", GKSUDO_BINARY, T_XCDROAST, cmd_chmod, wrapper);
		ret = exec_sudo(tmp);
		dodebug(3, "Return-code: %d.\n", ret); 

		return ret;
	}

	/* try this next */
	env = getenv("SUDO_ASKPASS");
	if (env) {
		dodebug(10, "Found environment variable SUDO_ASKPASS=%s.", env);
		g_snprintf(tmp, MAXLINE, "%s -A %s 4711 %s", SUDO_BINARY, cmd_chmod, wrapper);
		ret = exec_sudo(tmp);
		dodebug(3, "Return-code: %d.\n", ret); 

		return ret;

	}	

	/* give up */
	return -1;
}


#if (USER_HOST_MODE == 1)

/*
 * do check if the current user and host is allowed to start xcdroast
 * return 1 if so, 0 if denied
 */
static gint checkuserhost(gchar *username,gchar *hostname) {
gint userok, hostok;
gint match;
GList *loop;

	match = 0;
	/* user first */
	if (setupdata.root_users_access == 0) {
		userok = 1;
	} else 
	if (setupdata.root_users_access == 1) {
		userok = 0;
	} else {
		loop = g_list_first(setupdata.root_users_lists);
		while (loop) {
			if (strcmp(username,(gchar *)loop->data) == 0) {
				/* found our login on the list */
				match = 1;
			}		
			loop = loop->next;
		}
		if ((setupdata.root_users_access == 2 && match) ||
		    (setupdata.root_users_access == 3 && !match)) {
			userok = 1;
		} else  {
			userok = 0;
		}
	}	

	match = 0;
	/* now check host */
	if (setupdata.root_hosts_access == 0) {
		hostok = 1;
	} else 
	if (setupdata.root_hosts_access == 1) {
		hostok = 0;
	} else {
		loop = g_list_first(setupdata.root_hosts_lists);
		while (loop) {
			if (strcmp(hostname,(gchar *)loop->data) == 0) {
				/* found our login on the list */
				match = 1;
			}		
			loop = loop->next;
		}
		if ((setupdata.root_hosts_access == 2 && match) ||
		    (setupdata.root_hosts_access == 3 && !match)) {
			hostok = 1;
		} else  {
			hostok = 0;
		}
	}

	/* only when both the host and the user are allowed, allow access */
	if (userok && hostok) {
		return 1;
	} else {
		return 0;
	}
}
#endif


/*
 * returns if a executable got right permissions if we are not user root
 */
static gint check_mode_suid(gchar *tmp) {
gid_t bin_owner;
gint nofail;
	
	nofail = 1;
	bin_owner = get_file_owner(tmp);
	if (bin_owner != 0) {
		dodebug(3,"Note: %s not owned by root.\n", tmp);
		nofail = 0;
	}
	if (suid_set(tmp) == 0) {
		dodebug(3,"Note: %s has no suid-bit set.\n", tmp);
		nofail = 0;
	}

	return nofail;
}


/*
 * print usage-info
 */
static void usage(gchar *cmd) {

	g_print("Usage: %s [options]  (Version: %s)\n", cmd, XCDROAST_VERSION);
	g_print("Options:\n");
	g_print("\t-d <debug level>\n");
	g_print("\t-c <config directory>  (currently: %s)\n", configdir);
	g_print("\t-l <lib directory>     (currently: %s)\n", sharedir);
	g_print("\t-n : Disable cdrtools version check (use at own risk)\n");
	g_print("\t-w : Don't use cdrecord-ProDVD, even when it is available.\n");
	g_print("\t-a : Disable alternative device scans\n");
	g_print("\t-f \"<list of scsi-devices>\" : Instead of automatic scanning force\n\t     X-CD-Roast to use the given devices (semicolon seperated list).\n\t     You can set these also within the setup-menu.\n");
	
	g_print("Some GTK-Options:\n");
	g_print("\t--display <remote host>\n");
	g_print("\t--sync\n");
	g_print("\t--no-xshm\n");
}


/*
 * Misc-init-stuff. stuff done once at program-startup
 * return 0 if config file ok loaded, 1 on failure
 */
gint init(gint argc, gchar *argv[], gint *altdevscan) {
gchar tmp[MAXLINE];
gchar basedir[MAXLINE];
gchar *mylocale;
gchar *p1;
gchar *alt_dev_string;
gint c, usercnf, stat;
gint isProDVD, ignoreProDVD;
	
	if (!language) 
		language = g_strdup("");
	debug = 0;
	*altdevscan = 1;
	no_versioncheck = 0;
	c_locale_is_utf8 = 0;
	ignoreProDVD = 0;
	alt_dev_string = NULL;
	strncpy(configdir, CONFIGDIR, MAXLINE);
	g_snprintf(rootconfig, MAXLINE, "%s/%s", SYSCONFDIR, ROOTCONFIG);
	writerreaderdevs = NULL;

#ifdef PRE_LIBDIR 
	/* use prefix as sharedir as it came from the makefile-option */
	strncpy(sharedir, PRE_LIBDIR, MAXLINE);
#else
	/* otherwise install our default prefix */
	strncpy(sharedir, LIBDIR, MAXLINE);
#endif

#ifdef CDRTOOLS_PREFIX
        /* use prefix as it came from the makefile-option */
        strncpy(prefixdir, CDRTOOLS_PREFIX, MAXLINE);
#else
# ifdef PREFIX
	/* use prefix as it came from the makefile-option */
	strncpy(prefixdir, PRE_PREFIX, MAXLINE);
# else
	/* otherwise install our default prefix */
	strncpy(prefixdir, PREFIX, MAXLINE);
# endif	
#endif	

	/* parse command-line */
	while ((c = getopt(argc,argv,"d:c:l:anwf:")) != EOF)
	switch ((gchar)c) {
	
	case 'd':
		debug = atoi(optarg);
		break;

	case 'c':
		strncpy(configdir, optarg, MAXLINE);
		break;

	case 'l':
		strncpy(sharedir, optarg, MAXLINE);
		break;

	case 'a':
		*altdevscan = 0;
		break;

	case 'n':
		no_versioncheck = 1;
		break;

	case 'w':
		ignoreProDVD = 1;
		break;

	case 'f':
		alt_dev_string = g_strdup(optarg);
		break;

	default:
		usage(argv[0]);
		gtk_exit(1);
	}
	
	/* init random generator */
	srand(time(NULL));

	/* get some system-info */
	system_platform = g_strdup(strip_string(get_uname_info(tmp)));
	if (gethostname(hostname,MAXLINE) != 0) {
		strncpy(hostname,"not_available",MAXLINE);
	}

	p1 = (gchar *) g_get_user_name();
	if (p1 != NULL) {
		strncpy(username,p1, MAXLINE);
	} else {
		strncpy(username,"not_available",MAXLINE);
	}

	/* subst ~/ by $HOME */
	check_tilde(configdir);

	dodebug(1, "Starting X-CD-Roast %s by %s@%s on %s\n", 
		XCDROAST_VERSION,  username, hostname, system_platform);
	dodebug(1, "debug level: %d\n", debug);
	dodebug(1, "configdir: %s\n", configdir);
#if (USER_HOST_MODE == 1)
	dodebug(1, "rootconfig: %s\n", rootconfig);
#endif
	dodebug(1, "libdir: %s\n",sharedir);
	dodebug(1, "checking large file support: sizeof(off_t) = %d\n", sizeof(off_t));

	/* gettext stuff */
	mylocale = setlocale (LC_ALL, "");
	if (mylocale) {
		dodebug(1, "my locale: %s\n", mylocale);
		if (strstr(mylocale, "UTF-8")) {
			c_locale_is_utf8 = 1;
		}
	}
	setlocale (LC_NUMERIC, "C");

        /* load the logo images */
        g_snprintf(tmp, MAXLINE, "%s/%s", sharedir, XCDRLOGO);
        img.xcdrlogo = cairo_image_surface_create_from_png(tmp);
        g_snprintf(tmp, MAXLINE, "%s/%s", sharedir, XCDRLOGO_MIDDLE);
        img.xcdrlogo_middle = cairo_image_surface_create_from_png(tmp);
        g_snprintf(tmp, MAXLINE, "%s/%s", sharedir, XCDRLOGO_SMALL);
        img.xcdrlogo_small = cairo_image_surface_create_from_png(tmp);
        g_snprintf(tmp, MAXLINE, "%s/%s", sharedir, CDDBLOGO);
        img.cddblogo = cairo_image_surface_create_from_png(tmp);

	/* get current status of user-host-mode */
#if (USER_HOST_MODE == 0) 
	dodebug(1,"-- X-CD-Roast compiled without --enable-user-host-mode.\n");
#else
	dodebug(1,"-- X-CD-Roast compiled with --enable-user-host-mode.\n");
#endif

	/* check if the systemconfig-directory exists */
	if (!is_directory(SYSCONFDIR)) {
		toplevel = gtk_window_new(GTK_WINDOW_TOPLEVEL);
		gtk_widget_realize(toplevel);
		set_wm_icon();
		g_snprintf(tmp,MAXLINE, _("The configured system-config-directory \"%s\"\n\twas not found. Aborting...\n"), SYSCONFDIR);
                show_dialog(ICO_WARN, tmp, T_OK, NULL, NULL, 0);
		gtk_exit(1);
	}

	dodebug(3, "Checking X-CD-Roast wrapper installation\n");
	stat = check_wrapper_binary();
	if (stat == 1) {
		/* we need a toplevel for the show_dialog function */
		toplevel = gtk_window_new(GTK_WINDOW_TOPLEVEL);
		gtk_widget_realize(toplevel);
		set_wm_icon();
		show_fancy_dialog(_("Warning:"), _("Access denied!\nYou have no permission to start X-CD-Roast on that host.\nAsk the superuser to add you to the allow-list."), T_OK, NULL, 0);
		gtk_exit(1);
	}

	/* no root config file yet */
	if (stat == 2) {
		if (!isroot()) {
			/* we need a toplevel for the show_dialog function */
			toplevel = gtk_window_new(GTK_WINDOW_TOPLEVEL);
			gtk_widget_realize(toplevel);
			set_wm_icon();
			show_fancy_dialog(_("Warning:"), _("No root configuration file found or not readable!\nThe superuser must start and configure X-CD-Roast\nfirst, before other users can use it."), T_OK, NULL, 0);
			gtk_exit(1);
		}
	}

	dodebug(3, "Checking for helper binaries (noversioncheck = %d)\n", no_versioncheck);
	isProDVD = check_binaries(no_versioncheck);

	if (isProDVD) {
		if (ignoreProDVD) {
			isProDVD = 0;
			dodebug(1,"-> cdrecord.ProDVD detected but disabled\n");
		} else {	
			dodebug(1,"-> cdrecord.ProDVD detected\n");
		}
	} else {
		dodebug(1,"-> cdrecord.ProDVD not detected\n");
	}

	/* config-directory available? */
	if (!is_directory(configdir)) {
		/* try to create directory */
		strncpy(basedir, configdir, MAXLINE);
		if (get_basedir(basedir) != NULL)
			mkdir(basedir, 0700);

		mkdir(configdir, 0700);
		dodebug(2, "trying to mkdir %s\n", configdir);
	}

	/* any options given with -f? */
	parse_alt_devs(alt_dev_string);

	scandrivers();
	scanblankmodes();
	scancharsets();

	dodebug(3, "Initializing global data structures\n");
	wav_in = -1;
	init_setupdata();
	init_curset();
	init_cdinfo();
	init_trackreadset();
	init_writeparams();
	init_masterparams();
	imagelist = (GList *) NULL;
	writelist = (GList *) NULL;
	tocfiles = (GList *) NULL;
	strcpy(xcdroast_version_loaded, "");

	curset.isProDVD = isProDVD;

	/* load iso-options if available */
	g_snprintf(tmp,MAXLINE,"%s/%s", configdir, ISOOPTFILE);
	load_isooptions_file(tmp);

	/* load iso-headers if available */
	g_snprintf(tmp,MAXLINE,"%s/%s", configdir, ISOHEADERFILE);
	load_isoheaders_file(tmp);

	/* load write options if available */
	g_snprintf(tmp,MAXLINE,"%s/%s", configdir, WRITEOPTFILE);
	load_writeoptions_file(tmp);

	/* first load config-file from root */

#if (USER_HOST_MODE == 1) 
	if (load_setup_config(rootconfig,1) != 0) {
		/* failed */
		if (!isroot()) {
			/* we need a toplevel for the show_dialog function */
			toplevel = gtk_window_new(GTK_WINDOW_TOPLEVEL);
			gtk_widget_realize(toplevel);
			set_wm_icon();
			show_fancy_dialog(_("Warning:"), _("No root configuration file found or not readable!\nThe superuser must start and configure X-CD-Roast\nfirst, before other users can use it."), T_OK, NULL, 0);
			gtk_exit(1);
		} else {
			/* first start for root - let him create config */
			return 1;
		}
	}

	/* set the language to the one defined in the root config */
        if (strcmp(setupdata.language, "") != 0) {
		g_free(language);
	        language = g_strdup(setupdata.language);
		setlocale (LC_ALL, language);
		setlocale (LC_NUMERIC, "C");
		putenv("G_FILENAME_ENCODING=UTF-8");
		dodebug(3, "Setting language to %s\n", language);
       	}

	/* now check if the loaded root-config was really from root */
	if (get_file_owner(rootconfig) != 0) {
		/* we need a toplevel for the show_dialog function */
		toplevel = gtk_window_new(GTK_WINDOW_TOPLEVEL);
		gtk_widget_realize(toplevel);
		set_wm_icon();
		show_dialog(ICO_WARN, _("The root configuration file is not owned by root!\nAborting..."), T_OK, NULL, NULL, 0);
		gtk_exit(1);
	}

	/* here check if the current user is allowed to run xcdroast */
	if (!isroot()) {
		if (!checkuserhost(username,hostname)) {
			/* we need a toplevel for the show_dialog function */
			toplevel = gtk_window_new(GTK_WINDOW_TOPLEVEL);
			gtk_widget_realize(toplevel);
			set_wm_icon();
			show_fancy_dialog(_("Warning:"), _("Access denied!\nYou have no permission to start X-CD-Roast on that host.\nAsk the superuser to add you to the allow-list."), T_OK, NULL, 0);
			gtk_exit(1);
		}
	}

#endif

	/* tmp dir writeable? */
	if (is_dir_writeable(TMP_XCDR_DIR) == 1) {
		toplevel = gtk_window_new(GTK_WINDOW_TOPLEVEL);
		gtk_widget_realize(toplevel);
		set_wm_icon();
		g_snprintf(tmp,MAXLINE,_("The temporary directory \"%s\" is not writeable.\nAborting..."), TMP_XCDR_DIR);
		show_dialog(ICO_WARN, tmp, T_OK, NULL, NULL, 0);
		gtk_exit(1);
	} else {
		/* writeable - but how many space free? */
		if (get_free_space(TMP_XCDR_DIR, NULL) == 0) {
			toplevel = gtk_window_new(GTK_WINDOW_TOPLEVEL);
			gtk_widget_realize(toplevel);
			set_wm_icon();
			g_snprintf(tmp,MAXLINE,_("No free space in the temporary directory \"%s\".\nAborting..."), TMP_XCDR_DIR);
			show_dialog(ICO_WARN, tmp, T_OK, NULL, NULL, 0);
			gtk_exit(1);
		}
	}

	/* load user config file - if possible */
	g_snprintf(tmp,MAXLINE,"%s/%s", configdir, CONFFILE);


#if (USER_HOST_MODE == 1) 
	if (!isroot()) {
		/* load only when not root */
		usercnf = load_setup_config(tmp,0);
	} else {
		usercnf = 0;
	}
#else
	usercnf = load_setup_config(tmp,0);
#endif
	if (usercnf == 0) {
		/* load ok */

		/* set language to the one in user-config */
        	if (strcmp(setupdata.language, "") != 0) {
			g_free(language);
	        	language = g_strdup(setupdata.language);

			setlocale (LC_ALL, language);
			setlocale (LC_NUMERIC, "C");
			putenv("G_FILENAME_ENCODING=UTF-8");
			dodebug(3, "Setting language to %s\n", language);
       		}
		return 0;
	} else {
		/* load failed */
		strcpy(xcdroast_version_loaded,"");
		return 1;
	}
}

