#define MAINPROGRAM

#include "main.h"

struct sigaction sigint_vec,sigint_ovec;

#define GET_STATIC_CONFIG    1

getmsg_t   getl[]= {
			{t_static_configuration,
                          "Static Configuration (TRUE/FALSE)", 
                         "FALSE",
                         "Setting FALSE will commit all programs to read the conf_file\n   each time they startup\n",
                         "See The ConfigurationFile in the DQS 3.2 Installation \n and Maintenance Manual" },

                        {t_has_automounter,
                         "Does Your Site Use Automounter(TRUE/FALSE)",
                         "FALSE",
                         "DQS will append the automount prefix for file\n",
                          "See The ConfigurationFile in the DQS 3.2 Installation \n  and Maintenance Manual" },

                        {t_automounter_prefix,
                         "Enter Automount Prefix",
                         "/tmp_mnt",
                         "This prefix will be appended to all DQS managed files\n",
                         "See The ConfigurationFile in the DQS 3.2 Installation \n and Maintenance Manual" },

			{t_use_AFS ,
                         "Does Your Site have AFS (TRUE/FALSE)",
                         "FALSE",
                         "The Andrew File System provides additional security support,\n   but requires additional administrative information for DQS\n",
                         "See  AFS Operation in the DQS 3.2 Installation and Maintenance Manual" },

			{t_klog,
                         "Which klog will you be using ?",
			 "/usr/local/bin/klog",
			  "",
                         "See  AFS Operation in the DQS 3.2 Installation and Maintenance Manual\n" },

                        {t_reauth_time,
                         "enter reauthentication time in seconds",
                         "60",
                         "The qmaster will reauthenticate all running jobs at this interval.\n",
                         "See  AFS Operation in the DQS 3.2 Installation and Maintenance Manual" },

                         
                        {t_use_reserved_port,
                         "Use Reserved ports (TRUE/FALSE) ?",
                          "TRUE",
	                  "Use of reserved ports requires operation of DQS qmaster \n  and dqs_execd as root\n",
                          "See System Management in the DQS 3.2 Installation \n and Maintenance Manual" },

                        {t_no_use_reserved_port,
                         "Use Reserved ports (TRUE/FALSE) ?",
                          "FALSE",
                          "Use of reserved ports requires operation of DQS qmaster \n  and dqs_execd as root\n",
			 "See System Management in the DQS 3.2 Installation \n and Maintenance Manual" },

                        {t_qmaster_service,
                         "Enter port name for qmaster service",
                         "dqs32_qmaster",
                         "This name will be entered in the conf_file and /etc/services\n",
                          "See System Management in the DQS 3.2 Installation \n and Maintenance Manual" },

                        {t_keep_qmaster_entry,
			"Do you wish to keep this port name for the qmaster service (yes/no) ?",
                         "NO",
                         "The port name must be unique among the names in /etc/services\n",
                          "See System Management in the DQS 3.2 Installation \n   and Maintenance Manual" },

                        {t_qmaster_service_ur,
                         "Enter port name for qmaster service",
                         "dqs32_qmaster_ur",
                         "This name will be entered in the conf_file and /etc/services\n",
                          "See System Management in the DQS 3.2 Installation \n and Maintenance Manual" },

                        {t_keep_qmaster_entry_ur,
                        "Do you wish to keep this port name for the qmaster service (yes/no) ?",
                         "NO",
                         "The port name must be unique among the names in /etc/services\n",
                          "See System Management in the DQS 3.2 Installation \n   and Maintenance Manual" },

                        { t_dqs_execd_service,
			"Enter port name for the dqs_execd service",
                         "dqs32_dqs_execd",                          
                         "This name will be entered in the conf_file and /etc/services\n",
                          "See System Management in the DQS 3.2 Installation \n and Maintenance Manual" },

                        {t_keep_dqs_execd_entry,
			"Do you wish to keep this port name for the dqs_execd service (yes/no) ?",
                         "NO",
                         "The port name must be unique among the names in /etc/services\n",
                          "See System Management in the DQS 3.2 Installation \n and Maintenance Manual" },


                        { t_dqs_execd_service_ur,
                        "Enter port name for the dqs_execd service",
                         "dqs32_dqs_execd_ur",
                         "This name will be entered in the conf_file and /etc/services\n",
                          "See System Management in the DQS 3.2 Installation \n and Maintenance Manual" },

                        {t_keep_dqs_execd_entry_ur,
                        "Do you wish to keep this port name for the dqs_execd service (yes/no) ?",
                         "NO",
                         "The port name must be unique among the names in /etc/services\n",
			 "See System Management in the DQS 3.2 Installation \n and Maintenance Manual" },

                        {t_intercell_service,
			"Enter port name for the intercell service",
                         "dqs32_dqs_intercell",                          
                         "This name will be entered in the conf_file and /etc/services\n",
                          "See System Management in the DQS 3.2 Installation \n  and Maintenance Manual" },
                          
                        {t_keep_intercell_entry,
			"Do you wish to keep this port name for the intercell service (yes/no) ?",
                         "NO",
                         "The port name must be unique among the names in /etc/services\n",
                          "See System Management in the DQS 3.2 Installation \n  and Maintenance Manual" },

			{t_intercell_service_ur,
                        "Enter port name for the intercell service",
                         "dqs32_dqs_intercell_ur",
                         "This name will be entered in the conf_file and /etc/services\n",
			 "See System Management in the DQS 3.2 Installation \n  and Maintenance Manual" },

                        {t_keep_intercell_entry_ur,
                        "Do you wish to keep this port name for the intercell service (yes/no) ?",
                         "NO",
                         "The port name must be unique among the names in /etc/services\n",
			 "See System Management in the DQS 3.2 Installation \n  and Maintenance Manual" },

                        { t_mailer,
			"What is the name of your mailer program ?",
                          "/bin/mail",
                          "DQS uses the system mailer to send notification to the users\n  and the administrator\n",
                          "See System Management in the DQS 3.2 Installation \n  and Maintenance Manual"},

                        {t_mail_has_subj_line,
			"\nDoes your mailer have a -s subject_line option ? (yes/no)",
                         "YES",
                         "DQS can add a brief informational header to any mail \n  if the system supports a subject line",
                         ""},

                        {t_administrator,
			"Enter the login name of the administrator",
                         "",
                         "DQS will notify the administrator of operational problems\n",
                         "See DQS Operation in the DQS 3.2 installation and Maintenance Manual"},

                        {t_default_manager,
			"Enter the login name of the default manager",
                         "root",
                         "Initially all queues are assigned the default manager,\n  until one is explicitly added later\n",
                         "See DQS Operation in the DQS 3.2 installation and Maintenance Manual"},

                        {t_administrator2,
			"Enter the login name of the user-mode alternative administrator",
                         "",
                         "When not running with RESERVED PORTS, you must be in user mode.\n A secondary administrator is required.\n",
                         "See DQS Operation in the DQS 3.2 installation and Maintenance Manual"},

                        { t_logmail,
			"Should DQS log all DQS generated mail ? (yes/no)",
                         "NO",
                         "",
                         ""},

                        { t_default_rerun,
			"Should jobs be rerun by default? (yes/no) ",
                         "NO",
                         "Automatic rerunning of jobs is not enabled in DQS 3.2",
                         ""},

                        { t_default_account,
			"Enter a default account name ",
                         "GENERAL",
                         "Accounting information is recorded for all jobs.\n  An arbitrary ascii string may be used as an account name.\n",
                         "See DQS Operation in the DQS 3.2 installation and Maintenance Manual"},

                         { t_default_sort_seq_no,
			"Sort queues by Sequence Number ? (Yes/no)",
                          "NO",
                          "Queues are selected for job assignment by the inverse values\n  of their load averages or by a queueu sequence number\n.",
                         "See DQS Operation in the DQS 3.2 installation and Maintenance Manual"},

                         { t_sync_io,
			"Should DQS synchronize all stdout/stderr/stin I/O ? (yes/no)",
                          "NO",
                          "DQS can flush all i/o buffers it controls \n to maintin a semblance of synchronization with some impact on performance\n",
                          "I/O synchronization is not enabled in DQS 3.2" },

                         {t_user_access,
                          "What is the user access level: [ACCESS_FREE | ACCESS_OPEN | ACCESS_RESTRICTED ]?",
                         "ACCESS_FREE",
                         "User Access level is not enabled in DQS 3.2",
                         ""},

                         { t_logfacility,
			"What is the log facility: [LOG_VIA_SYSLOG | LOG_VIA_FILE | LOG_VIA_COMBO]",
                         "LOG_VIA_COMBO",
                         "DQS can replicate log entries in its own system log \nand a separately named file.\n",
                         "See DQS Operation in the DQS 3.2 installation and Maintenance Manual"},

                         {t_loglevel,
			"What is the log level: [ LOG_EXTDEBUG |  LOG_DEBUG |\n        LOG_INFO |  LOG_NOTICE  | LOG_WARN  | LOG_ERR | LOG_CRIT]",
                          "LOG_INFO",
                          "DQS selectively logs information based on a level \n fron lowest level (LOG_EXTDEBUG) to highest",
                         "See DQS Operation in the DQS 3.2 installation and Maintenance Manual"},                         
                          
                         { t_min_uid,
			"Enter the minimum user id (minuid) which can be used \n to execute DQS utilities",
                         "10",
                         "Users whose uid's are less than this value \n will not be permitted to use DQS facilities.\n",
                         "See DQS Operation in the DQS 3.2 installation and Maintenance Manual"},

                         {t_min_gid, 
			"Enter the minimum group id (mingid) which can be used\n  to execute DQS utilities",
                         "10",
                         "Users whose gid is less than this value \n will not be permitted to use DQS facilities.\n",
                         "See DQS Operation in the DQS 3.2 installation and Maintenance Manual"},

                         { t_load_log_time,
			"Enter the number of seconds interval between load average logging attempts",
                          "30",
                          "Each dqs_execd will send a summary of its load average for each interval.\n",
                         "See DQS Operation in the DQS 3.2 installation and Maintenance Manual"},

                         { t_max_unheard,
			"Enter number of seconds required for dqs_execd reporting to the qmaster",
                          "90",
                          "If the qmaster has not heard in this time \n  it will mark a queue status as UNDEFINED.\n",
                         "See DQS Operation in the DQS 3.2 installation and Maintenance Manual"},

                         {t_schedule_time,
			"Enter number of seconds between job scheduling passes by the qmaster",
                         "60",
                         "The qmaster will examone the job queue each time a job is submitted\n   or terminates or at least this interval\n",
                         "See DQS Operation in the DQS 3.2 installation and Maintenance Manual"},

                         {t_stat_log_time,
			"Enter the number of seconds between statistics logging",
                         "600",
                         "The qmaster logs selected system statistics each enterval of this time\n",
                         "See DQS Operation in the DQS 3.2 installation and Maintenance Manual"},

                         { t_maxujobs,
			"Enter the maximum number of jobs a single user is permitted\n     to have in all the queues at one time",
                          "10",
                          "DQS limits user jobs system-wide and on a queue by queue basis.\n  This is the system_wide limit.\n",
                         "See DQS Operation in the DQS 3.2 installation and Maintenance Manual"},

                         { t_output_handling,
			"Enter output file handling method\n [COPY_OUTPUT_FILES || LINK_OUTPUT_FILES || LEAVE_OUTPUT_FILES]",
                         "LEAVE_OUTPUT_FILES",
                         "DQS can copy the output files at a prescribed interval, \nor it can create links to those files, or leave them in place\n",
                         "See DQS Operation in the DQS 3.2 installation and Maintenance Manual"},

                         {t_addon_script,
			"enter addon_script pathname or NONE",
                         "NONE",
                         "DQS can execute a system script at the conclusion of job execution.\n",
                         "See DQS Operation in the DQS 3.2 installation and Maintenance Manual"},

                         {t_addon_info,
			"Enter addon_info file pathname",
                         "NONE",
                         "Execution of an addon script can generate information which\n should not be placed in the user's file space\n",
                         "See DQS Operation in the DQS 3.2 installation and Maintenance Manual"},

                         {t_copy_file_delay,
			"Enter number of seconds between output file copy operations(if enabled)",
                         "300",
                         "If output file handling specifies COPY_OUTPUT_FILES,\n the copy operations will occur at this interval\n",
                         "See DQS Operation in the DQS 3.2 installation and Maintenance Manual"},

                         {t_link_file_path,
			"Enter the path name to the directory into which \n the output files will be linked",
                         "",
                         "If the output file handling method is LINK_OUTPUT_FILES, this path will be the basis of the file linking.\n",
                         "See DQS Operation in the DQS 3.2 installation and Maintenance Manual"},

                         { t_slave_loop_time,
			"Enter slave loop time in millisconds",
                          "200",
                          "Each job is accompanied by a DQS process-shepherd. \n This is the interval for the shepherd to check on the job.\n",
                          "See DQS Operation in the DQS 3.2 installation and Maintenance Manual"},

                         { t_pvm_root,
			"Enter the PVM_ROOT path if PVM will be used.",
                          "",
                          "DQS supports the PVM parallel/cluster system. \n To perform daemon startup and cleanup the PVM_ROOT must be known.\n",
                          "See DQS Operation in the DQS 3.2 installation and Maintenance Manual"},
                         	
                        { t_alarms,
			"Enter the number of millesconds for the ALARMS system constant.",
                        "3",
                        "ALARMS controls the interruption of load average transmissions\n  to the qmaster.\n",
                        "See DQS Operation in the DQS 3.2 installation and Maintenance Manual"},
                         
                        { t_alarmm,
			"Enter the number of millesconds for the ALARMM system constant.",
                        "3",
                        "ALARMM controls the interruption of all message transmissions \n in the system.\n",
                        "See DQS Operation in the DQS 3.2 installation and Maintenance Manual"},   
                         
                        { t_alarml,
			"Enter the number of millesconds for the ALARML system constant.",
                        "3",
                        "ALARMm controls the interruption of intertask communications.\n",
                        "See DQS Operation in the DQS 3.2 installation and Maintenance Manual"},

                        { t_bin_dir,
			"Enter the path for the directory where the DQS binaries will be installed.",
                         "DQS/bin",
                         "The dqs_execd and all utilities (qsub, qmod,...)\n      must be accessible by all hosts.\n",
                        "See DQS Operation in the DQS 3.2 installation and Maintenance Manual\n"},

                        {t_conf_dir,
			"Enter the path where the conf_file and resolve_file will be stored",
                         "DQS/conf",
                         "Each host must access the conf_file and resolve_file\n    or an exact copy or each.\n",
                        "See DQS Operation in the DQS 3.2 installation and Maintenance Manual"},

                        {t_qmaster_spool_dir,
			"Enter the pathname for the qmaster_spool directory",
                        "DQS/conf",
                        "The qmaster spool directory needs only to be accessed by the qmaster.\n",
                        "See DQS Operation in the DQS 3.2 installation and Maintenance Manual"},

                        { t_dqs_execd_spool_dir,
			"Enter the pathname for the dqs_execd_spool directory",
                         "DQS/conf",
                         "If possible the dqs_execd_spool directory should be accessible\n  by qmaster as well as all dqs_execds\n",
                        "See DQS Operation in the DQS 3.2 installation and Maintenance Manual"},

                        {t_doc_dir,
			"Enter the pathname for the directory to contain DQS 3.2 documentation.",
                         "DQS/DOC",
                         "The DQS 3.2 documents will be copied to this directory\n",
                        "See DQS Operation in the DQS 3.2 installation and Maintenance Manual"},

                        {t_lib_dir,
                         "Enter the pathname for the directory to contain DQS 3.2 libraries.",
                         "DQS/lib",
                         "Any pvm, mpi or P4 libraries should be copied to this directory.\n",
                        "See DQS Operation in the DQS 3.2 installation and Maintenance Manual"},

                        {t_man1_dir,
			"Enter the pathname to the system man1 pages.",
                        "DQS/man/man1",
                        "",
                        ""},

                        {t_man3_dir,
			"Enter the pathname to the system man3 pages.",
                        "DQS/man/man3",
                        "",
                        ""},

                        { t_dqs_root,
			"Enter the User ID (uid) for the DQS 3.2 binaries.",
                        "0",
                        "",
                        ""},

                        { t_dqs_sysgrp,
			"Enter the group ID (gid) for the DQS 3.2 binaries.",
                         "0",
                         "",
                         ""},

                        { t_root,
			"Enter the User ID (uid) for the manuals and documentation.",
                         "0",
                         "",
                         ""},

                        {t_sysgrp,
			"Enter the Group ID (gid) for the manuals and documentation.",
                         "0",
                         "",
                         ""},

                        { t_simple_install,  
			"  Do you wish to use the Simple Installation Process? (Yes/No)",
                         "YES",
                         "",
                         ""},

                         { t_default_install,
			" Is This satisfactory ? (Yes/No) ",
                          "YES",
                          "",
                          ""},

                        { t_user_cwd,
                        "",
                        "",
                        "",
                        ""},

                        { t_list_end,
                        "XXXXXXXX",
                        "XXXXXXXX",
                        "XXXXXXXX",
                        "XXXXXXXX" }

};

