177943Sdfr/*- 277943Sdfr * Copyright (c) 1996 377943Sdfr * Keith Bostic. All rights reserved. 477943Sdfr * 577943Sdfr * See the LICENSE file for redistribution information. 677943Sdfr */ 777943Sdfr 877943Sdfr#include "config.h" 977943Sdfr 1077943Sdfr#ifndef lint 1177943Sdfrstatic const char sccsid[] = "@(#)ip_read.c 8.3 (Berkeley) 9/24/96"; 1277943Sdfr#endif /* not lint */ 1377943Sdfr 1477943Sdfr#include <sys/types.h> 1577943Sdfr#include <sys/queue.h> 1677943Sdfr 1777943Sdfr#include <bitstring.h> 1877943Sdfr#include <stdio.h> 1977943Sdfr#include <termios.h> 2077943Sdfr#include <time.h> 2177943Sdfr 2277943Sdfr#include "../common/common.h" 2377943Sdfr#include "../ex/script.h" 2477943Sdfr#include "ip.h" 2577943Sdfr 2677943Sdfrextern GS *__global_list; 2777943Sdfr 2877943Sdfrtypedef enum { INP_OK=0, INP_EOF, INP_ERR, INP_TIMEOUT } input_t; 2977943Sdfr 3077943Sdfrstatic input_t ip_read __P((SCR *, IP_PRIVATE *, struct timeval *)); 3177943Sdfrstatic int ip_resize __P((SCR *, size_t, size_t)); 3277943Sdfrstatic int ip_trans __P((SCR *, IP_PRIVATE *, EVENT *)); 3377943Sdfr 3477943Sdfr/* 3577943Sdfr * ip_event -- 3677943Sdfr * Return a single event. 3777943Sdfr * 3877943Sdfr * PUBLIC: int ip_event __P((SCR *, EVENT *, u_int32_t, int)); 3977943Sdfr */ 4077943Sdfrint 4177943Sdfrip_event(sp, evp, flags, ms) 4277943Sdfr SCR *sp; 4377943Sdfr EVENT *evp; 4477943Sdfr u_int32_t flags; 4577943Sdfr int ms; 4677943Sdfr{ 4777943Sdfr IP_PRIVATE *ipp; 4877943Sdfr struct timeval t, *tp; 4977943Sdfr 5077943Sdfr if (LF_ISSET(EC_INTERRUPT)) { /* XXX */ 5177943Sdfr evp->e_event = E_TIMEOUT; 5277943Sdfr return (0); 5377943Sdfr } 5477943Sdfr 5577943Sdfr ipp = sp == NULL ? GIPP(__global_list) : IPP(sp); 5677943Sdfr 5777943Sdfr /* Discard the last command. */ 5877943Sdfr if (ipp->iskip != 0) { 5977943Sdfr ipp->iblen -= ipp->iskip; 6077943Sdfr memmove(ipp->ibuf, ipp->ibuf + ipp->iskip, ipp->iblen); 6177943Sdfr ipp->iskip = 0; 6277943Sdfr } 6377943Sdfr 6477943Sdfr /* Set timer. */ 65154491Smarcel if (ms == 0) 66154491Smarcel tp = NULL; 67154491Smarcel else { 68154491Smarcel t.tv_sec = ms / 1000; 69154491Smarcel t.tv_usec = (ms % 1000) * 1000; 70154491Smarcel tp = &t; 7177943Sdfr } 7277943Sdfr 7377943Sdfr /* Read input events. */ 7477943Sdfr for (;;) { 7577943Sdfr switch (ip_read(sp, ipp, tp)) { 7677943Sdfr case INP_OK: 7777943Sdfr if (!ip_trans(sp, ipp, evp)) 7877943Sdfr continue; 7977943Sdfr break; 8077943Sdfr case INP_EOF: 8195190Smarcel evp->e_event = E_EOF; 8277943Sdfr break; 8377943Sdfr case INP_ERR: 8477943Sdfr evp->e_event = E_ERR; 8577943Sdfr break; 8677943Sdfr case INP_TIMEOUT: 8777943Sdfr evp->e_event = E_TIMEOUT; 8877943Sdfr break; 8977943Sdfr default: 9077943Sdfr abort(); 9177943Sdfr } 9277943Sdfr break; 9377943Sdfr } 9477943Sdfr return (0); 9577943Sdfr} 9677943Sdfr 9777943Sdfr/* 9877943Sdfr * ip_read -- 9977943Sdfr * Read characters from the input. 100132437Smarcel */ 101132437Smarcelstatic input_t 102132437Smarcelip_read(sp, ipp, tp) 10377943Sdfr SCR *sp; 10477943Sdfr IP_PRIVATE *ipp; 10577943Sdfr struct timeval *tp; 10677943Sdfr{ 107132437Smarcel struct timeval poll; 108132437Smarcel GS *gp; 109132437Smarcel SCR *tsp; 110132437Smarcel fd_set rdfd; 11177943Sdfr input_t rval; 11277943Sdfr size_t blen; 11395190Smarcel int maxfd, nr; 11495190Smarcel char *bp; 11595190Smarcel 11695190Smarcel gp = sp == NULL ? __global_list : sp->gp; 11795190Smarcel bp = ipp->ibuf + ipp->iblen; 11895190Smarcel blen = sizeof(ipp->ibuf) - ipp->iblen; 11995190Smarcel 12095190Smarcel /* 12195190Smarcel * 1: A read with an associated timeout, e.g., trying to complete 12295190Smarcel * a map sequence. If input exists, we fall into #2. 12395190Smarcel */ 12495190Smarcel FD_ZERO(&rdfd); 12595190Smarcel poll.tv_sec = 0; 12695190Smarcel poll.tv_usec = 0; 12795190Smarcel if (tp != NULL) { 12895190Smarcel FD_SET(ipp->i_fd, &rdfd); 12995190Smarcel switch (select(ipp->i_fd + 1, 13095190Smarcel &rdfd, NULL, NULL, tp == NULL ? &poll : tp)) { 13195190Smarcel case 0: 132154491Smarcel return (INP_TIMEOUT); 13395190Smarcel case -1: 13495190Smarcel goto err; 13595190Smarcel default: 13677943Sdfr break; 13795190Smarcel } 13895190Smarcel } 13977943Sdfr 14095190Smarcel /* 14177943Sdfr * 2: Wait for input. 14295190Smarcel * 14395190Smarcel * Select on the command input and scripting window file descriptors. 14495190Smarcel * It's ugly that we wait on scripting file descriptors here, but it's 14595190Smarcel * the only way to keep from locking out scripting windows. 14695190Smarcel */ 14795190Smarcel if (sp != NULL && F_ISSET(gp, G_SCRWIN)) { 14895190Smarcelloop: FD_ZERO(&rdfd); 14995190Smarcel FD_SET(ipp->i_fd, &rdfd); 15085436Sdfr maxfd = ipp->i_fd; 15195190Smarcel for (tsp = gp->dq.cqh_first; 15295190Smarcel tsp != (void *)&gp->dq; tsp = tsp->q.cqe_next) 153154491Smarcel if (F_ISSET(sp, SC_SCRIPT)) { 15477943Sdfr FD_SET(sp->script->sh_master, &rdfd); 15595190Smarcel if (sp->script->sh_master > maxfd) 15695190Smarcel maxfd = sp->script->sh_master; 15777943Sdfr } 15877943Sdfr switch (select(maxfd + 1, &rdfd, NULL, NULL, NULL)) { 15977943Sdfr case 0: 16077943Sdfr abort(); 16177943Sdfr case -1: 16277943Sdfr goto err; 16395190Smarcel default: 16495190Smarcel break; 16595190Smarcel } 16695190Smarcel if (!FD_ISSET(ipp->i_fd, &rdfd)) { 16795190Smarcel if (sscr_input(sp)) 16895190Smarcel return (INP_ERR); 16995190Smarcel goto loop; 17095190Smarcel } 17195190Smarcel } 17295190Smarcel 17395190Smarcel /* 17495190Smarcel * 3: Read the input. 17595190Smarcel */ 17695190Smarcel switch (nr = read(ipp->i_fd, bp, blen)) { 17795190Smarcel case 0: /* EOF. */ 17895190Smarcel rval = INP_EOF; 17995190Smarcel break; 18095190Smarcel case -1: /* Error or interrupt. */ 18195190Smarcelerr: rval = INP_ERR; 18295190Smarcel msgq(sp, M_SYSERR, "input"); 18395190Smarcel break; 18495190Smarcel default: /* Input characters. */ 18595190Smarcel ipp->iblen += nr; 18695190Smarcel rval = INP_OK; 18795190Smarcel break; 18895190Smarcel } 18995190Smarcel return (rval); 19095190Smarcel} 19195190Smarcel 19295190Smarcel/* 19395190Smarcel * ip_trans -- 19495190Smarcel * Translate messages into events. 19595190Smarcel */ 19695190Smarcelstatic int 19795190Smarcelip_trans(sp, ipp, evp) 19895190Smarcel SCR *sp; 19995190Smarcel IP_PRIVATE *ipp; 20095190Smarcel EVENT *evp; 20195190Smarcel{ 20295190Smarcel u_int32_t val1, val2; 20395190Smarcel 20495190Smarcel switch (ipp->ibuf[0]) { 20577943Sdfr case IPO_EOF: 20695190Smarcel evp->e_event = E_EOF; 20777943Sdfr ipp->iskip = IPO_CODE_LEN; 20877943Sdfr return (1); 20995190Smarcel case IPO_ERR: 21077943Sdfr evp->e_event = E_ERR; 21177943Sdfr ipp->iskip = IPO_CODE_LEN; 212154491Smarcel return (1); 21395190Smarcel case IPO_INTERRUPT: 21477943Sdfr evp->e_event = E_INTERRUPT; 215154491Smarcel ipp->iskip = IPO_CODE_LEN; 216132437Smarcel return (1); 217132437Smarcel case IPO_QUIT: 218154491Smarcel evp->e_event = E_QUIT; 21977943Sdfr ipp->iskip = IPO_CODE_LEN; 22077943Sdfr return (1); 22195190Smarcel case IPO_RESIZE: 22277943Sdfr if (ipp->iblen < IPO_CODE_LEN + IPO_INT_LEN * 2) 22395190Smarcel return (0); 22477943Sdfr evp->e_event = E_WRESIZE; 22595190Smarcel memcpy(&val1, ipp->ibuf + IPO_CODE_LEN, IPO_INT_LEN); 22677943Sdfr val1 = ntohl(val1); 22795190Smarcel memcpy(&val2, 22877943Sdfr ipp->ibuf + IPO_CODE_LEN + IPO_INT_LEN, IPO_INT_LEN); 22995190Smarcel val2 = ntohl(val2); 23085436Sdfr ip_resize(sp, val1, val2); 23195190Smarcel ipp->iskip = IPO_CODE_LEN + IPO_INT_LEN * 2; 23295190Smarcel return (1); 23395190Smarcel case IPO_SIGHUP: 23495190Smarcel evp->e_event = E_SIGHUP; 235154491Smarcel ipp->iskip = IPO_CODE_LEN; 23685436Sdfr return (1); 23785436Sdfr case IPO_SIGTERM: 238154491Smarcel evp->e_event = E_SIGTERM; 23995190Smarcel ipp->iskip = IPO_CODE_LEN; 24077943Sdfr return (1); 24195190Smarcel case IPO_STRING: 24295190Smarcel evp->e_event = E_STRING; 24377943Sdfrstring: if (ipp->iblen < IPO_CODE_LEN + IPO_INT_LEN) 24495190Smarcel return (0); 24595190Smarcel memcpy(&val1, ipp->ibuf + IPO_CODE_LEN, IPO_INT_LEN); 24677943Sdfr val1 = ntohl(val1); 24795190Smarcel if (ipp->iblen < IPO_CODE_LEN + IPO_INT_LEN + val1) 24877943Sdfr return (0); 24995190Smarcel ipp->iskip = IPO_CODE_LEN + IPO_INT_LEN + val1; 25095190Smarcel evp->e_csp = ipp->ibuf + IPO_CODE_LEN + IPO_INT_LEN; 25177943Sdfr evp->e_len = val1; 252132437Smarcel return (1); 253132437Smarcel case IPO_WRITE: 254132437Smarcel evp->e_event = E_WRITE; 255132437Smarcel ipp->iskip = IPO_CODE_LEN; 256132437Smarcel return (1); 257132437Smarcel default: 258132437Smarcel /* 25995190Smarcel * XXX: Protocol is out of sync? 26095190Smarcel */ 26195190Smarcel abort(); 26277943Sdfr } 26395190Smarcel /* NOTREACHED */ 26495190Smarcel} 26595190Smarcel 26695190Smarcel/* 26795190Smarcel * ip_resize -- 26895190Smarcel * Reset the options for a resize event. 26977943Sdfr */ 27095190Smarcelstatic int 27195190Smarcelip_resize(sp, lines, columns) 27295190Smarcel SCR *sp; 27395190Smarcel size_t lines, columns; 27495190Smarcel{ 27585436Sdfr GS *gp; 27695190Smarcel ARGS *argv[2], a, b; 27795190Smarcel char b1[1024]; 27895190Smarcel 27995190Smarcel /* 28085436Sdfr * XXX 28195190Smarcel * The IP screen has to know the lines and columns before anything 28285436Sdfr * else happens. So, we may not have a valid SCR pointer, and we 28395190Smarcel * have to deal with that. 28495190Smarcel */ 28595190Smarcel if (sp == NULL) { 28695190Smarcel gp = __global_list; 28795190Smarcel OG_VAL(gp, GO_LINES) = OG_D_VAL(gp, GO_LINES) = lines; 28877943Sdfr OG_VAL(gp, GO_COLUMNS) = OG_D_VAL(gp, GO_COLUMNS) = columns; 28995190Smarcel return (0); 29077943Sdfr } 29195190Smarcel 29277943Sdfr a.bp = b1; 29395190Smarcel b.bp = NULL; 29477943Sdfr a.len = b.len = 0; 29595190Smarcel argv[0] = &a; 29695190Smarcel argv[1] = &b; 29777943Sdfr 29877943Sdfr (void)snprintf(b1, sizeof(b1), "lines=%lu", (u_long)lines); 29977943Sdfr a.len = strlen(b1); 30077943Sdfr if (opts_set(sp, argv, NULL)) 30177943Sdfr return (1); 30277943Sdfr (void)snprintf(b1, sizeof(b1), "columns=%lu", (u_long)columns); 30377943Sdfr a.len = strlen(b1); 30477943Sdfr if (opts_set(sp, argv, NULL)) 30577943Sdfr return (1); 30677943Sdfr return (0); 307107720Smarcel} 30877943Sdfr