/*
 * utility/nqsmkdirs.c
 * 
 * DESCRIPTION:
 *
 *
 *	Construct all of the subdirectories used by NQS to store
 *	request control, data, output, and transaction state files.
 *
 *
 *	Original Author:
 *	-------
 *	Brent A. Kingsbury, Sterling Software Incorporated.
 *	March 6, 1986.
 */

#include <libnqs/license.h>
/* Generic NQS license information */
#include <libnqs/defines.h>
#include <libnqs/types.h>
#include <libnqs/proto.h>
#include <libnqs/nqsdirs.h>

#include <libsal/license.h>
#include <libsal/libsal.h>

#include <stdio.h>
#include <grp.h>
#include <pwd.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>

static void makedirectory ( int no_of_subdirs, char *parent_name);

/*** main
 *
 *
 *	int main():
 */
int main (void)
{
	char *base_dir;


        if ( ! buildenv()) {
                fprintf (stderr, "Unable to establish directory ");
                fprintf (stderr, "independent environment.\n");
                fflush (stdout);
                fflush (stderr);
                exit(1);                /* Exit */
        }
	if (getuid() != 0) {
		/*
		 *  You must be running as root to run this utility.
		 */
		printf ("Utility [nqsmkdirs]:  User is not root.\n");
		printf ("Utility [nqsmkdirs]:  Aborting.\n");
		fflush (stdout);
		fflush (stderr);
		exit (1);
	}
	/*
	 *  Change our directory to the NQS root directory to begin
	 *  our work.
	 */
        base_dir = getfilnam (Nqs_root, SPOOLDIR);
        if (base_dir == (char *)NULL) {
                printf ("Utility [rnqsmkdirs]:  Unable to determine ");
                printf ("root directory name.\n");
                exit (5);
        }

	if (chdir (base_dir) == -1) {
		/*
		 *  Unable to change directory to the NQS root directory.
		 */
		printf ("Utility [nqsmkdirs]:  Unable to chdir to %s.\n", base_dir);
		printf ("Utility [nqsmkdirs]:  Reason: %s.\n",
			libsal_err_strerror(errno));
		printf ("Utility [nqsmkdirs]:  Aborting.\n");
		relfilnam (base_dir);
		fflush (stdout);
		fflush (stderr);
		exit (5);
	}
	relfilnam (base_dir);
	/*
	 *  The subdirectories that we are going to create, must be created
	 *  with a mode of 777.  Therefore, we clear the umask....
	 */
	umask (0);
	/*
	 *  Build the necessary subdirectories.
	 */
	makedirectory (MAX_CTRLSUBDIRS, Nqs_control);
	makedirectory (MAX_DATASUBDIRS, Nqs_data);
	makedirectory (MAX_OUTPSUBDIRS, Nqs_output);
	makedirectory (MAX_TDSCSUBDIRS, Nqs_transact);
	printf ("Utility [nqsmkdirs]:  NQS database subdirectory ");
	printf ("construction is complete.\n");
	printf ("Utility [nqsmkdirs]:  Exiting.\n");
	fflush (stdout);
	fflush (stderr);
	sync();				/* Schedule all dirty system I/O */
					/* buffers for writing (so that */
					/* directory blocks refering to the */
					/* newly created files will be */
					/* securely written to disk */
	exit (0);
}


/*** makedirectory()
 *
 *
 *	void makedirectory():
 *
 *	Construct the subdirectories for the specified NQS database parent
 *	directory.
 */