/******************************************************
 *                          MAIN
 *******************************************************/
main(argc,argv)
int argc;
char ** argv;
{
     char *str;
     int i;
     struct stat sbuf;
     char *config_script_file;
     
     DEBUG_TRACEID         =0;
     qmaster_service_num   =0;
     dqs_execd_service_num =0;
     intercell_service_num =0;
     num_in_exec_matrix    =0;
     has_manager2          =0;
     has_automount         =0;
     already_has_port_nums =0;
     SIMPLE_INSTALL		   =0;
     I_AM_ROOT			   =0;
     
     if (getenv("DEBUG"))
     DEBUG_ON=1;
     else
     DEBUG_ON=0;

     /* in case of SIMPLE_INSTALL we will place directories relative to */
     /* the cwd if we are not doing the build as root                   */
     /* otherwise we will place the directories according to the prototye */
     
     if(getuid()<10) I_AM_ROOT=1;

      	MALLOC_STR(user_cwd);
     	getcwd(user_cwd,MAXSTR);
        MALLOC_STR(base_user_cwd);
        strcpy(base_user_cwd, user_cwd);
     
     sigemptyset(&sigint_vec.sa_mask);
     sigint_vec.sa_handler = interrupt_so_punt;
     if( sigaction(SIGINT,&sigint_vec, & sigint_ovec)== -1 ) err_crit("Can't set sigmask");
     
     if  (argc==2)
     if (!strcmp(argv[1],"-u")) undo_config();
     
     build_makefile_proto();
     
     if (argc ==3)
     if (!strcmp(argv[1],"-f")){
	  stat_move_files();
	  MALLOC_STR(config_script_file);
	  strcpy(config_script_file,argv[2]);
	  PUT_NULL(config_script_file);
	  DPRINTF(("config file to be read == :%s:\n",config_script_file));
	  
	  if(stat(config_script_file,&sbuf)==-1) err_crit("can't open script file\n");
	  read_all_config(config_script_file);
	  DTRACE;
	  dump_dqs_config(); /* writes out dqs.h*/
	  DTRACE;
	  write_make();  /* writes make file*/
	  DPRINTF(("about to configure conf_file....\n\n"));
	  configure_conf_file();
	  get_resolve_file();
	  /* copy_res_conf_files();        just added exper tpg */
	  printf("DQS header files reconfiguration complete.\n");
	  printf("type \"make\" to remake DQS with new parameters\n"); 
	  exit(0);
     }
     
     
     
     stat_move_files();
     give_intro();
     get_make();
     
     get_dqs_config();
     get_resolve_file();
     find_good_ports();
     configure_conf_file();
     write_make();
     dump_dqs_config();
     write_all_config();
     add_services();
     /*copy_res_conf_files(); tpg */
     exit_config();
     
}

