/*
* Copyright (c) 2001-2003 The Trustees of Indiana University.
* All rights reserved.
* Copyright (c) 1998-2001 University of Notre Dame.
* All rights reserved.
* Copyright (c) 1994-1998 The Ohio State University.
* All rights reserved.
*
* This file is part of the LAM/MPI software package. For license
* information, see the LICENSE file in the top level directory of the
* LAM/MPI source distribution.
*
* $HEADER$
* Ohio Trollius
* Copyright 1997 The Ohio State University
* GDB/RBD
*
* $Id: clientio.c,v 1.8 2003/11/02 20:08:40 brbarret Exp $
*
* Function: - interface between kernel runtime request library
* and native environment
*/
#include <lam_config.h>
#include <sfh.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include <fcntl.h>
#include <unistd.h>
#include <freq.h>
#include <kio.h>
#include <kreq.h>
#include <laminternal.h>
#include <terror.h>
#include <typical.h>
/*
* global functions
*/
void _cio_bail(); /* terminate self */
void _cio_cleanup(); /* mach. dep. cleanup */
int _cio_init(void); /* initialize kernel I/O */
/* make a kernel request */
int _cio_kreq(struct kreq *pkq, struct kreply *pkr);
int _cio_kreqback(struct kreply *pkr); /* 1st half of kreq */
int _cio_kreqfront(struct kreq *pkq); /* 2nd half of kreq */
int _cio_send(struct kmsg *pkmsg); /* send data */
int _cio_recv(struct kmsg *pkmsg); /* recv data */
/*
* external variables
*/
struct kio_t _kio; /* Kernel I/O block */
struct fclient _ufd[FUMAX]; /* user file desc. */
/*
* local variables
*/
static int sd_kernel; /* kernel socket */
/*
* _cio_init
*
* Function: - initializes kernel interface
* - establishes UDP INET domain socket to communicate
* with the kernel and other Trollius processes
* Returns: - 0 or ERROR
*/
int
_cio_init()
{
char *p;
int errnosave;
(void) _lam_signal(SIGPIPE, 0);
if (lam_tmpdir_init(NULL, NULL) != 0)
return LAMERROR;
if ((p = lam_get_sockname()) == NULL)
return(LAMERROR);
sd_kernel = sfh_sock_open_clt_unix_stm(p);
errnosave = errno;
free(p);
if (sd_kernel < 0) {
/* According to new semantics of
sfh_sock_open_clt_unix_stm(), ECONNREFUSED and ETIMEDOUT
will also return a failure. See lengthy comment in
share/etc/socket.c. If this is the case, be sure to
remove the extra directory that we created to put the
socket in. */
if ((errnosave == ENOENT) || (errnosave == ENXIO) ||
(errnosave == ECONNREFUSED) || (errnosave == ETIMEDOUT) ) {
lam_tmpdir_remove();
errno = ENOKERNEL;
}
return(LAMERROR);
}
if (sfh_sock_set_buf_size(sd_kernel, SFH_UNIX, SO_SNDBUF,
KPKTLEN + sizeof(struct nmsg))) {
return(LAMERROR);
}
if (sfh_sock_set_buf_size(sd_kernel, SFH_UNIX, SO_RCVBUF,
KPKTLEN + sizeof(struct nmsg))) {
return(LAMERROR);
}
/*
* Set default stdio node and descriptors.
*/
_kio.ki_ionode = NOTNODEID;
_kio.ki_stdin = 0;
_kio.ki_stdout = 1;
_kio.ki_stderr = 2;
if ((p = getenv("TROLLIUSFD"))) {
_kio.ki_ionode = stoi((unsigned char *) p);
p = strchr(p, ':') + 1;
_kio.ki_stdin = stoi((unsigned char *) p);
p = strchr(p, ':') + 1;
_kio.ki_stdout = stoi((unsigned char *) p);
p = strchr(p, ':') + 1;
_kio.ki_stderr = stoi((unsigned char *) p);
}
_kio.ki_pid = -1;
/*
* Get any inherited runtime flags.
*/
_kio.ki_rtf = (p = getenv("TROLLIUSRTF"))
? stoi((unsigned char *) p) : 0;
/*
* Have we been forked?
*/
if ((p = getenv("LAMKENYAPID"))) {
if (getppid() != stoi((unsigned char *) p)) {
_kio.ki_rtf &= ~(RTF_WAIT | RTF_FLAT);
_kio.ki_rtf |= RTF_FORKED;
}
}
/*
* Some APIs want to know the total world population, a-priori.
*/
_kio.ki_world = (p = getenv("LAMWORLD")) ? stoi((unsigned char *) p) : 0;
_kio.ki_parent = (p = getenv("LAMPARENT"))
? stoi((unsigned char *) p) : 0;
/*
* Set the LAM job identifier.
*/
if ((p = getenv("LAMJOBID"))) {
_kio.ki_jobid.jid_node = stoi((unsigned char *) p);
p = strchr(p, ':') + 1;
_kio.ki_jobid.jid_pid = stoi((unsigned char *) p);
}
return(0);
}
/*
* _cio_kreq
*
* Function: - makes a kernel request
* Accepts: - kernel request ptr
* - kernel reply ptr
* Returns: - 0 or ERROR
*/
int
_cio_kreq(struct kreq *pkq, struct kreply *pkr)
{
if (_cio_kreqfront(pkq) < 0) {
return(ERROR);
}
return(_cio_kreqback(pkr));
}
/*
* _cio_kreqfront
*
* Function: - front half of a kernel request
* - sends the request structure to the kernel
* - verifies kernel connection
* Accepts: - kernel request ptr
* Returns: - client/kernel socket or ERROR
*/
int
_cio_kreqfront(struct kreq *pkq)
{
/*
* Send the request to the kernel.
*/
if (mwrite(sd_kernel, (char *) pkq, sizeof(struct kreq)) <
(int)sizeof(struct kreq)) {
if (errno == EPIPE) {
if (pkq->kq_req != KQATTACH) {
exit(ENOKERNEL);
} else {
errno = ENOKERNEL;
}
}
return(LAMERROR);
}
return(sd_kernel);
}
/*
* _cio_kreqback
*
* Function: - back half of a kernel request
* - receives the reply structure from the kernel
* Accepts: - kernel reply ptr
* Returns: - 0 or ERROR
*/
int
_cio_kreqback(struct kreply *pkr)
{
if (mread(sd_kernel, (char *) pkr, sizeof(struct kreply)) <
(int)sizeof(struct kreply)) {
if (errno == EEOF) exit(ENOKERNEL);
return(LAMERROR);
}
return(0);
}
/*
* _cio_recv
*
* Function: - receives a message from another process
* through the kernel
* Accepts: - kernel msg desc.
* Returns: - 0 or ERROR
*/
int
_cio_recv(struct kmsg *pkmsg)
{
int4 r;
int4 totlen;
struct iovec iov[2];
char *sv_msg;
if (pkmsg->k_flags & KPROBE) {
return(0);
}
totlen = pkmsg->k_length;
if (pkmsg->k_flags & KNMSG) {
sv_msg = ((struct nmsg *) (pkmsg->k_msg))->nh_msg;
iov[0].iov_base = pkmsg->k_msg;
iov[0].iov_len = sizeof(struct nmsg);
iov[1].iov_base = sv_msg;
iov[1].iov_len = pkmsg->k_length;
totlen += sizeof(struct nmsg);
r = mreadv(sd_kernel, iov, 2);
((struct nmsg *) (pkmsg->k_msg))->nh_msg = sv_msg;
} else {
r = mread(sd_kernel, pkmsg->k_msg, pkmsg->k_length);
}
if (r < totlen) {
if (errno == EEOF) {
errno = ENOKERNEL;
}
return(LAMERROR);
}
return(0);
}
/*
* _cio_send
*
* Function: - sends a message to another process
* through the kernel
* Accepts: - kernel msg desc.
* Returns: - 0 or ERROR
*/
int
_cio_send(struct kmsg *pkmsg)
{
int4 r;
int4 totlen;
struct iovec iov[2];
totlen = pkmsg->k_length;
if (pkmsg->k_flags & KNMSG) {
iov[0].iov_base = pkmsg->k_msg;
iov[0].iov_len = sizeof(struct nmsg);
iov[1].iov_base = ((struct nmsg *) (pkmsg->k_msg))->nh_msg;
iov[1].iov_len = pkmsg->k_length;
totlen += sizeof(struct nmsg);
r = mwritev(sd_kernel, iov, 2);
} else {
r = mwrite(sd_kernel, pkmsg->k_msg, pkmsg->k_length);
}
if (r < totlen) {
if (errno == EPIPE) {
errno = ENOKERNEL;
}
return(LAMERROR);
}
return(0);
}
/*
* _cio_cleanup
*
* Function: - closes communication sockets
*/
void
_cio_cleanup()
{
close(sd_kernel);
}
/*
* _cio_bail
*
* Function: - terminates the process
* Accepts: - exit status
*/
void
_cio_bail(int status)
{
exit(status);
}
syntax highlighted by Code2HTML, v. 0.9.1