static void makedirectory (int no_of_subdirs, char *parent_name)
/* int no_of_subdirs;			#of subdirectories to create */
/* char *parent_name;			Name of parent directory */
/* uid_t owner_uid;			Owner user-id */
/* gid_t owner_gid;			Owner group-id */
{
	char *argv [4];			/* Argv() to mkdir() */
	char *envp [1];			/* Envp() to mkdir() */
	char path [MAX_PATHNAME+1];	/* NQS pathname */
	register int i;			/* Iteration counter */
	int waitstatus;			/* Child wait status */
	int childpid;			/* Child process-id */
#if	IS_HPUX
	char	command[512];
#endif

	/*
	 *  Loop to create the control-file directory subdirectories.
	 */
	for (i = 0; i < no_of_subdirs; i++) {
		childpid = fork();
		if (childpid == -1) {
			/*
			 *  The fork was not successful!
			 */
			printf ("Utility [nqsmkdirs]:  Unable to fork() ");
			printf ("mkdir process.\n");
			printf ("Utility [nqsmkdirs]:  Reason: %s.\n",
				libsal_err_strerror(errno));
			printf ("Utility [nqsmkdirs]:  Aborting.\n");
			fflush (stdout);
			fflush (stderr);
			sync();		/* Schedule all dirty system I/O */
					/* buffers for writing (so that */
					/* directory blocks refering to the */
					/* newly created files will be */
					/* securely written to disk */
			exit (6);
		}
		if (childpid == 0) {
			/*
			 *  We are the child mkdir process.
			 */
			pack6name (path, parent_name, (int) i, (char *) 0,
				   0L, 0, 0L, 0, 0, 0);
#if	IS_HPUX
			sprintf(command, "mkdir -p %s",path);
			printf ("Utility [nqsmkdirs]:  Executing: %s.\n",
				command);
			system(command);
			exit(0);
#else
#if	IS_DECOSF
			argv [0] = "mkdir";
#else
			argv [0] = "-mkdir";
#endif
			argv [1] = path;
			argv [2] = (char *) 0;
			envp [0] = (char *) 0;
			/*
			 *  Create the named directory.
			 */
			printf ("Utility [nqsmkdirs]:  Creating: %s.\n",
				path);
#if	IS_DECOSF
			execve ("/sbin/mkdir", argv, envp);
#else
			execve ("/bin/mkdir", argv, envp);
#endif
			/*
			 *  The execve() failed!
			 */
			printf ("Utility [nqsmkdirs]:  Unable to execve() ");
			printf ("mkdir program.\n");
			printf ("Utility [nqsmkdirs]:  Reason: %s.\n",
				libsal_err_strerror(errno));
			printf ("Utility [nqsmkdirs]:  Exiting.\n");
			fflush (stdout);
			fflush (stderr);
			kill (getpid(), 9);	/* Kill ourselves so */
						/* that the parent aborts */
						/* as well */
#endif
		}
		/*
		 *  As the parent, we wait for the mkdir process
		 *  to complete.
		 */
		while (wait (&waitstatus) == -1 && errno == EINTR)
			;
		/*
		 *  The child has exited.
		 */
		if ((waitstatus & 0xFF) == 0) {
			/*
			 *  The mkdir process exited normally.
			 */
			printf ("Utility [nqsmkdirs]:  mkdir exited (%1d).\n",
			       (waitstatus >> 8) & 0xFF);
		}
		else if ((waitstatus & 0xFF00) == 0) {
			/*
			 *  The mkdir process was terminated by a signal!
			 */
			printf ("Utility [nqsmkdirs]:  mkdir terminated ");
			printf ("by signal (%1d).\n", waitstatus & 0x7F);
			printf ("Utility [nqsmkdirs]:  Aborting.\n");
			fflush (stdout);
			fflush (stderr);
			sync();		/* Schedule all dirty system I/O */
					/* buffers for writing (so that */
					/* directory blocks refering to the */
					/* newly created files will be */
					/* securely written to disk */
			exit (7);
		}
		else {
			/*
			 *  The mkdir program stopped!
			 */
			printf ("Utility [nqsmkdirs]:  mkdir stopped by ");
			printf ("signal (%1d).\n", (waitstatus >> 8) & 0xFF);
			printf ("Utility [nqsmkdirs]:  Aborting.\n");
			fflush (stdout);
			fflush (stderr);
			sync();		/* Schedule all dirty system I/O */
					/* buffers for writing (so that */
					/* directory blocks refering to the */
					/* newly created files will be */
					/* securely written to disk */
			exit (8);
		}
		/*
		 *  Change the mode of any previously existing subdirectories
		 *  to 777.
		 */
		chmod (path, 0777);
	}
}
