/*
 *	Network Queueing System (NQS)
 *  This version of NQS is Copyright (C) 1992  John Roman
 *
 *  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 1, 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.
 */
/*
*  PROJECT:     Network Queueing System
*  AUTHOR:      John Roman
*
*  Modification history:
*
*       Version Who     When            Description
*       -------+-------+---------------+-------------------------
*       V01.10  JRR     15-Apr-1992     Initial version.
*	V01.2	JRR	26-May-1992	Fix declaration of get_snap_units.
*					Add header.
*	V01.3	JRR	02-Oct-1992	Fixed long line with wrap.
*					Added scheduler...
*	V01.4	JRR	26-Feb-1993	Put NQS version in header.
*	V01.5	JRR	11-Aug-1993	Check current working directory.
*	V01.6	JRR	21-Apr-1994	Ranking compute servers.
*/
/*++ mgr_snap.c - Network Queueing System
 *
 * $Source: /usr2/jrroma/nqs/nqs-3.36/src/RCS/mgr_snap.c,v $
 *
 * DESCRIPTION
 *
 * STANDARDS VIOLATIONS:
 *   None.
 *
 * REVISION HISTORY: ($Revision: 1.7 $ $Date: 1994/09/02 17:39:37 $ $State: Exp $)
 * $Log: mgr_snap.c,v $
 * Revision 1.7  1994/09/02  17:39:37  jrroma
 * Version 3.36
 *
 * Revision 1.6  1994/03/30  20:36:22  jrroma
 * Version 3.35.6
 *
 * Revision 1.5  93/09/10  13:56:57  jrroma
 * Version 3.35
 * 
 * Revision 1.4  93/07/13  21:33:42  jrroma
 * Version 3.34
 * 
 * Revision 1.3  92/12/22  15:39:41  jrroma
 * Version 3.30
 * 
 * Revision 1.2  92/06/18  17:30:46  jrroma
 * Added gnu header
 * 
 * Revision 1.1  92/05/06  10:37:23  jrroma
 * Initial revision
 * 
 *
 */

#include "nqs.h"			/* NQS types and definitions */
#include <unistd.h>
#include <errno.h>
#include "nqsxvars.h"			/* NQS external vars */
#include "transactcc.h"                 /* For TCML_COMPLETE */
					/* from a database file */
#ifndef __CEXTRACT__
#if __STDC__

static char *get_snap_units ( short units );
static void snap_batch ( struct gendescr *descr );
static void snap_complex ( struct gendescr *descr );
static void snap_dest ( struct gendescr *que_descr );
static void snap_global ( void );
static void snap_managers ( void );
static void snap_param ( void );
static void snap_pipe ( struct gendescr *descr );
static void snap_queacc ( struct gendescr *descr );
static void snap_servers ( void );

#else /* __STDC__ */

static char *get_snap_units (/* short units */);
static void snap_batch (/* struct gendescr *descr */);
static void snap_complex (/* struct gendescr *descr */);
static void snap_dest (/* struct gendescr *que_descr */);
static void snap_global (/* void */);
static void snap_managers (/* void */);
static void snap_param (/* void */);
static void snap_pipe (/* struct gendescr *descr */);
static void snap_queacc (/* struct gendescr *descr */);
static void snap_servers (/* void */);

#endif /* __STDC__ */
#endif /* __CEXTRACT__ */

extern gid_t cgid;			/* Caller's gid */
extern Mid_t Local_mid;
extern int Init_mgr;
extern char *our_cwd;

FILE *genfile;				/* Qmgr command generation file */