/***********************************************
 *        COPY_RES_CONF_FILES
 *************************************************/
void  copy_res_conf_files()
/* copies resolve_file and conf_file to DQS/SRC*/
{
     char buf[MAXLEN];
     FILE * fd,*outfd;
     
     /* 1st copy resolve_file*/
     
     if( (fd = fopen(resolve_file,"r"))==NULL){
	  printf("Can't copy resolve file \n");
	  return;
     }
     
     if( (outfd = fopen("../SRC/resolve_file","w"))==NULL){
          printf("Can't copy resolve file \n");
          return;
     }
     
     bzero(buf,MAXLEN);
     while(fgets(buf,MAXLEN,fd)){
	  fprintf(outfd,"%s",buf);
	  bzero(buf,MAXLEN);
     }
     
     fclose(fd);
     fclose(outfd);
     
     /* Now take care of conf_file */
     if( (fd = fopen(conf_file,"r"))==NULL){
	  printf("Can't copy conf file \n");
	  return;
     }
     
     if( (outfd = fopen("../SRC/conf_file","w"))==NULL){
          printf("Can't copy conf file \n");
          return;
     }
     
     bzero(buf,MAXLEN);
     while(fgets(buf,MAXLEN,fd)){
	  fprintf(outfd,"%s",buf);
	  bzero(buf,MAXLEN);
     }
     
     bzero(buf,MAXLEN);
     
     fclose(fd);
     fclose(outfd);
     
     
}

