Back to index

radiance  4R0+20100331
devcomm.c
Go to the documentation of this file.
00001 #ifndef lint
00002 static const char    RCSid[] = "$Id: devcomm.c,v 2.15 2008/08/21 07:05:58 greg Exp $";
00003 #endif
00004 /*
00005  *  devcomm.c - communication routines for separate drivers.
00006  *
00007  *  External symbols declared in driver.h
00008  */
00009 
00010 #include "copyright.h"
00011 
00012 #include <sys/types.h>
00013 #include <sys/wait.h> /* XXX platform specific */
00014 
00015 #include "platform.h"
00016 #include "standard.h"
00017 #include "driver.h"
00018 
00019 #ifndef DEVPATH
00020 #define DEVPATH             getenv("PATH")       /* device search path */
00021 #endif
00022 
00023 FILE   *devin, *devout;
00024 int    devchild;
00025 
00026 static struct driver * final_connect(void);
00027 static void mygets(char     *s, FILE      *fp);
00028 static void myputs(char     *s, FILE      *fp);
00029 static void reply_error(char       *routine);
00030 static void getstate(void);
00031 
00032 static dr_closef_t comm_close;
00033 static dr_clearf_t comm_clear;
00034 static dr_paintrf_t comm_paintr;
00035 static dr_getcurf_t comm_getcur;
00036 static dr_comoutf_t comm_comout;
00037 static dr_cominf_t comm_comin;
00038 static dr_flushf_t comm_flush;
00039 
00040 struct driver comm_driver = {
00041        comm_close, comm_clear, comm_paintr, comm_getcur,
00042        comm_comout, comm_comin, comm_flush
00043 };
00044 
00045 
00046 static struct driver *
00047 final_connect(void)                       /* verify and initialize connection */
00048 {
00049        putw(COM_SENDM, devout);
00050        fflush(devout);
00051        if (getw(devin) != COM_RECVM)
00052               return(NULL);
00053                                           /* get driver parameters */
00054        getstate();
00055                                           /* set error vectors */
00056        erract[COMMAND].pf = comm_comout;
00057        /*                                 doesn't work with raypcalls.c
00058        if (erract[WARNING].pf != NULL)
00059               erract[WARNING].pf = comm_comout;
00060        */
00061        return(&comm_driver);
00062 }
00063 
00064 
00065 extern struct driver *
00066 slave_init(                 /* run rview in slave mode */
00067        char   *dname,
00068        char   *id
00069 )
00070 {
00071        devchild = -1;                            /* we're the slave here */
00072        devout = stdout;                   /* use standard input */
00073        devin = stdin;                            /* and standard output */
00074        return(final_connect());           /* verify initialization */
00075 }
00076 
00077 
00078 extern struct driver *
00079 comm_init(                  /* set up and execute driver */
00080        char   *dname,
00081        char   *id
00082 )
00083 {
00084        char   *dvcname;
00085        int    p1[2], p2[2];
00086        char   pin[16], pout[16];
00087                                           /* find driver program */
00088        if ((dvcname = getpath(dname, DEVPATH, X_OK)) == NULL) {
00089               eputs(dname);
00090               eputs(": not found\n");
00091               return(NULL);
00092        }
00093 #ifdef RHAS_FORK_EXEC
00094                                           /* open communication pipes */
00095        if (pipe(p1) == -1 || pipe(p2) == -1)
00096               goto syserr;
00097        if ((devchild = fork()) == 0) {    /* fork driver process */
00098               close(p1[1]);
00099               close(p2[0]);
00100               sprintf(pin, "%d", p1[0]);
00101               sprintf(pout, "%d", p2[1]);
00102               execl(dvcname, dname, pin, pout, id, NULL);
00103               perror(dvcname);
00104               _exit(127);
00105        }
00106        if (devchild == -1)
00107               goto syserr;
00108        close(p1[0]);
00109        close(p2[1]);
00110        /*
00111         * Close write stream on exec to avoid multiprocessing deadlock.
00112         * No use in read stream without it, so set flag there as well.
00113         */
00114        fcntl(p1[1], F_SETFD, FD_CLOEXEC);
00115        fcntl(p2[0], F_SETFD, FD_CLOEXEC);
00116        if ((devout = fdopen(p1[1], "w")) == NULL)
00117               goto syserr;
00118        if ((devin = fdopen(p2[0], "r")) == NULL)
00119               goto syserr;
00120        return(final_connect());           /* verify initialization */
00121 syserr:
00122        perror(dname);
00123        return(NULL);
00124 
00125 #else  /* ! RHAS_FORK_EXEC */
00126 
00127        eputs(dname);
00128        eputs(": no fork/exec\n");
00129        return(NULL);
00130 
00131 #endif /* ! RHAS_FORK_EXEC */
00132 }
00133 
00134 
00135 static void
00136 comm_close(void)                   /* done with driver */
00137 {
00138        int    pid;
00139 
00140        erract[COMMAND].pf = NULL;         /* reset error vectors */
00141        if (erract[WARNING].pf != NULL)
00142               erract[WARNING].pf = wputs;
00143        fclose(devout);
00144        fclose(devin);
00145        if (devchild < 0)
00146               return;
00147        while ((pid = wait(0)) != -1 && pid != devchild)
00148               ;
00149 }
00150 
00151 
00152 static void
00153 comm_clear(                        /* clear screen */
00154        int    xres,
00155        int    yres
00156 )
00157 {
00158        putc(COM_CLEAR, devout);
00159        putw(xres, devout);
00160        putw(yres, devout);
00161        fflush(devout);
00162 }
00163 
00164 
00165 static void
00166 comm_paintr(  /* paint a rectangle */
00167        COLOR  col,
00168        int    xmin,
00169        int    ymin,
00170        int    xmax,
00171        int    ymax
00172 )
00173 {
00174        putc(COM_PAINTR, devout);
00175        fwrite((char *)col, sizeof(COLOR), 1, devout);
00176        putw(xmin, devout);
00177        putw(ymin, devout);
00178        putw(xmax, devout);
00179        putw(ymax, devout);
00180 }
00181 
00182 
00183 static void
00184 comm_flush(void)                          /* flush output to driver */
00185 {
00186        putc(COM_FLUSH, devout);
00187        fflush(devout);
00188        if (getc(devin) != COM_FLUSH)
00189               reply_error("flush");
00190        getstate();
00191 }
00192 
00193 
00194 static int
00195 comm_getcur(                /* get and return cursor position */
00196        int    *xp,
00197        int    *yp
00198 )
00199 {
00200        int    c;
00201 
00202        putc(COM_GETCUR, devout);
00203        fflush(devout);
00204        if (getc(devin) != COM_GETCUR)
00205               reply_error("getcur");
00206        c = getc(devin);
00207        *xp = getw(devin);
00208        *yp = getw(devin);
00209        return(c);
00210 }
00211 
00212 
00213 static void
00214 comm_comout(                /* print string to command line */
00215        char   *str
00216 )
00217 {
00218        putc(COM_COMOUT, devout);
00219        myputs(str, devout);
00220        if (str[strlen(str)-1] == '\n')
00221               fflush(devout);
00222 }
00223 
00224 
00225 static void
00226 comm_comin(                 /* read string from command line */
00227        char   *buf,
00228        char   *prompt
00229 )
00230 {
00231        putc(COM_COMIN, devout);
00232        if (prompt == NULL)
00233               putc(0, devout);
00234        else {
00235               putc(1, devout);
00236               myputs(prompt, devout);
00237        }
00238        fflush(devout);
00239        if (getc(devin) != COM_COMIN)
00240               reply_error("comin");
00241        mygets(buf, devin);
00242        getstate();
00243 }
00244 
00245 
00246 static void
00247 mygets(                            /* get string from file (with nul) */
00248        register char *s,
00249        register FILE *fp
00250 )
00251 {
00252        register int  c;
00253 
00254        while ((c = getc(fp)) != EOF)
00255               if ((*s++ = c) == '\0')
00256                      return;
00257        *s = '\0';
00258 }
00259 
00260 
00261 static void
00262 myputs(                            /* put string to file (with nul) */
00263        register char *s,
00264        register FILE *fp
00265 )
00266 {
00267        do
00268               putc(*s, fp);
00269        while (*s++);
00270 }
00271 
00272 
00273 static void
00274 reply_error(                /* what should we do here? */
00275        char   *routine
00276 )
00277 {
00278        eputs(routine);
00279        eputs(": driver reply error\n");
00280        quit(1);
00281 }
00282 
00283 
00284 static void
00285 getstate(void)                            /* get driver state variables */
00286 {
00287        fread((char *)&comm_driver.pixaspect,
00288                      sizeof(comm_driver.pixaspect), 1, devin);
00289        comm_driver.xsiz = getw(devin);
00290        comm_driver.ysiz = getw(devin);
00291        comm_driver.inpready = getw(devin);
00292 }