int snap (filename)
char *filename;
{

	struct gendescr *descr;
	int newfd;		/* File descriptor of commands file */
	char machines_path [MAX_PATHNAME+1];
	long nownow;
	uid_t ouruid;
	char filename_path [MAX_PATHNAME+1];
	
	seekdb (Paramfile, 0L);
	ldparam ();

	ouruid = getuid();
	if ( setuid(ouruid) != 0) {
	    show_failed_prefix();
	    fprintf(stderr, "Unable to setuid to %d, errno = %d\n",
			ouruid, errno);
	    fflush(stderr);
	    return(TCML_EPERM);
	}
	/*
	 * If an absolute pathname,  use as is.  Otherwise, prepend with the
	 * current working directory.
	 */
	if (*filename == '/') {
	    strcpy (filename_path, filename);
	} else {
	    strcpy (filename_path, our_cwd);
	    strcat (filename_path, "/");
	    strcat (filename_path, filename);
	}
	if ((newfd = open (filename_path, O_CREAT | O_WRONLY | O_TRUNC, 0644)) == -1) {
	    show_failed_prefix();
	    fprintf (stderr, "Unable to open %s for writing qmgr", filename);
	    fprintf (stderr, " configuration commands.\n");
	    fflush (stderr);
	    return( errnototcm() );
	}

	genfile = fdopen (newfd, "w");

	if (telldb (Queuefile) != -1) {
	    /*
	     * We are not necessarily at the start of the database file
	     */
	    seekdb (Queuefile, 0L);		/* Seek to the beginning */
	}
	time (&nownow);
	fprintf (genfile, "#\n");
	fprintf (genfile, "#    Snap file created for %s by %s on %s", 
		 getmacnam (Local_mid), cuserid (NULL), ctime( &nownow) );
	fprintf (genfile, "#\n");
	fprintf (genfile, "#    NQS Version %s\n",  NQS_VERSION);
	fprintf (genfile, "#\n");
	fprintf (genfile, "#    Create the batch queues and set the defined");
	fprintf (genfile, " attributes\n");
	fprintf (genfile, "#\n");

	while ((descr = nextdb (Queuefile)) != (struct gendescr *) 0)  {
	    if (descr->v.que.type == QUE_BATCH) snap_batch (descr);
	}
	if (telldb (Queuefile) != -1) {
	    /*
	     * We are not necessarily at the start of the database file
	     */
	    seekdb (Queuefile, 0L);		/* Seek to the beginning */
	}
	fprintf (genfile, "#\n");
	fprintf (genfile, "#    Create the pipe queues and set the defined");
	fprintf (genfile, " attributes\n");
	fprintf (genfile, "#\n");

	while ((descr = nextdb (Queuefile)) != (struct gendescr *) 0)  {
	    if (descr->v.que.type == QUE_PIPE) snap_pipe (descr);
	}
	fflush (genfile);
	if (telldb (Queuefile) != -1) {
	    /*
	     * We are not necessarily at the start of the database file
	     */
	    seekdb (Queuefile, 0L);		/* Seek to the beginning */
	}
	fprintf (genfile, "#\n");
	fprintf (genfile, "#    Add the destinations to the pipe queues.\n");
	fprintf (genfile, "#\n");

	while ((descr = nextdb (Queuefile)) != (struct gendescr *) 0)
	    if (descr->v.que.type == QUE_PIPE) snap_dest (descr);

	if (telldb (Qcomplexfile) != -1) {
	    /*
	     * We are not necessarily at the start of the database file
	     */
	    seekdb (Qcomplexfile, 0L);	/* Seek to the beginning */
	}
	fprintf (genfile, "#\n");
	fprintf (genfile, "#    Create and set up queue complexes.\n");
	fprintf (genfile, "#\n");

	while ((descr = nextdb (Qcomplexfile)) != (struct gendescr *) 0)  {
		snap_complex (descr);
	}
	fprintf (genfile, "#\n");
	fprintf (genfile, "#    Add all managers to the list.\n");
	fprintf (genfile, "#\n");
	snap_managers ();

	fprintf (genfile, "#\n");
	fprintf (genfile, "#    Set general parameters.\n");
	fprintf (genfile, "#\n");
	snap_param ();
 
	fprintf (genfile, "#\n");
	fprintf (genfile, "#    Set global parameters.\n");
	fprintf (genfile, "#\n");
	snap_global ();

	fprintf (genfile, "#\n");
	fprintf (genfile, "#    Set compute servers.\n");
	fprintf (genfile, "#\n");
	snap_servers ();

	fclose (genfile);
	return (TCML_COMPLETE);
}


