| 1 | greg | 1.1 | #ifndef lint | 
| 2 | greg | 2.8 | static const char       RCSid[] = "$Id: devcomm.c,v 2.7 2003/02/25 02:47:22 greg Exp $"; | 
| 3 | greg | 1.1 | #endif | 
| 4 |  |  | /* | 
| 5 |  |  | *  devcomm.c - communication routines for separate drivers. | 
| 6 |  |  | * | 
| 7 | greg | 2.6 | *  External symbols declared in driver.h | 
| 8 |  |  | */ | 
| 9 |  |  |  | 
| 10 | greg | 2.7 | #include "copyright.h" | 
| 11 | greg | 1.1 |  | 
| 12 | greg | 1.10 | #include "standard.h" | 
| 13 | greg | 1.1 |  | 
| 14 |  |  | #include "color.h" | 
| 15 |  |  |  | 
| 16 |  |  | #include "driver.h" | 
| 17 |  |  |  | 
| 18 | greg | 2.2 | #include "vfork.h" | 
| 19 |  |  |  | 
| 20 | greg | 1.1 | #ifndef DEVPATH | 
| 21 |  |  | #define DEVPATH         getenv("PATH")  /* device search path */ | 
| 22 |  |  | #endif | 
| 23 |  |  |  | 
| 24 | greg | 2.6 | static int      comm_getcur(); | 
| 25 |  |  | static void     comm_close(), comm_clear(), comm_paintr(), | 
| 26 |  |  | comm_comin(), comm_comout(), comm_flush(); | 
| 27 | greg | 1.1 |  | 
| 28 | greg | 1.12 | struct driver   comm_driver = { | 
| 29 | greg | 1.1 | comm_close, comm_clear, comm_paintr, comm_getcur, | 
| 30 | greg | 1.12 | comm_comout, comm_comin, comm_flush | 
| 31 | greg | 1.1 | }; | 
| 32 |  |  |  | 
| 33 | greg | 2.6 | static void     mygets(), myputs(), reply_error(), getstate(); | 
| 34 | greg | 2.4 |  | 
| 35 | greg | 1.1 | FILE    *devin, *devout; | 
| 36 |  |  |  | 
| 37 |  |  | int     devchild; | 
| 38 |  |  |  | 
| 39 |  |  |  | 
| 40 | greg | 2.3 | static struct driver * | 
| 41 |  |  | final_connect()                         /* verify and initialize connection */ | 
| 42 |  |  | { | 
| 43 |  |  | putw(COM_SENDM, devout); | 
| 44 |  |  | fflush(devout); | 
| 45 |  |  | if (getw(devin) != COM_RECVM) | 
| 46 |  |  | return(NULL); | 
| 47 |  |  | /* get driver parameters */ | 
| 48 |  |  | getstate(); | 
| 49 |  |  | /* set error vectors */ | 
| 50 | gregl | 2.5 | erract[COMMAND].pf = comm_comout; | 
| 51 |  |  | if (erract[WARNING].pf != NULL) | 
| 52 |  |  | erract[WARNING].pf = comm_comout; | 
| 53 | greg | 2.3 | return(&comm_driver); | 
| 54 |  |  | } | 
| 55 |  |  |  | 
| 56 |  |  |  | 
| 57 | greg | 1.1 | struct driver * | 
| 58 | greg | 2.3 | slave_init(dname, id)                   /* run rview in slave mode */ | 
| 59 |  |  | char    *dname, *id; | 
| 60 |  |  | { | 
| 61 |  |  | devchild = -1;                          /* we're the slave here */ | 
| 62 |  |  | devout = stdout;                        /* use standard input */ | 
| 63 |  |  | devin = stdin;                          /* and standard output */ | 
| 64 |  |  | return(final_connect());                /* verify initialization */ | 
| 65 |  |  | } | 
| 66 |  |  |  | 
| 67 |  |  |  | 
| 68 |  |  | struct driver * | 
| 69 | greg | 1.7 | comm_init(dname, id)                    /* set up and execute driver */ | 
| 70 |  |  | char    *dname, *id; | 
| 71 | greg | 1.1 | { | 
| 72 | greg | 2.6 | char    *dvcname; | 
| 73 | greg | 1.1 | int     p1[2], p2[2]; | 
| 74 | greg | 1.7 | char    pin[16], pout[16]; | 
| 75 |  |  | /* find driver program */ | 
| 76 | greg | 2.6 | if ((dvcname = getpath(dname, DEVPATH, X_OK)) == NULL) { | 
| 77 | gregl | 2.5 | eputs(dname); | 
| 78 |  |  | eputs(": not found\n"); | 
| 79 | greg | 1.1 | return(NULL); | 
| 80 |  |  | } | 
| 81 | greg | 2.8 | #ifdef RHAS_FORK_EXEC | 
| 82 | greg | 1.7 | /* open communication pipes */ | 
| 83 | greg | 1.1 | if (pipe(p1) == -1 || pipe(p2) == -1) | 
| 84 |  |  | goto syserr; | 
| 85 | greg | 1.7 | if ((devchild = vfork()) == 0) {        /* fork driver process */ | 
| 86 | greg | 1.1 | close(p1[1]); | 
| 87 |  |  | close(p2[0]); | 
| 88 | greg | 1.7 | sprintf(pin, "%d", p1[0]); | 
| 89 |  |  | sprintf(pout, "%d", p2[1]); | 
| 90 | greg | 2.6 | execl(dvcname, dname, pin, pout, id, 0); | 
| 91 |  |  | perror(dvcname); | 
| 92 | greg | 1.1 | _exit(127); | 
| 93 |  |  | } | 
| 94 |  |  | if (devchild == -1) | 
| 95 |  |  | goto syserr; | 
| 96 |  |  | close(p1[0]); | 
| 97 |  |  | close(p2[1]); | 
| 98 |  |  | if ((devout = fdopen(p1[1], "w")) == NULL) | 
| 99 |  |  | goto syserr; | 
| 100 |  |  | if ((devin = fdopen(p2[0], "r")) == NULL) | 
| 101 |  |  | goto syserr; | 
| 102 | greg | 2.3 | return(final_connect());                /* verify initialization */ | 
| 103 | greg | 1.1 | syserr: | 
| 104 | greg | 1.7 | perror(dname); | 
| 105 | greg | 1.1 | return(NULL); | 
| 106 | greg | 2.8 |  | 
| 107 |  |  | #else   /* ! RHAS_FORK_EXEC */ | 
| 108 |  |  |  | 
| 109 |  |  | eputs(dname); | 
| 110 |  |  | eputs(": no fork/exec\n"); | 
| 111 |  |  | return(NULL); | 
| 112 |  |  |  | 
| 113 |  |  | #endif  /* ! RHAS_FORK_EXEC */ | 
| 114 | greg | 1.1 | } | 
| 115 |  |  |  | 
| 116 |  |  |  | 
| 117 | greg | 2.6 | static void | 
| 118 | greg | 1.1 | comm_close()                    /* done with driver */ | 
| 119 |  |  | { | 
| 120 |  |  | int     pid; | 
| 121 |  |  |  | 
| 122 | gregl | 2.5 | erract[COMMAND].pf = NULL;              /* reset error vectors */ | 
| 123 |  |  | if (erract[WARNING].pf != NULL) | 
| 124 |  |  | erract[WARNING].pf = wputs; | 
| 125 | greg | 1.1 | fclose(devout); | 
| 126 |  |  | fclose(devin); | 
| 127 | greg | 2.3 | if (devchild < 0) | 
| 128 |  |  | return; | 
| 129 | greg | 1.1 | while ((pid = wait(0)) != -1 && pid != devchild) | 
| 130 |  |  | ; | 
| 131 |  |  | } | 
| 132 |  |  |  | 
| 133 |  |  |  | 
| 134 | greg | 2.6 | static void | 
| 135 | greg | 1.1 | comm_clear(xres, yres)                          /* clear screen */ | 
| 136 |  |  | int     xres, yres; | 
| 137 |  |  | { | 
| 138 |  |  | putc(COM_CLEAR, devout); | 
| 139 | greg | 1.8 | putw(xres, devout); | 
| 140 |  |  | putw(yres, devout); | 
| 141 | greg | 1.1 | fflush(devout); | 
| 142 |  |  | } | 
| 143 |  |  |  | 
| 144 |  |  |  | 
| 145 | greg | 2.6 | static void | 
| 146 | greg | 1.1 | comm_paintr(col, xmin, ymin, xmax, ymax)        /* paint a rectangle */ | 
| 147 |  |  | COLOR   col; | 
| 148 |  |  | int     xmin, ymin, xmax, ymax; | 
| 149 |  |  | { | 
| 150 |  |  | putc(COM_PAINTR, devout); | 
| 151 | greg | 1.10 | fwrite((char *)col, sizeof(COLOR), 1, devout); | 
| 152 | greg | 1.8 | putw(xmin, devout); | 
| 153 |  |  | putw(ymin, devout); | 
| 154 |  |  | putw(xmax, devout); | 
| 155 |  |  | putw(ymax, devout); | 
| 156 | greg | 1.12 | } | 
| 157 |  |  |  | 
| 158 |  |  |  | 
| 159 | greg | 2.6 | static void | 
| 160 | greg | 1.12 | comm_flush()                            /* flush output to driver */ | 
| 161 |  |  | { | 
| 162 |  |  | putc(COM_FLUSH, devout); | 
| 163 |  |  | fflush(devout); | 
| 164 | greg | 1.13 | if (getc(devin) != COM_FLUSH) | 
| 165 |  |  | reply_error("flush"); | 
| 166 | greg | 1.17 | getstate(); | 
| 167 | greg | 1.1 | } | 
| 168 |  |  |  | 
| 169 |  |  |  | 
| 170 |  |  | static int | 
| 171 |  |  | comm_getcur(xp, yp)                     /* get and return cursor position */ | 
| 172 |  |  | int     *xp, *yp; | 
| 173 |  |  | { | 
| 174 |  |  | int     c; | 
| 175 |  |  |  | 
| 176 |  |  | putc(COM_GETCUR, devout); | 
| 177 |  |  | fflush(devout); | 
| 178 |  |  | if (getc(devin) != COM_GETCUR) | 
| 179 |  |  | reply_error("getcur"); | 
| 180 |  |  | c = getc(devin); | 
| 181 | greg | 1.8 | *xp = getw(devin); | 
| 182 |  |  | *yp = getw(devin); | 
| 183 | greg | 1.1 | return(c); | 
| 184 |  |  | } | 
| 185 |  |  |  | 
| 186 |  |  |  | 
| 187 | greg | 2.6 | static void | 
| 188 | greg | 1.1 | comm_comout(str)                        /* print string to command line */ | 
| 189 |  |  | char    *str; | 
| 190 |  |  | { | 
| 191 |  |  | putc(COM_COMOUT, devout); | 
| 192 |  |  | myputs(str, devout); | 
| 193 | greg | 1.18 | if (str[strlen(str)-1] == '\n') | 
| 194 |  |  | fflush(devout); | 
| 195 | greg | 1.1 | } | 
| 196 |  |  |  | 
| 197 |  |  |  | 
| 198 | greg | 2.6 | static void | 
| 199 | greg | 1.11 | comm_comin(buf, prompt)                 /* read string from command line */ | 
| 200 | greg | 1.1 | char    *buf; | 
| 201 | greg | 1.11 | char    *prompt; | 
| 202 | greg | 1.1 | { | 
| 203 |  |  | putc(COM_COMIN, devout); | 
| 204 | greg | 1.11 | if (prompt == NULL) | 
| 205 |  |  | putc(0, devout); | 
| 206 |  |  | else { | 
| 207 |  |  | putc(1, devout); | 
| 208 |  |  | myputs(prompt, devout); | 
| 209 |  |  | } | 
| 210 | greg | 1.1 | fflush(devout); | 
| 211 |  |  | if (getc(devin) != COM_COMIN) | 
| 212 |  |  | reply_error("comin"); | 
| 213 |  |  | mygets(buf, devin); | 
| 214 | greg | 1.17 | getstate(); | 
| 215 | greg | 1.1 | } | 
| 216 |  |  |  | 
| 217 |  |  |  | 
| 218 | greg | 2.6 | static void | 
| 219 | greg | 1.1 | mygets(s, fp)                           /* get string from file (with nul) */ | 
| 220 |  |  | register char   *s; | 
| 221 |  |  | register FILE   *fp; | 
| 222 |  |  | { | 
| 223 |  |  | register int    c; | 
| 224 |  |  |  | 
| 225 |  |  | while ((c = getc(fp)) != EOF) | 
| 226 |  |  | if ((*s++ = c) == '\0') | 
| 227 |  |  | return; | 
| 228 |  |  | *s = '\0'; | 
| 229 |  |  | } | 
| 230 |  |  |  | 
| 231 |  |  |  | 
| 232 | greg | 2.6 | static void | 
| 233 | greg | 1.1 | myputs(s, fp)                           /* put string to file (with nul) */ | 
| 234 |  |  | register char   *s; | 
| 235 |  |  | register FILE   *fp; | 
| 236 |  |  | { | 
| 237 |  |  | do | 
| 238 |  |  | putc(*s, fp); | 
| 239 |  |  | while (*s++); | 
| 240 |  |  | } | 
| 241 |  |  |  | 
| 242 |  |  |  | 
| 243 | greg | 2.6 | static void | 
| 244 | greg | 1.1 | reply_error(routine)                    /* what should we do here? */ | 
| 245 |  |  | char    *routine; | 
| 246 |  |  | { | 
| 247 | gregl | 2.5 | eputs(routine); | 
| 248 |  |  | eputs(": driver reply error\n"); | 
| 249 | greg | 1.1 | quit(1); | 
| 250 | greg | 1.17 | } | 
| 251 |  |  |  | 
| 252 |  |  |  | 
| 253 | greg | 2.6 | static void | 
| 254 | greg | 1.17 | getstate()                              /* get driver state variables */ | 
| 255 |  |  | { | 
| 256 |  |  | fread((char *)&comm_driver.pixaspect, | 
| 257 |  |  | sizeof(comm_driver.pixaspect), 1, devin); | 
| 258 |  |  | comm_driver.xsiz = getw(devin); | 
| 259 |  |  | comm_driver.ysiz = getw(devin); | 
| 260 |  |  | comm_driver.inpready = getw(devin); | 
| 261 | greg | 1.1 | } |