/***********************************************
 *      COPY_KEY_FILE
 *************************************************/
/* Copies the key_file from DQS/SRC/key_file */

void copy_key_file()

{
     FILE * fd,*infd;
     char buf[MAXLEN];
     
     
     if ( (fd = fopen(key_file,"w"))==NULL){
	  err_cont("Can't open key file for writing\n");
	  return;
     }
     
     if ( (infd = fopen("../SRC/key_file","r"))==NULL){
	  err_cont("Can't open key file for reading\n");
	  return;
     }
     while(fgets(buf,MAXLEN,infd)){
	  
	  fprintf(fd,"%s",buf);
	  jbzero(buf,MAXLEN);
     }
     
     chmod(key_file,0600);
     return;
     
}

/***********************************************
 *          INTERRUPT_SO_PUNT
 *************************************************/
/* Someone has ctrl-C'd during the session so 
   we need to move things back to their origional
   state and exit                              */
void interrupt_so_punt()
{
     
     printf("\n\n\n It has come to our attention that you have\n");
     printf(" hit CTRL-C...We are now moving things back to \n");
     printf(" Their origional state.......\n\n\n");
     
     undo_config();
     
     
     
}
/************************************************
 *             MAKE_DIR
 *************************************************/

/* makes directory 1 level at a time, like mkdir -p*/