static void snap_batch (descr)
register struct gendescr *descr;
{
	int i;
	char *qname;

	qname = descr->v.que.namev.name;
	fprintf (genfile, "#\n");
	fprintf (genfile, "#    Creating and defining batch queue %s\n", qname);
	fprintf (genfile, "#\n");
	fprintf (genfile, "create batch_queue %s priority=%d",  qname,
		descr->v.que.priority);
	if (descr->v.que.status & QUE_PIPEONLY) fprintf (genfile, " pipeonly");
	fprintf (genfile, "\n");
#if     SGI
	if (descr->v.que.ndp != 0) 
	    fprintf(genfile, "set ndp=%d %s\n", descr->v.que.ndp, qname);
#endif
	/*
	 *  Set the run limits.
	 */
	fprintf (genfile, "set run_limit=%d %s\n", 
		descr->v.que.v1.batch.runlimit, qname);
	fprintf (genfile, "set user_limit=");
	fprintf (genfile, "%d %s\n",  descr->v.que.v1.batch.userlimit, qname);
	/*
	 *  Set per_process and per_request limits.
	 */
#if	(VALID_LIMITS & LIM_PPCORE)
	fprintf (genfile, "set corefile_limit = (");
	if (descr->v.que.v1.batch.infinite & LIM_PPCORE)
	    fprintf (genfile, "unlimited) %s\n", qname);
	else
	    fprintf (genfile, "%lu %s) %s\n",
			 descr->v.que.v1.batch.ppcorecoeff, 
			 get_snap_units (descr->v.que.v1.batch.ppcoreunits),
			 qname);
#endif
#if	(VALID_LIMITS & LIM_PPDATA)
	fprintf (genfile, "set data_limit = (");
	if (descr->v.que.v1.batch.infinite & LIM_PPDATA)
	    fprintf (genfile, "unlimited) %s\n", qname);
	else
	    fprintf (genfile, "%lu %s) %s\n",
			 descr->v.que.v1.batch.ppdatacoeff, 
			 get_snap_units (descr->v.que.v1.batch.ppdataunits),
			 qname);
#endif
#if	(VALID_LIMITS & LIM_PPPFILE)
	fprintf (genfile, "set per_process permfile_limit = (");
	if (descr->v.que.v1.batch.infinite & LIM_PPPFILE)
	    fprintf (genfile, "unlimited) %s\n", qname);
	else
	    fprintf (genfile, "%lu %s) %s\n",
			 descr->v.que.v1.batch.pppfilecoeff, 
			 get_snap_units (descr->v.que.v1.batch.pppfileunits),
			 qname);
#endif
#if	(VALID_LIMITS & LIM_PRPFILE)
	fprintf (genfile, "set per_request permfile_limit = (");
	if (descr->v.que.v1.batch.infinite & LIM_PRPFILE)
	    fprintf (genfile, "unlimited) %s\n", qname);
	else
	    fprintf (genfile, "%lu %s) %s\n",
			 descr->v.que.v1.batch.prpfilecoeff, 
			 get_snap_units (descr->v.que.v1.batch.prpfileunits),
			 qname);
#endif
#if	(VALID_LIMITS & LIM_PPTFILE)
	fprintf (genfile, "set per_process tempfile_limit = (");
	if (descr->v.que.v1.batch.infinite & LIM_PPTFILE)
	    fprintf (genfile, "unlimited) %s\n", qname);
	else
	    fprintf (genfile, "%lu %s) %s\n",
			 descr->v.que.v1.batch.pptfilecoeff, 
			 get_snap_units (descr->v.que.v1.batch.pptfileunits),
			 qname);
#endif
#if	(VALID_LIMITS & LIM_PRTFILE)
	fprintf (genfile, "set per_request tempfile_limit = (");
	if (descr->v.que.v1.batch.infinite & LIM_PRTFILE)
	    fprintf (genfile, "unlimited) %s\n", qname);
	else
	    fprintf (genfile, "%lu %s) %s\n",
			 descr->v.que.v1.batch.prtfilecoeff, 
			 get_snap_units (descr->v.que.v1.batch.prtfileunits),
			 qname);
#endif
#if	(VALID_LIMITS & LIM_PPMEM)
	fprintf (genfile, "set per_process memory_limit = (");
	if (descr->v.que.v1.batch.infinite & LIM_PPMEM)
	    fprintf (genfile, "unlimited) %s\n", qname);
	else
	    fprintf (genfile, "%lu %s) %s\n",
			 descr->v.que.v1.batch.ppmemcoeff, 
			 get_snap_units (descr->v.que.v1.batch.ppmemunits),
			 qname);
#endif
#if     (VALID_LIMITS & LIM_PRMEM)
	fprintf (genfile, "set per_request memory_limit = (");
	if (descr->v.que.v1.batch.infinite & LIM_PRMEM)
	    fprintf (genfile, "unlimited) %s\n", qname);
	else
	    fprintf (genfile, "%lu %s) %s\n",
			 descr->v.que.v1.batch.prmemcoeff, 
			 get_snap_units (descr->v.que.v1.batch.prmemunits),
			 qname);
#endif
#if	(VALID_LIMITS & LIM_PPSTACK)
	fprintf (genfile, "set stack_limit = (");
	if (descr->v.que.v1.batch.infinite & LIM_PPSTACK)
	    fprintf (genfile, "unlimited) %s\n", qname);
	else
	    fprintf (genfile, "%lu %s) %s\n",
			 descr->v.que.v1.batch.ppstackcoeff, 
			 get_snap_units (descr->v.que.v1.batch.ppstackunits),
			 qname);
#endif
#if	(VALID_LIMITS & LIM_PPWORK)
	fprintf (genfile, "set working_set_limit = (");
	if (descr->v.que.v1.batch.infinite & LIM_PPWORK)
	    fprintf (genfile, "unlimited) %s\n", qname);
	else
	    fprintf (genfile, "%lu %s) %s\n",
			 descr->v.que.v1.batch.ppworkcoeff, 
			 get_snap_units (descr->v.que.v1.batch.ppworkunits),
			 qname);
#endif
#if     (VALID_LIMITS & LIM_PPCPUT)
	fprintf (genfile, "set per_process cpu_limit = (");
	if (descr->v.que.v1.batch.infinite & LIM_PPCPUT)
	    fprintf (genfile, "unlimited) %s\n", qname);
	else
	    fprintf (genfile, " %lu ) %s\n",
			 descr->v.que.v1.batch.ppcpusecs, qname);
#endif
#if     (VALID_LIMITS & LIM_PRCPUT)
	fprintf (genfile, "set per_request cpu_limit = (");
	if (descr->v.que.v1.batch.infinite & LIM_PRCPUT)
	    fprintf (genfile, "unlimited) %s\n", qname);
	else
	    fprintf (genfile, "%lu) %s\n",
			 descr->v.que.v1.batch.prcpusecs, qname);
#endif
#if     (VALID_LIMITS & LIM_PPNICE)
	fprintf (genfile, "set nice_value_limit=%d %s\n", 
		 descr->v.que.v1.batch.ppnice, qname);
#endif
	/*
	 *  Set up the queue's access restrictions
	 */
	if (descr->v.que.status & QUE_BYGIDUID) {
	    fprintf (genfile, "set no_access %s\n", qname);
	    snap_queacc (descr);
	}
	if (descr->v.que.status & QUE_RUNNING)  
		fprintf (genfile, "start queue %s\n", qname);
	if (descr->v.que.status & QUE_ENABLED)
		fprintf (genfile, "enable queue %s\n", qname);
	fflush (genfile);
}


