/*
 *
 * Copyright 1998-1999, University of Notre Dame.
 * Authors: Jeffrey M. Squyres, Kinis L. Meyer with M. D. McNally 
 *          and Andrew Lumsdaine
 *
 * This file is part of the Notre Dame LAM implementation of MPI.
 *
 * You should have received a copy of the License Agreement for the
 * Notre Dame LAM implementation of MPI along with the software; see
 * the file LICENSE.  If not, contact Office of Research, University
 * of Notre Dame, Notre Dame, IN 46556.
 *
 * Permission to modify the code and to distribute modified code is
 * granted, provided the text of this NOTICE is retained, a notice that
 * the code was modified is included with the above COPYRIGHT NOTICE and
 * with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
 * file is distributed with the modified code.
 *
 * LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
 * By way of example, but not limitation, Licensor MAKES NO
 * REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
 * PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
 * OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
 * OR OTHER RIGHTS.  
 *
 * Additional copyrights may follow.
 *
 *	Ohio Trollius
 *	Copyright 1997 The Ohio State University
 *	GDB
 *
 *	$Id: kkill.c,v 6.4 1999/08/26 22:22:53 jsquyres Exp $
 * 
 *	Function:	- supports client cleanup by the kernel and by tkill(1)
 *			- OTB specific code
 */

#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
               
#include <kreq.h>
#include <typical.h>

/*
 * global functions
 */
void			kkillall();
int			kkillclose();
int			kkillopen();
int			kkillrewrite();
int			kkillwrite();

/*
 * external variables
 */
extern struct kproc	*pready;
extern struct kproc	*pblock;

/*
 * local variables
 */
static FILE		*fp_kill;	/* kill file ptr */
static int		fd_kill;	/* kill file desc. */

/*
 *	kkillall
 *
 *	Function:	- catches SIGTERM and SIGHUP
 *			- kills all attached processes
 *			- exits
 */
void
kkillall()

{
	struct kproc	*p;

	for (p = pready; p; p = p->kp_next) {

		if (!(p->kp_flags & KIPROC)) {
			kill(p->kp_pid, SIGCONT);
			kill(p->kp_pid, SIGHUP);
		}
	}

	for (p = pblock; p; p = p->kp_next) {

		if (!(p->kp_flags & KIPROC)) {
			kill(p->kp_pid, SIGCONT);
			kill(p->kp_pid, SIGHUP);
		}
	}

	exit(0);
}

/*
 *	kkillopen
 *
 *	Function:	- opens the kill file
 *			- locates the kill directory and constructs
 *			  the full kill pathname by appending the
 *			  userid to the kill directory
 *			- writes the kernel's own pid in the first
 *			  entry of the kill file
 *	Accepts:	- kill filename
 *	Returns:	- 0 or LAMERROR
 */
int
kkillopen(f_kill)

char			*f_kill;

{
	fd_kill = open(f_kill, O_WRONLY | O_CREAT | O_EXCL, 0200);

	if (fd_kill < 0) {
		return(LAMERROR);
	}

	fp_kill = fdopen(fd_kill, "w");

	if (! fp_kill) {
		return(LAMERROR);
	}

	setvbuf(fp_kill, (char *) 0, _IOLBF, 0);

	if (fprintf(fp_kill, "%d\n", (int) getpid()) == EOF) {
		return(LAMERROR);
	}

	if (chmod(f_kill, 0644)) {
		return(LAMERROR);
	}

	return(0);
}

/*
 *	kkillwrite
 *
 *	Function:	- writes pid into lock file
 *	Accepts:	- pid
 *	Returns:	- 0 or LAMERROR
 */
int
kkillwrite(pid)

int4			pid;

{
	if (fprintf(fp_kill, "%d\n", pid) == EOF) {
		return(LAMERROR);
	} else {
		return(0);
	}
}

/*
 *	kkillrewrite
 *
 *	Function:	- rewrites entire kill file from current process list
 *	Accepts:	- kernel process table
 *	Returns:	- 0 or LAMERROR
 */
int
kkillrewrite(kptable)

struct kproc		kptable[];

{
	int		i;
/*
 * Rewind the stdio descriptor.
 */
	rewind(fp_kill);
/*
 * Write the kernel pid first.
 */
	if (fprintf(fp_kill, "%d\n", (int) getpid()) == EOF) {
		return(LAMERROR);
	}
/*
 * Write every current client pid.
 */
	for (i = 0; i < KPMAX; ++i) {

		if ((kptable[i].kp_state != KSFREE) &&
				!(kptable[i].kp_flags & KIPROC)) {

			if (fprintf(fp_kill, "%d\n", kptable[i].kp_pid)
					== EOF) {
				return(LAMERROR);
			}
		}
	}
/*
 * Truncate file to new length.
 */
#ifdef SCO
	if (chsize(fd_kill, ftell(fp_kill))) {
#else
	if (ftruncate(fd_kill, ftell(fp_kill))) {
#endif
		return(LAMERROR);
	}

	return(0);
}

/*
 *	kkillclose
 *
 *	Function:	- Flush and close the kill file.
 *	Returns:	- 0 or LAMERROR
 */
int
kkillclose()

{
	if (fclose(fp_kill) == EOF) {
		return(LAMERROR);
	} else {
		return(0);
	}
}