int make_dir(path,perm)
char *  path;
int perm;
{
     char *tmp;
     char *place;
     char *targ;
     struct stat sbuf;
     int i;
     
     
     MALLOC_STR(tmp);
     for(i=0;i<MAXSTR;i++)
     tmp[i]='\0';
     
     tmp[0]=path[0];
     for(i=1;i<strlen(path);i++){
	  if(path[i] == '/'){
	       tmp[i] = '\0';
	       DPRINTF(("tmp_path ==:%s:\n",tmp));  
	       if(do_make_dir(tmp,perm)==-1) return(-1);
	  }
	  tmp[i] = path[i];
     }
     PUT_NULL(tmp);
     DPRINTF(("finally trying :%s:\n",tmp));
     if(do_make_dir(tmp,perm)==-1) return(-1);
     
     free(tmp);
     return(1);
}
/************************************************
 *                     DO_MAKE_DIR
 *************************************************/
/* stats path and trys to make directory, returns
   -1 on failure 1 on success                  */
int do_make_dir(path,perm)
char *  path;
int perm;
{
     struct stat sbuf;
     
     DPRINTF(("DO_MAKE_DIR....:%s:\n",path));
     
     if(stat(path,&sbuf)==-1) {
	  DPRINTF(("directory :%s: doesn't exist, trying to make\n",path));
	  if(mkdir(path,perm)==-1) {
	       DPRINTF(("Can't make  :%s: \n",path));
	       err_cont("Can't make path\n");
	       return(-1);
	  }
	  else  
	  DPRINTF(("success making :%s:\n",path));
     }
     else
     DPRINTF(("directory already exists returning\n"));
     
     return(1);
     
}
/************************************************
 *                  EXIT_CONFIG
 *************************************************/
void exit_config()
{
     
     printf("\n\n\n\n############################################################\n");
     printf("Before you can run DQS, Changes must be made to  \n");
     printf("/etc/services on all machines that will run dqs: (the port numbers\n");
     printf(" MUST BE THE SAME IN /etc/services on all machines !!!)\n\n");  
     printf("A script has been provided for this purpose. \n");
     printf("It is called ~DQS/CONFIG/addservice.sh.  This should be run as\n");
     printf(" root on all machines that will use DQS.  If you  do not wish to \n");
     printf("run this program please edit /etc/services by hand\n");
     printf("   See 'Installation' in DQS 3.2 Installation and Maintenance Manual\n");     
     printf("keeping the port numbers consistent across all architectures\n\n");
     
     printf("Your entries in /etc/services should look like the following\n");
     printf("%s  %d/tcp\n",qmaster_service, qmaster_service_num);
     printf("%s  %d/tcp\n",dqs_execd_service, dqs_execd_service_num);
     printf("%s  %d/tcp\n",intercell_service, intercell_service_num);     
     exit(0);
     
     
}
/************************************************
 *                   UNDO_CONFIG
 *************************************************/
/* moves Makefile.orig back  and ../SRC/dqs.h.orig back to ../SRC/dqs.h */

void undo_config()
{
     char *tmpmake;
     struct stat sbuf;
     
     MALLOC_STR(tmpmake);
     strcpy(tmpmake,MAKEFILE);
     strcat(tmpmake,".orig");
     if(stat(tmpmake,&sbuf) == -1) err_crit("No makefile.orig to move back\n");
     if(rename(tmpmake,MAKEFILE) ==1) err_crit("Can't move Makefile.orig back to Makefile");
     
     if(stat("../SRC/dqs.h.orig",&sbuf) ==-1) err_crit("No ../SRC/dqs.h.orig to move back\n");
     if(rename("../SRC/dqs.h.orig","../SRC/dqs.h") ==-1) err_crit("Can't move ../SRC/dqs.h.orig back to ../SRC/dqs.h");
     printf("Move completed please edit files Makefile and ../SRC/dqs.h by hand \n");
     printf("   See 'Installation' in DQS 3.2 Installation and Maintenance Manual\n");
     
     
     if(stat("../SRC/conf_file.orig",&sbuf) ==-1) err_crit("No ../SRC/conf_file.orig to move back\n");
     if(rename("../SRC/conf_file.orig","../SRC/conf_file") ==-1) err_crit("Can't move ../SRC/conf_file.orig back to ../SRC/conf_file");
     printf("Move completed please edit files Makefile and ../SRC/conf_file by hand \n");
     printf("   See 'Installation' in DQS 3.2 Installation and Maintenance Manual\n");
     
     if(stat("../SRC/resolve_file.orig",&sbuf) ==-1) printf("No ../SRC/resolve_file.orig to move back....continuing\n");
     if(rename("../SRC/resolve_file.orig","../SRC/resolve_file") ==-1) printf("Can't move ../SRC/resolve_file.orig back to ../SRC/resolve_file\n");
     
     
     printf("Move completed please edit files Makefile and ../SRC/resolve_file by hand  \n");
     printf("   See 'Installation' in DQS 3.2 Installation and Maintenance Manual\n");     
     
     if(stat("/etc/services.orig.dqs",&sbuf) ==-1) printf("No /etc/services.orig.dqs to move back\n");
     if(rename("/etc/services.orig.dqs","/etc/services") ==-1) printf("Can't move /etc/services.orig.dqs back to /etc/services\n");
     else                                                      printf("\n\nMoves /etc/services completed. \n");
     
     printf("\nAll files restored to origional pre-config form please edit and remake DQS \n");
     printf("   See 'Installation' in DQS 3.2 Installation and Maintenance Manual\n");     
     
     exit(1);
}
/************************************************
 *            STAT_MOVE_FILES
 *************************************************/