static void snap_pipe (descr)
register struct gendescr *descr;
{
	char *qname;

	qname = descr->v.que.namev.name;
	fprintf (genfile, "#\n");
	fprintf (genfile, "#    Creating and defining pipe queue %s\n", qname);
	fprintf (genfile, "#\n");
	fprintf (genfile, "create pipe_queue %s priority=%d server=(%s)\n", qname, 
		 descr->v.que.priority, 
		 descr->v.que.v1.pipe.server);
	if (descr->v.que.status & QUE_PIPEONLY)
		fprintf (genfile, "set pipeonly %s\n", qname);
	if (descr->v.que.status & QUE_LDB_IN)
		fprintf (genfile, "set lb_in %s\n", qname);
	if (descr->v.que.status & QUE_LDB_OUT)
		fprintf (genfile, "set lb_out %s\n", qname);
	/*
	 *  Set the run limits.
	 */
	fprintf (genfile, "set run_limit=%d %s\n", 
		descr->v.que.v1.pipe.runlimit, qname);
	/*
	 *  Set up the queue's access restrictions
	 */
	if (descr->v.que.status & QUE_BYGIDUID) {
	    fprintf (genfile, "set no_access %s\n", qname);
	    snap_queacc (descr);
	}
	if (descr->v.que.status & QUE_RUNNING)
		fprintf (genfile, "start queue %s\n", qname);
	if (descr->v.que.status & QUE_ENABLED)
		fprintf (genfile, "enable queue %s\n", qname);
	fflush (genfile);
}


static void snap_queacc (descr)
struct gendescr *descr;
{
	
	int fd;				/* File descriptor */
	unsigned long buffer [QAFILE_CACHESIZ];
	int done;			/* Boolean */
	int cachebytes;			/* Try to read this much */
	int bytes;			/* Did read this much */
	int entries;			/* Did read this many */
	int i;				/* Loop variable */


