V10/ipc/mgrs/4.3gate/main.c
#include "ipc.h"
#include "mgr.h"
#include <errno.h>
#include <sys/types.h>
#include <sys/filio.h>
/* buffer definition */
#define BUFLEN 512
/* our name */
char *ipcname;
/*
* timeout routine
*/
static int
dingaling()
{
signal(SIGALRM, dingaling);
}
/*
* gate a call to the arpanet
*/
main()
{
int caller, callee;
ipcinfo info;
ipcinfo *ip;
fd_set fds;
char newname[BUFLEN];
int (*oldsig)();
/*
* get the original request
*/
info.uid = info.gid = 0;
info.user="root";
if (_info_read(caller, &info)<0)
return -1;
/*
* dial the number
*/
sprintf(newname, "%s!%s", "/cs/tcp", info.name);
info.name = newname;
info.rfd = info.cfd = -1;
oldsig=signal(SIGALRM, dingaling);
alarm(30);
callee = ipcdial(&info);
alarm(0);
signal(SIGALRM, oldsig);
/*
* return status
*/
if (callee<0) {
_reply_write(caller, errno, errstr);
close(caller);
return -1;
}
if (_reply_write(caller, 0, ipcname)<0) {
close(caller);
close(callee);
return -1;
}
/*
* For creat's, we accept only one call per creat. This
* makes life a lot simpler though less general.
*/
if(info.flags & IPC_CREAT) {
int nfd;
if((ip = ipclisten(callee)) == NULL)
exit(0);
if(_info_write(caller, ip) < 0)
exit(0);
if(_reply_read(caller) < 0)
exit(0);
if(errno) {
ipcreject(ip, errno, errstr);
exit(0);
} else {
nfd = ipcdaccept(ip, -1, ipcname);
close(callee);
callee = nfd;
}
}
/*
* shuttle bytes back and forth
*/
FD_ZERO(fds);
for(;;) {
FD_SET(caller, fds);
FD_SET(callee, fds);
switch(select(NOFILE, &fds, (struct fd_set *)0, 1000)) {
case -1:
return -1;
case 0:
continue;
}
if (FD_ISSET(caller, fds))
if (pass(caller, callee)<0)
exit(0);
if (FD_ISSET(callee, fds))
if (pass(callee, caller)<0)
exit(0);
}
}
pass(from, to)
int from, to;
{
char buf[4096];
int n;
if ((n=read(from, buf, sizeof(buf)))<=0)
return -1;
if (write(to, buf, n)!=n)
return -1;
return 0;
}
/*
* Send the connection info.
*/
int
_info_write(fd, ip)
int fd;
ipcinfo *ip;
{
char b[BUFLEN];
int n;
if (ip->name==NULL)
ip->name = "";
if (ip->param==NULL)
ip->param = "";
if (ip->machine==NULL)
ip->machine = "";
if (ip->user==NULL)
ip->user = "";
if (ip->myname==NULL)
ip->myname = "";
sprintf(b, "%s\n%s\n%s\n%s\n%s\n%d\n%d\n%d\n", ip->myname, ip->name,
ip->param, ip->machine, ip->user, ip->flags, ip->uid, ip->gid);
n = strlen(b);
if (write(fd, b, n)!=n)
return ABORT(errno, "can't send request", NULLINFO);
return 0;
}
/* dial a number or plug into the name space */
ipcdial(ip)
ipcinfo *ip;
{
/*
* decode the call
*/
if(
if (ip->flags && IPC_CREAT){
/* plug into the name space */
} else {
}
}
/* listen for a connection */
ipcinfo *
ipclisten(fd)
int fd;
{
static ipcinfo info;
static char buf[BUFSIZE];
static char user[32];
/* accept only one connection */
info.rfd = fd;
close(fd);
/* get the request */
if (_info_read(info.rfd, &info)<0) {
/* requestor gave up */
close(info.rfd);
return NULL;
}
return &info;
}
/*
* Accept a connection. Close all except ip->cfd.
*/
int
ipcaccept(ip)
ipcinfo *ip;
{
ipcdaccept(ip, -1, "who_cares");
}
/*
* Accept a connection, and supply a source address and communications fd
*/
int
ipcdaccept(ip, commfd, source)
ipcinfo *ip;
int commfd;
char *source;
{
if (commfd >= 0) {
/* supply our own channel for communications */
if (_fd_write(ip->rfd, commfd) < 0) {
close(commfd);
return ABORT(errno, "can't pass conection", ip);
}
_reply_write(ip->rfd, 0, source);
ABORT(0, "", ip);
ip->cfd = commfd;
} else if (ip->cfd >= 0) {
/* use client supplied channel for communications */
_reply_write(ip->rfd, 0, "");
close(ip->rfd);
ip->rfd = -1;
} else {
/* use reply channel for communications */
_reply_write(ip->rfd, 0, "");
ip->cfd = ip->rfd;
ip->rfd = -1;
}
return(ip->cfd);
}
/* Reject a connection.
*/
int
ipcreject(ip, no, str)
ipcinfo *ip;
int no; /* error number */
char *str; /* error string */
{
_reply_write(ip->rfd, no, str);
ABORT(no, str, ip);
return 0;
}