void stat_move_files()
/* checks to see if there is ../SRC/dqs.h.orig and
   if not, moves ../SRC/dqs.h ../SRC/dqs.h.orig. Also
   moves ~DQS/Makefile to ~DQS/Makefile.orig       */
{
     struct stat sbuf;
     char *tmpmake;
     
     MALLOC_STR(tmpmake);
     strcpy(tmpmake,MAKEFILE);
     strcat(tmpmake,".orig");    
     
     DPRINTF(("Stat'ing file %s\n",tmpmake));
     
     if(stat(tmpmake,&sbuf) == -1){
	  /* need to move files to wonk.orig*/
	  DPRINTF(("%s doesn't exist...moving\n",tmpmake));
	  DPRINTF(("moving %s to %s\n",MAKEFILE,tmpmake));
	  if (rename(MAKEFILE,tmpmake)==-1) err_crit("Can't move Makefiles\n");
	  
     }
     else{
	  DPRINTF(("Makefile.orig does exist\n"));
     }  
     
     /* now move ../SRC/dqs.h to ../SRC/dqs.h.orig*/
     
     if (stat("../SRC/dqs.h.orig",&sbuf)==-1){
	  DPRINTF(("../SRC/dqs.h.orig doesn't exist...moving\n"));
	  if (rename("../SRC/dqs.h","../SRC/dqs.h.orig")==-1) err_crit("Can't move ../SRC/dqs.h\n");
     }
     
     if (stat("../SRC/conf_file.orig",&sbuf)==-1){
	  DPRINTF(("../SRC/conf_file.orig doesn't exist...moving\n"));
	  if (rename("../SRC/conf_file","../SRC/conf_file.orig")==-1) err_cont("Can't move ../SRC/conf_file\n");
     }
     
     if (stat("../SRC/resolve_file.orig",&sbuf)==-1){
	  DPRINTF(("../SRC/resolve_file.orig doesn't exist...moving\n"));
	  if (rename("../SRC/resolve_file","../SRC/resolve_file.orig")==-1) err_cont("Can't move resolve_file\n");
     }
     
     
     free(tmpmake);
}

/************************************************
 *                    SET_VAR
 *************************************************/
/* takes in default and given values from str1 and 
   str2.  If str1 is empty assign str2 to str1 and 
   return
   */
void set_var(str1,defaultstr)
char * str1,*defaultstr;
{
     DPRINTF(("in set_var, defaultstr == :%s:\n",defaultstr));
     if(is_empty(str1)){
	  DPRINTF(("target is empty...using defaultstr\n"));
	  strcpy(str1,defaultstr);
	  PUT_NULL(str1);
     }     
     /* check default for TRUE or FALSE and give some resiliancy on user input*/
     if ( (!strcmp(defaultstr,"TRUE")) || (!strcmp(defaultstr,"FALSE")) || (!strcmp(defaultstr,"YES")) || (!strcmp(defaultstr,"NO"))  ){
	  DPRINTF(("is true/false str[0] ==:%c:\n\n",str1[0]));
	  if( (str1[0]=='t') || (str1[0]=='T') )
	  strcpy(str1,"TRUE");
	  if( (str1[0]=='y') || (str1[0]=='Y') )
	  strcpy(str1,"TRUE");
	  
	  if( (str1[0] == 'f') || (str1[0]=='F') )
	  strcpy(str1,"FALSE");
	  if( (str1[0] == 'n') || (str1[0]=='N') )
	  strcpy(str1,"FALSE");
	  
	  PUT_NULL(str1);
     }


     DPRINTF(("Leaving set_var target == :%s:\n",str1));
     
}

/************************************************
 *                    SET_DEF
 *************************************************/
/*  Sets the default value of an input string for a given type description
   */
void set_def(str, type)
char ** str;
int type;
{
	int i;
	char *tmpc;
     DPRINTF(("in set_def, type= %d:\n",type));


     if(!*str) tmpc=  (char *)malloc(MAXLEN);
     *str= tmpc;
     strcpy(*str, getl[type].tdefault);

    /* check default for TRUE or FALSE and give some resiliancy on user input*/
     if  (!strcmp(*str,"YES")) strcpy(*str,"TRUE");
     if  (!strcmp(*str,"NO"))  strcpy(*str,"FALSE");
	  
     DPRINTF(("Leaving set_def target == :%s:\n",*str));
     
}



/************************************************
 *                       GIVE_INTRO
 *************************************************/
