Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F85110208
devcomm.c
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Thu, Sep 26, 20:38
Size
5 KB
Mime Type
text/x-c
Expires
Sat, Sep 28, 20:38 (2 d)
Engine
blob
Format
Raw Data
Handle
21130177
Attached To
R10977 RADIANCE Photon Map
devcomm.c
View Options
#ifndef lint
static const char RCSid[] = "$Id: devcomm.c,v 2.19 2016/08/18 00:52:48 greg Exp $";
#endif
/*
* devcomm.c - communication routines for separate drivers.
*
* External symbols declared in driver.h
*/
#include "copyright.h"
#include <sys/types.h>
#if !defined(_WIN32) && !defined(_WIN64)
#include <sys/wait.h>
#endif
#include "paths.h"
#include "platform.h"
#include "standard.h"
#include "driver.h"
#ifndef DEVPATH
#define DEVPATH getenv("PATH") /* device search path */
#endif
FILE *devin, *devout;
int devchild;
static struct driver * final_connect(void);
static void mygets(char *s, FILE *fp);
static void myputs(char *s, FILE *fp);
static void reply_error(char *routine);
static void getstate(void);
static dr_closef_t comm_close;
static dr_clearf_t comm_clear;
static dr_paintrf_t comm_paintr;
static dr_getcurf_t comm_getcur;
static dr_comoutf_t comm_comout;
static dr_cominf_t comm_comin;
static dr_flushf_t comm_flush;
struct driver comm_driver = {
comm_close, comm_clear, comm_paintr, comm_getcur,
comm_comout, comm_comin, comm_flush
};
static struct driver *
final_connect(void) /* verify and initialize connection */
{
putw(COM_SENDM, devout);
fflush(devout);
if (getw(devin) != COM_RECVM)
return(NULL);
/* get driver parameters */
getstate();
/* set error vectors */
erract[COMMAND].pf = comm_comout;
/* doesn't work with raypcalls.c
if (erract[WARNING].pf != NULL)
erract[WARNING].pf = comm_comout;
*/
return(&comm_driver);
}
struct driver *
slave_init( /* run rview in slave mode */
char *dname,
char *id
)
{
devchild = -1; /* we're the slave here */
devout = stdout; /* use standard input */
devin = stdin; /* and standard output */
return(final_connect()); /* verify initialization */
}
struct driver *
comm_init( /* set up and execute driver */
char *dname,
char *id
)
{
char *dvcname;
int p1[2], p2[2];
char pin[16], pout[16];
/* find driver program */
if ((dvcname = getpath(dname, DEVPATH, X_OK)) == NULL) {
eputs(dname);
eputs(": not found\n");
return(NULL);
}
#ifdef RHAS_FORK_EXEC
/* open communication pipes */
if (pipe(p1) == -1 || pipe(p2) == -1)
goto syserr;
if ((devchild = fork()) == 0) { /* fork driver process */
close(p1[1]);
close(p2[0]);
sprintf(pin, "%d", p1[0]);
sprintf(pout, "%d", p2[1]);
execl(dvcname, dname, pin, pout, id, NULL);
perror(dvcname);
_exit(127);
}
if (devchild == -1)
goto syserr;
close(p1[0]);
close(p2[1]);
/*
* Close write stream on exec to avoid multiprocessing deadlock.
* No use in read stream without it, so set flag there as well.
*/
fcntl(p1[1], F_SETFD, FD_CLOEXEC);
fcntl(p2[0], F_SETFD, FD_CLOEXEC);
if ((devout = fdopen(p1[1], "w")) == NULL)
goto syserr;
if ((devin = fdopen(p2[0], "r")) == NULL)
goto syserr;
return(final_connect()); /* verify initialization */
syserr:
perror(dname);
return(NULL);
#else /* ! RHAS_FORK_EXEC */
eputs(dname);
eputs(": no fork/exec\n");
return(NULL);
#endif /* ! RHAS_FORK_EXEC */
}
static void
comm_close(void) /* done with driver */
{
int pid;
erract[COMMAND].pf = NULL; /* reset error vectors */
if (erract[WARNING].pf != NULL)
erract[WARNING].pf = wputs;
fclose(devout);
fclose(devin);
if (devchild < 0)
return;
#if !defined(_WIN32) && !defined(_WIN64)
while ((pid = wait(0)) != -1 && pid != devchild)
;
#endif
}
static void
comm_clear( /* clear screen */
int xres,
int yres
)
{
putc(COM_CLEAR, devout);
putw(xres, devout);
putw(yres, devout);
fflush(devout);
}
static void
comm_paintr( /* paint a rectangle */
COLOR col,
int xmin,
int ymin,
int xmax,
int ymax
)
{
putc(COM_PAINTR, devout);
putbinary(col, sizeof(COLOR), 1, devout);
putw(xmin, devout);
putw(ymin, devout);
putw(xmax, devout);
putw(ymax, devout);
}
static void
comm_flush(void) /* flush output to driver */
{
putc(COM_FLUSH, devout);
fflush(devout);
if (getc(devin) != COM_FLUSH)
reply_error("flush");
getstate();
}
static int
comm_getcur( /* get and return cursor position */
int *xp,
int *yp
)
{
int c;
putc(COM_GETCUR, devout);
fflush(devout);
if (getc(devin) != COM_GETCUR)
reply_error("getcur");
c = getc(devin);
*xp = getw(devin);
*yp = getw(devin);
return(c);
}
static void
comm_comout( /* print string to command line */
char *str
)
{
putc(COM_COMOUT, devout);
myputs(str, devout);
if (str[strlen(str)-1] == '\n')
fflush(devout);
}
static void
comm_comin( /* read string from command line */
char *buf,
char *prompt
)
{
putc(COM_COMIN, devout);
if (prompt == NULL)
putc(0, devout);
else {
putc(1, devout);
myputs(prompt, devout);
}
fflush(devout);
if (getc(devin) != COM_COMIN)
reply_error("comin");
mygets(buf, devin);
getstate();
}
static void
mygets( /* get string from file (with nul) */
char *s,
FILE *fp
)
{
int c;
while ((c = getc(fp)) != EOF)
if ((*s++ = c) == '\0')
return;
*s = '\0';
}
static void
myputs( /* put string to file (with nul) */
char *s,
FILE *fp
)
{
do
putc(*s, fp);
while (*s++);
}
static void
reply_error( /* what should we do here? */
char *routine
)
{
eputs(routine);
eputs(": driver reply error\n");
quit(1);
}
static void
getstate(void) /* get driver state variables */
{
getbinary((char *)&comm_driver.pixaspect,
sizeof(comm_driver.pixaspect), 1, devin);
comm_driver.xsiz = getw(devin);
comm_driver.ysiz = getw(devin);
comm_driver.inpready = getw(devin);
}
Event Timeline
Log In to Comment