	fd = openqacc (Queuefile, descr);
	/*
	 * Openqacc returns 0 if the queue is restricted and the file
	 * is open; -1 if the queue is unrestricted; -2 if the queue
	 * queue is restricted but the file is not open, and -3
	 * if the queue appears to have been deleted.
	 */
	if (fd < -1) return;
	done = 0;
	cachebytes = QAFILE_CACHESIZ * sizeof (unsigned long);
	while ((bytes = read (fd, (char *) buffer, cachebytes)) > 0) {
	    entries = bytes / sizeof (unsigned long);
	    for (i = 0; i < entries; i++) {
		/* Zero comes only at the end */
		if (buffer [i] == 0) {
		    done = 1;
		    break;
		}
		if (buffer [i] & MAKEGID) 	/* If a group */
			fprintf (genfile, "add groups = %s %s\n",
				getgrpnam ((int) buffer [i] & ~MAKEGID),
				descr->v.que.namev.name);
		else				/* A user */
			fprintf (genfile, "add users = %s %s\n",
						getusenam ((int) buffer [i]), 
						descr->v.que.namev.name);
	    }
	    if (done) break;
	}
	fflush (genfile);
}


static void snap_dest (que_descr)
struct gendescr *que_descr;		/* The queue descriptor */
{
	register struct gendescr *dbds1;/* NQS database file generic descr */
	register struct gendescr *dbds2;/* NQS database file generic descr */
	register short column;		/* Current output column */
	register short fldsiz;		/* Size of output field */
	char *rhostname;		/* Remote host destination name */
	
	if (telldb (Qmapfile) != -1) {
	    /*
	     *  We are not necessarily at the start of the
	     *  queue/device/destination descriptor database
	     *  file....
	     */
	    seekdbb (Qmapfile, 0L);	/* Seek to the beginning */
	}
	dbds1 = nextdb (Qmapfile);
	while (dbds1 != (struct gendescr *) 0) {
	    if (!dbds1->v.map.qtodevmap &&
		strcmp (dbds1->v.map.v.qdestmap.lqueue,
		    que_descr->v.que.namev.name) == 0) {
		/*
		 *  We have located a pipe-queue/destination mapping
		 *  for the pipe queue.
		 *
		 *  Now, locate the database description for the
		 *  pipe queue destination referenced in the mapping.
		 */
		if (telldb (Pipeqfile) != -1) {
		    /*
		     *  We are not necessarily at the start of the
		     *  pipe queue descriptor database file....
		     */
		    seekdbb (Pipeqfile, 0L);/* Seek to start */
		}
		dbds2 = nextdb (Pipeqfile);
		while (dbds2 != (struct gendescr *) 0 &&
		      (strcmp (dbds1->v.map.v.qdestmap.rqueue,
		       dbds2->v.dest.rqueue) ||
		       dbds1->v.map.v.qdestmap.rhost_mid !=
		       dbds2->v.dest.rhost_mid)) {
			/*
			 *  We have not yet located the pipe queue
			 *  destination referred to in the mapping
			 *  descriptor.
			 */
			dbds2 = nextdb (Pipeqfile);
		}
		if (dbds2 != (struct gendescr *) 0) {
		    /*
		     *  We have located the pipe-queue
		     *  descriptor for the mapping.
		     */
		    rhostname = getmacnam (dbds2->v.dest.rhost_mid);
		    fprintf (genfile, "add destination=");
		    if (dbds2->v.dest.rhost_mid == Local_mid)
		        fprintf (genfile, "%s %s\n", dbds2->v.dest.rqueue,
				que_descr->v.que.namev.name);
		    else
		        fprintf (genfile, "%s@%s %s\n",
				 dbds2->v.dest.rqueue,
				 getmacnam(dbds2->v.dest.rhost_mid),
				 que_descr->v.que.namev.name);
		}
	    }
	    dbds1 = nextdb (Qmapfile);
	}
}

static void snap_complex (descr)
register struct gendescr *descr;	/* NQS database file queue descr*/
{
	register int i;
	register int count;

	count = 0;
	for (i = 0; i < MAX_QSPERCOMPLX; i++) {
	    if (descr->v.qcom.queues[i][0] != NULL) {
		if (count) {
		    fprintf (genfile, "add queue=(%s) %s\n",
					 descr->v.qcom.queues[i],
					 descr->v.qcom.name);
		} else {
		    fprintf (genfile, "create complex=(%s) %s\n",
					 descr->v.qcom.queues[i],
					 descr->v.qcom.name);
		    count++;
		}
	    }
	}
	if (!count) return;
	/*
	 *  Produce the qmgr commands to set the complex limits.
	 */
	fprintf (genfile, "set complex run_limit=%d %s\n", 
		descr->v.qcom.runlimit, descr->v.qcom.name);
	fprintf (genfile, "set complex user_limit=%d %s\n",  
		 descr->v.qcom.userlimit, 
		 descr->v.qcom.name);
	fflush (genfile);
}