/* set's up general information */
void give_intro(){

     char  *ans, *resp, *tmpstr;
     int   nmln;
     struct passwd *pw;

      tmpstr = get_administrator();
       strcpy(getl[t_administrator].tdefault, tmpstr);
       free(tmpstr);

      if (   (pw = getpwuid(getuid()))  ==  NULL){
	      }
      else{
	     strcpy(getl[t_administrator2].tdefault,pw->pw_name);
      }
	      
      if (getuid()) { /* t_dqs_root,t_dqs_sysgrp,t_root,t_sysgrp */
	sprintf(getl[t_dqs_root].tdefault,"%d",getuid());
        sprintf(getl[t_dqs_sysgrp].tdefault,"%d",getgid());
        sprintf(getl[t_root].tdefault,"%d",getuid());
        sprintf(getl[t_sysgrp].tdefault,"%d",getgid());
      }
	
     printf("\n\n\n########################################################\n");
     printf("  Welcome to the DQS-3.2  configuration program\n\n");

     
     if(get_line(&ans,t_simple_install) )SIMPLE_INSTALL=1;

     if(SIMPLE_INSTALL){
     	if(I_AM_ROOT){
     		printf(" You have chosen the simple installation option as a root user.\n");
     		printf(" The default installation will use /usr/local/DQS as base directory\n");
     		
     		if(get_line(&ans, t_default_install) ){
                  strcpy(user_cwd,"/usr/local/DQS");
     		}
     		else{
     		   strcpy(getl[t_user_cwd].tdefault,"/usr/local/DQS");
     		   printf(" enter an alternative to /usr/local/DQS as a starting path or\n");
 		   get_line(&user_cwd, t_user_cwd);   /* use current working directory as default */

                }
     		
     		printf(" The default installation will create or use following directories:\n");
     		printf("    qmaster & dqs_execd spool directories;%s/%s\n",user_cwd,CONF_DIR );
     		printf("    dqs executables: %s/%s\n", user_cwd,BIN_DIR);
     		printf("    dqs documentation: %s/%s\n",user_cwd,DOC_DIR);
     		printf("    dqs libraries: %s/%s\n", user_cwd, LIB_DIR);
     		printf("    dqs manual pages: %s/%s  %s/%s\n",user_cwd,MAN1_DIR, user_cwd,MAN3_DIR);

     		
     		if(get_line(&ans, t_default_install) ){

     		}
     		else{
     		   printf(" enter an alternative to %s as a starting path or\n",user_cwd);
     	  	   printf(" the word CUSTOM, to go to the custom installation: ");

 		   get_line(&user_cwd, t_user_cwd);   /* use current working directory as default */
                   resp= strstr(user_cwd,"CUSTOM");
                   if(resp)  SIMPLE_INSTALL=0;

                } /* happy with defaults  */
        }  /* I am root  */    
        else{
     		printf(" You have chosen the simple installation option as a non-root user.\n");
     		printf(" The default installation will use %s/usr/local/DQS as base directory\n",base_user_cwd);
     		
     		if(get_line(&ans, t_default_install)){
     		  strcpy(user_cwd, base_user_cwd);
                  strcat(user_cwd,"/usr/local/DQS");
     		}
     		else{
     		   strcpy(getl[t_user_cwd].tdefault,base_user_cwd);
     		   strcat(getl[t_user_cwd].tdefault,"/usr/local/DQS");
     		   printf(" enter an alternative to %s as a starting path or\n",getl[t_user_cwd].tdefault);
 		   get_line(&user_cwd, t_user_cwd);   /* use current working directory as default */

                }
     		printf(" The default installation will create or use following directories\n");
     		printf("    based on the current working directory: \n");
     		printf("    qmaster & dqs_execd spool directories; %s/%s\n",user_cwd,CONF_DIR );
     		printf("    dqs executables: %s/%s\n", user_cwd,BIN_DIR);
     		printf("    dqs documentation: %s/%s\n",user_cwd,DOC_DIR);
     		printf("    dqs libraries: %s/%s\n", user_cwd, LIB_DIR);
     		printf("    dqs manual pages: %s/%s  %s/%s\n",user_cwd,MAN1_DIR, user_cwd, MAN3_DIR);

     		
     		if(!get_line(&ans, t_default_install) ){
         		printf(" enter an alternative to %s as a starting path or\n",user_cwd);
        		printf(" the word CUSTOM, to go to the custom installation: ");
 		   get_line(&user_cwd, t_user_cwd);   /* use current working directory as default */
               resp= strstr(user_cwd,"CUSTOM");
               if(resp)  SIMPLE_INSTALL=0;

            }  /* happy with defaults  */
        }  /* I am not root  */    
	 }

        nmln= strlen(user_cwd);
        /* ensure that working directory ends with a '/'  */
        if(user_cwd[nmln-1]!='/'){
             user_cwd[nmln]='/';
             user_cwd[nmln+1]='\0';
		}
        strcpy(getl[t_bin_dir].tdefault,user_cwd);
        strcat(getl[t_bin_dir].tdefault,BIN_DIR);

        strcpy(getl[t_conf_dir].tdefault,user_cwd);
        strcat(getl[t_conf_dir].tdefault,CONF_DIR);

        strcpy(getl[t_qmaster_spool_dir].tdefault,user_cwd);
        strcat(getl[t_qmaster_spool_dir].tdefault,QMASTER_DIR);

        strcpy(getl[t_dqs_execd_spool_dir].tdefault,user_cwd);
        strcat(getl[t_dqs_execd_spool_dir].tdefault,DQS_EXECD_DIR);

        strcpy(getl[t_doc_dir].tdefault,user_cwd);
        strcat(getl[t_doc_dir].tdefault,DOC_DIR);

        strcpy(getl[t_lib_dir].tdefault,user_cwd);
        strcat(getl[t_lib_dir].tdefault,LIB_DIR);

        strcpy(getl[t_man1_dir].tdefault,user_cwd);
        strcat(getl[t_man1_dir].tdefault,MAN1_DIR);

        strcpy(getl[t_man3_dir].tdefault,user_cwd);
        strcat(getl[t_man3_dir].tdefault,MAN3_DIR);


     if(SIMPLE_INSTALL){
        
     	
     	printf(" The Simple Installation wil create the following files\n");
        printf("   with default values:\n");
        printf("                       resolve_file\n");
        printf("                       conf_file\n");
        printf("                       dqs.h\n");
        printf("                       def.h\n");
        printf("                       Makefile\n");
        printf("\n Before these files are copied  \n");
     	printf("   into the installtion directories the user will be asked\n");
     	printf("   to review their contents and approve the defaults \n");
     	return;
     }

     printf("  You have selected the Custom Installation option.\n");
     printf("  The following files will be setup interactively:\n");
     printf("                       resolve_file\n");
     printf("                       conf_file\n");
     printf("                       dqs.h\n");
     printf("                       def.h\n");
     printf("                       Makefile\n");
     printf("\n  As each file is setup you will be prompted with\n");
     printf("    questions requiring values to be entered or a response\n");
     printf("    such as yes or no or true or false. The first letters\n");
     printf("    y,Y,n,N,t,T,f,F may be used instead of the full words\n");
     printf(" \n Typing CTRL-C will terminate the configuration process\n");
     printf("     and restore files to their initial conditions\n");
     return;
}


