|
|
1.1 ! root 1: /* IBM has disclaimed copyright on this module. */ ! 2: ! 3: /***************************************************************/ ! 4: /* */ ! 5: /* Function: hftctl */ ! 6: /* */ ! 7: /* Syntax: */ ! 8: /* #include <sys/ioctl.h> */ ! 9: /* #include <sys/hft.h> */ ! 10: /* */ ! 11: /* int hftctl(fildes, request, arg ) */ ! 12: /* int fildes, request; */ ! 13: /* char *arg; */ ! 14: /* */ ! 15: /* Description: */ ! 16: /* */ ! 17: /* Does the following: */ ! 18: /* 1. determines if fildes is pty */ ! 19: /* does normal ioctl it is not */ ! 20: /* 2. places fildes into raw mode */ ! 21: /* 3. converts ioctl arguments to datastream */ ! 22: /* 4. waits for 2 secs for acknowledgement before */ ! 23: /* timimg out. */ ! 24: /* 5. places response in callers buffer ( just like */ ! 25: /* ioctl. */ ! 26: /* 6. returns fildes to its original mode */ ! 27: /* */ ! 28: /* User of this program should review steps 1,4, and 3. */ ! 29: /* hftctl makes no check on the request type. It must be */ ! 30: /* a HFT ioctl that is supported remotely. */ ! 31: /* This program will use the SIGALRM and alarm(2). Any */ ! 32: /* Previous alarms are lost. */ ! 33: /* */ ! 34: /* Users of this program are free to modify it any way */ ! 35: /* they want. */ ! 36: /* */ ! 37: /* Return Value: */ ! 38: /* */ ! 39: /* If ioctl fails, a value of -1 is returned and errno */ ! 40: /* is set to indicate the error. */ ! 41: /* */ ! 42: /***************************************************************/ ! 43: ! 44: ! 45: #include <stdio.h> ! 46: #include <fcntl.h> ! 47: #include <errno.h> ! 48: #include <setjmp.h> ! 49: #include <sys/ioctl.h> ! 50: #include <sys/signal.h> ! 51: #include <sys/devinfo.h> ! 52: #include <termios.h> ! 53: #include <termio.h> ! 54: #include <sys/hft.h> ! 55: #include <sys/uio.h> ! 56: #include <sys/tty.h> ! 57: /* #include <sys/pty.h> */ ! 58: #define REMOTE 0x01 ! 59: ! 60: #undef ioctl ! 61: static char SCCSid[] = "com/gnuemacs/src,3.1,9021-90/05/03-5/3/90"; ! 62: ! 63: /*************** LOCAL DEFINES **********************************/ ! 64: ! 65: typedef int (*FUNC)(); /* pointer to a function */ ! 66: ! 67: #define QDEV ((HFQPDEVCH<<8)|HFQPDEVCL) ! 68: #define QLOC ((HFQLOCCH<<8)|HFQLOCCL) ! 69: #define QPS ((HFQPRESCH<<8)|HFQPRESCL) ! 70: ! 71: #ifndef TCGETS ! 72: #define TCGETS TCGETA ! 73: #endif ! 74: #ifndef TCSETS ! 75: #define TCSETS TCSETA ! 76: #endif ! 77: ! 78: /*************** EXTERNAL / GLOBAL DATA AREA ********************/ ! 79: ! 80: static int hfqry(); ! 81: static int hfskbd(); ! 82: char *malloc(); ! 83: ! 84: extern int errno; ! 85: static jmp_buf hftenv; ! 86: static int is_ack_vtd; ! 87: static FUNC sav_alrm; ! 88: static struct hfctlreq req = ! 89: { 0x1b,'[','x',0,0,0,21,HFCTLREQCH,HFCTLREQCL}; ! 90: static struct hfctlack ACK = ! 91: { 0x1b,'[','x',0,0,0,21,HFCTLACKCH,HFCTLACKCL}; ! 92: ! 93: /* FUNC signal(); */ ! 94: ! 95: /*************** LOCAL MACROS ***********************************/ ! 96: ! 97: #define HFTYPE(p) ((p->hf_typehi<<8)|(p->hf_typelo)) ! 98: ! 99: #define BYTE4(p) ((p)[0]<<24 | (p)[1]<<16 | (p)[2]<<8 | (p)[3]) ! 100: ! 101: /* read a buffer */ ! 102: #define RD_BUF(f,p,l) \ ! 103: while ((l)) \ ! 104: if ((j = read((f),(p),(l))) < 0) \ ! 105: if (errno != EINTR) return (-1); \ ! 106: else continue; \ ! 107: else { (l) -= j; (p) += j; } ! 108: ! 109: /*************** function prototypes ***************************/ ! 110: #ifdef __STDC__ ! 111: static GT_ACK (int fd, int req, char *buf); ! 112: static WR_REQ (int fd, int request, int cmdlen, char *cmd, int resplen); ! 113: static hft_alrm(int sig); ! 114: #else ! 115: static GT_ACK (); ! 116: static WR_REQ (); ! 117: static hft_alrm (); ! 118: #endif ! 119: ! 120: /*************** HFTCTL FUNCTION *******************************/ ! 121: ! 122: hftctl (fd, request, arg) ! 123: int fd; ! 124: int request; ! 125: union { ! 126: struct hfintro *intro; ! 127: struct hfquery *query; ! 128: char *c; ! 129: } arg; ! 130: { ! 131: ! 132: int i; ! 133: int fd_flag; /* fcntl flags */ ! 134: register union { ! 135: struct hfintro *cmd; /* p.cmd - intro des. */ ! 136: struct hfqphdevc *ph; /* p.ph - physical dev.*/ ! 137: char *c; /* p.c - char ptr */ ! 138: } p; /* general pointer */ ! 139: int pty_new; /* pty modes */ ! 140: int pty_old; ! 141: int retcode; ! 142: struct termios term_new; /* terminal attributes */ ! 143: struct termios term_old; ! 144: struct devinfo devInfo; /* defined in sys/devinfo.h */ ! 145: ! 146: ! 147: if (ioctl (fd, IOCINFO, &devInfo) == -1) return(-1); ! 148: ! 149: if (devInfo.devtype != DD_PSEU) /* is it a pty? */ ! 150: return (ioctl(fd, request, arg)); /* no, do IOCTL */ ! 151: ! 152: /******* START PTY **************/ ! 153: /** Pty found, possible HFT */ ! 154: /** set new file des as raw */ ! 155: /** as you can. */ ! 156: /********************************/ ! 157: ! 158: /* Get current state of file */ ! 159: /* descriptor & save */ ! 160: if ((fd_flag = fcntl (fd, F_GETFL, 0)) == -1) return (-1); ! 161: if (ioctl (fd, TCGETS, &term_old) == -1) return (-1); ! 162: /* set terminal attr to raw */ ! 163: /* and to delay on read */ ! 164: pty_new = pty_old | REMOTE; ! 165: memcpy (&term_new, &term_old, sizeof (term_new)); ! 166: term_new.c_iflag = 0; ! 167: term_new.c_oflag = 0; ! 168: term_new.c_lflag = 0; ! 169: /* term_new.c_line = 0; */ ! 170: for (i = 1; i <= 5; i++) ! 171: term_new.c_cc[i] = 0; ! 172: term_new.c_cc[0] = -1; ! 173: ioctl (fd, TCSETS, &term_new); ! 174: if (fcntl (fd, F_SETFL, fd_flag & ~O_NDELAY) == -1) ! 175: return(-1); ! 176: /* call spacific function */ ! 177: if (request == HFSKBD) ! 178: retcode = hfskbd (fd, request, arg.c); ! 179: else /* assume HFQUERY */ ! 180: retcode = hfqry (fd, request, arg.c); ! 181: ! 182: fcntl (fd, F_SETFL, fd_flag); /* reset terminal to original */ ! 183: ioctl (fd, TCSETS, &term_old); ! 184: ! 185: ! 186: return (retcode); /* return error */ ! 187: } ! 188: ! 189: /*************** HFSKBD FUNCTION ******************************/ ! 190: static int ! 191: hfskbd (fd, request, arg) ! 192: int fd; ! 193: int request; ! 194: struct hfbuf *arg; ! 195: { ! 196: WR_REQ(fd, request, arg->hf_buflen, arg->hf_bufp,0); ! 197: return (GT_ACK(fd, request, arg->hf_bufp)); ! 198: } ! 199: ! 200: /*************** HFQUERY FUNCTION ******************************/ ! 201: static int ! 202: hfqry (fd, request, arg) ! 203: int fd; ! 204: int request; ! 205: struct hfquery *arg; ! 206: { ! 207: WR_REQ(fd, request, arg->hf_cmdlen, arg->hf_cmd, arg->hf_resplen); ! 208: return (GT_ACK(fd, request, arg->hf_resp)); ! 209: } ! 210: ! 211: ! 212: /*************** GT_ACK FUNCTION ******************************/ ! 213: static int ! 214: GT_ACK (fd, req, buf) ! 215: int fd; ! 216: int req; ! 217: char *buf; ! 218: { ! 219: struct hfctlack ack; ! 220: int i = sizeof (ack); ! 221: int j = 0; ! 222: union { ! 223: char *c; ! 224: struct hfctlack *ack; ! 225: } p; ! 226: ! 227: is_ack_vtd = 0; /* flag no ACT VTD yet */ ! 228: ! 229: if (setjmp (hftenv)) /* set environment in case */ ! 230: { /* of time out */ ! 231: errno = ENODEV; /* if time out, set errno */ ! 232: return (-1); /* flag error */ ! 233: } ! 234: ! 235: alarm(3); /* time out in 3 secs */ ! 236: sav_alrm = (FUNC) signal (SIGALRM, (void(*)())hft_alrm); /* prepare to catch time out */ ! 237: ! 238: p.ack = &ack; ! 239: while (! is_ack_vtd) /* do until valid ACK VTD */ ! 240: { ! 241: RD_BUF(fd, p.c, i); /* read until a ACK VTD is fill*/ ! 242: ! 243: if (! memcmp (&ack, &ACK, sizeof (HFINTROSZ)) /* the ACK intro & */ ! 244: && (ack.hf_request == req)) /* is it the response we want ?*/ ! 245: { /* yes, ACK VTD found */ ! 246: is_ack_vtd = 1; /* quickly, flag it */ ! 247: break; /* get the %$%#@ out of here */ ! 248: } ! 249: ! 250: p.ack = &ack; /* no, then skip 1st */ ! 251: ++p.c; /* char and start over */ ! 252: i = sizeof (ack) - 1; /* one less ESC to cry over */ ! 253: ! 254: while ((*p.c != 0x1b) && i) /* scan for next ESC */ ! 255: { ++p.c; --i; } /* if any */ ! 256: ! 257: (i ? memcpy (&ack, p.c, i) : 0); /* if any left over, then move */ ! 258: p.ack = &ack; /* ESC to front of ack struct */ ! 259: p.c += i; /* skip over whats been read */ ! 260: i = sizeof (ack) - i; /* set whats left to be read */ ! 261: } /***** TRY AGAIN */ ! 262: ! 263: alarm(0); /* ACK VTD received, reset alrm*/ ! 264: signal (SIGALRM, (void(*)())sav_alrm); /* reset signal */ ! 265: ! 266: if (i = ack.hf_arg_len) /* any data following ? */ ! 267: { /* yes, */ ! 268: RD_BUF(fd,buf,i); /* read until it is received */ ! 269: } ! 270: ! 271: if (errno = ack.hf_retcode) /* set errno based on returned */ ! 272: return (-1); /* code, if 0, then no error */ ! 273: else ! 274: return (0); /* if set, then error returned */ ! 275: } ! 276: ! 277: /*************** HFT_ALRM FUNCTION ******************************/ ! 278: static int ! 279: hft_alrm (sig) /* Function hft_alrm - handle */ ! 280: int sig; /* alarm signal */ ! 281: { ! 282: signal (SIGALRM, (void(*)())sav_alrm); /* reset to previous */ ! 283: ! 284: if (is_ack_vtd) /* has ack vtd arrived ? */ ! 285: return(0); /* yes, then continue */ ! 286: else /* no, then return with error */ ! 287: longjmp (hftenv, -1); ! 288: ! 289: } ! 290: ! 291: /*********************************************************************/ ! 292: /*** ***/ ! 293: /*** NOTE: Both the HFCTLREQ and the arg structure should be ***/ ! 294: /*** sent in one io write operation. If terminal ***/ ! 295: /*** emulators are in NODELAY mode then multiple writes ***/ ! 296: /*** may cause bogus information to be read by the emulator ***/ ! 297: /*** depending on the timing. ***/ ! 298: /*** ***/ ! 299: /*********************************************************************/ ! 300: ! 301: static int ! 302: WR_REQ (fd, request, cmdlen, cmd, resplen) ! 303: int fd; ! 304: int request; ! 305: int cmdlen; ! 306: char *cmd; ! 307: int resplen; ! 308: { ! 309: struct { ! 310: char *c; ! 311: struct hfctlreq *req; ! 312: } p; ! 313: int size; ! 314: ! 315: req.hf_request = request; ! 316: req.hf_arg_len = cmdlen; ! 317: req.hf_rsp_len = resplen; ! 318: ! 319: if (cmdlen) /* if arg structure to pass */ ! 320: { ! 321: size = sizeof (struct hfctlreq) + cmdlen; ! 322: if ((p.c = malloc(size)) == NULL) /* malloc one area */ ! 323: return (-1); ! 324: ! 325: memcpy (p.c, &req, sizeof (req)); /* copy CTL REQ struct */ ! 326: memcpy (p.c + sizeof (req), cmd, cmdlen); /* copy arg struct */ ! 327: } ! 328: else ! 329: { ! 330: p.req = &req; /* otherwise use only CTL REQ */ ! 331: size = sizeof (req); ! 332: } ! 333: ! 334: /* write request to terminal */ ! 335: if (write(fd,p.c,size) == -1) return (-1); ! 336: if (p.req != &req) /* free if allocated */ ! 337: free (p.c); ! 338: return (0); ! 339: ! 340: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.