static void snap_managers()
{
	register struct gendescr *descr;  /* NQS database file queue descr*/

	seekdb (Mgrfile, 0L);
	descr = nextdb (Mgrfile);
	while ((descr = nextdb (Mgrfile)) != (struct gendescr *) 0) {
	    fprintf (genfile, "add managers ");
	    if (descr->v.mgr.manager_mid != Local_mid) 
		    fprintf (genfile, "[%d]@%s", (int) descr->v.mgr.manager_uid,
			     getmacnam (descr->v.mgr.manager_mid));
	    else fprintf (genfile, "%s", getusenam (descr->v.mgr.manager_uid));
	    if (descr->v.mgr.privileges & QMGR_MGR_PRIV)
		    fprintf (genfile, ":m\n");
	    else fprintf (genfile, ":o\n");
	}
	fflush (genfile);
}
 
static void snap_servers()
{
        register struct gendescr *descr;  /* NQS database file queue descr*/

        seekdb (Serverfile, 0L);
        /* descr = nextdb (Serverfile); */
        while ((descr = nextdb (Serverfile)) != (struct gendescr *) 0) {
            fprintf (genfile, "set server performance=");
	    fprintf (genfile, "%d %s\n", descr->v.cserver.rel_perf,
			getmacnam (descr->v.cserver.server_mid) );
        }
        fflush (genfile);
}


static void snap_param ()
{

	fprintf (genfile, "set debug %d\n", Debug);
	fprintf (genfile, "set default batch_request priority %d\n", Defbatpri);
	if (Defbatque [0] != '\0')
		fprintf (genfile, "set default batch_request queue %s\n", Defbatque);
	fprintf (genfile, "set default destination_retry time %d\n",  
		 (long) Defdesrettim / 3600);
	fprintf (genfile, "set default destination_retry wait %d\n", 
		 (long) Defdesretwai / 60);
	fprintf (genfile, "set lifetime %d\n", Lifetime / 3600);
	if (Logfilename [0] != '\0')
		fprintf (genfile, "set log_file  %s\n",  Logfilename);
	fprintf (genfile, "set mail %s\n", getusenam (Mail_uid));
	if (Netclient [0] != '\0')
		fprintf (genfile, "set network client=(%s)\n", Netclient);
	if (Netdaemon [0] != '\0')
		fprintf (genfile, "set network daemon=(%s)\n", Netdaemon);
	if (Netserver [0] != '\0')
		fprintf (genfile, "set network server=(%s)\n", Netserver);
	if (Loaddaemon [0] != '\0')
		fprintf (genfile, "set load_daemon=(%s)\n", Loaddaemon);
	fprintf (genfile, "set shell_strategy ");
	if (Shell_strategy == SHSTRAT_FREE)
		fprintf (genfile, "free\n");
	else if (Shell_strategy == SHSTRAT_LOGIN)
		fprintf (genfile, "login\n");
	else
		fprintf (genfile, "fixed (%s)\n",Fixed_shell);
	if (Plockdae)
		fprintf (genfile, "lock local_daemon\n");
	if (LB_Scheduler)
		fprintf (genfile, "set scheduler %s\n", fmtmidname(LB_Scheduler));
	else
		fprintf (genfile, "set no_scheduler\n");
	fprintf(genfile,  "set default load_interval %d\n", Defloadint/60);
	fflush (genfile);
}  



static void snap_global ()
{
	int i;

	fprintf (genfile, "set global batch_limit=%d\n",  Maxgblbatlimit);
	fprintf (genfile, "set global pipe_limit=%d\n",  Maxgblpiplimit);
	fflush (genfile);
}

static char *get_snap_units (units)
register short units;
{
	switch (units) {
	case QLM_BYTES:
		return ("b");
	case QLM_WORDS:
		return ("w");
	case QLM_KBYTES:
		return ("kb");
	case QLM_KWORDS:
		return ("kw");
	case QLM_MBYTES:
		return ("mb");
	case QLM_MWORDS:
		return ("mw");
	case QLM_GBYTES:
		return ("gb");
	case QLM_GWORDS:
		return ("gw");
	}
	return ("");		/* Unknown units! */
}