/************************************************
 *                GET_LINE
 *************************************************/
/* prompts with str and reads a line in.  mallocs
   memory and returns a pointer to that memory  */

int  get_line(str, type)
char ** str;
int type;
{  
     
     char   buff[MAXSTR];
     int i,j, got_reply;
          
     MALLOC_STR(*str)

     got_reply= FALSE;

     do{
     for(i=0;i<MAXSTR-1;i++)  buff[i]='\0';
     for(i=0;i<MAXSTR-1;i++)  (*str)[i]='\0';
        printf("%s\n", getl[type].message);
     
        printf("default [%s]  ",getl[type].tdefault);
        if( fgets(*str,MAXSTR,stdin)==(char*)NULL) {
             strcpy(*str, getl[type].tdefault);
	}            

	i= strlen(*str);
	if(i>0) (*str)[i-1]= '\0';
     
        DPRINTF(("line read in in get-line ==:%s:\n",*str));
     /* now remove any leading-trailing blanks */
     
        j=0;
        for(i=0;i<strlen(*str);i++){
  	  if ( ( (*str)[i] != ' ') && ( (*str)[i] !='\t') ){
	       buff[j] = (*str)[i];
	       j++;
	  }
        }
     
        PUT_NULL(buff);
     
     
        strcpy(*str,buff);

        if( (*str)[0]=='?'){
     	   printf("%s",getl[type].description);
     	   fflush(stdout);
     	   printf("\n");
     	   fflush(stdout);
     	   printf("%s",getl[type].reference);
     	   fflush(stdout);
     	   printf("\n");
     	   fflush(stdout);
     	   continue;
        }
        else{
           if( (*str)[0]=='\0'){                  /* empty string */
             strcpy(*str, getl[type].tdefault);
	   }
           
           
	}
	got_reply=TRUE;
     }while (got_reply==FALSE);
     set_var(*str, getl[type].tdefault);
     DPRINTF(("Returning :%s:\n",*str));
     if( !strcmp(*str,"TRUE")) return TRUE;
     return(FALSE);
}
/************************************************
 *      SQUEEZE_SPACE      
 ************************************************/

/* compresses multiple spaces into one space,  good for formatting
   for consistent strtoks                                      */

void squeeze_space(buf)
char*buf;
{
     char tbuf[MAXLEN];
     int i,j,k;
     char ptr;
     int onesp=0;
     
     if(strlen(buf)==0){
	  DPRINTF(("NULL buff returning"));
	  return;
     }
     DPRINTF(("----->sqsp: buf ==:%s:\n",buf));
     bzero(tbuf,MAXLEN);
     j=0;
     for(i=0;i<=strlen(buf);i++){
	  tbuf[j] = buf[i];
	  if(isspace(buf[i])){
	       while(isspace(buf[i])){
		    i++;
	       }
	       i--;
	  }
	  j++;
     }
     
     if(isspace((tbuf[strlen(tbuf)-1]))) tbuf[(strlen(tbuf)-1)]='\0';
     
     PUT_NULL(tbuf);
     DPRINTF(("tbuf == :%s:\n",tbuf));
     bzero(buf,strlen(buf));
     strcpy(buf,tbuf);
     DPRINTF(("<-----sqsp:Fixed buf ==:%s:\n",buf));
     return;
     
}
/************************************************
 *      delete_ltr_spaces
 ************************************************/
/* deletes leading and trailing spaces from buf */

void delete_ltr_spaces(buf)
char * buf;
{
     
     char tbuf[MAXLEN];
     int i,j;
     int first,last;
     
     DPRINTF(("--> delete_ltr_spaces buf==:%s:\n",buf));
     
     if((last = strlen(buf))==0){
	  DPRINTF(("NULL buff returning"));
	  return;
     }
     
     
     for(i=0;(i<last) &&(isspace(buf[i]));i++)
     ;
     
     first=i;
     for(i=last;(i>=0) &&(isspace(buf[i]));i--)
     ;
     
     bzero(tbuf,MAXLEN);       
     
     last = i;
     j=0;
     for(i=first;i<last;i++){
	  tbuf[j]=buf[i];
	  j++;
     }
     bzero(buf,strlen(buf));
     strcpy(buf,tbuf);
     DPRINTF(("<----dltr:  Fixed buf ==:%s:\n",buf));
     
     return;
     
}




