int ReadRequest(ClientPtr client) { OsCommPtr oc; ConnectionInputPtr oci; fsReq *request; int fd, result, gotnow, needed = 0; if (client == NULL) return -1; oc = (OsCommPtr) client->osPrivate; if (oc == NULL) return -1; oci = oc->input; fd = oc->fd; if (oci != NULL && fd < 0) return -1; if (AvailableInput) { if (AvailableInput != oc) { ConnectionInputPtr aci = AvailableInput->input; if (aci->size > BUFWATERMARK) { fsfree(aci->buffer); fsfree(aci); } else { aci->next = FreeInputs; FreeInputs = aci; } AvailableInput->input = (ConnectionInputPtr) NULL; } AvailableInput = (OsCommPtr) NULL; } if (!oci) { if ((oci = FreeInputs ) != (ConnectionInputPtr) 0) { FreeInputs = oci->next; } else if (!(oci = AllocateInputBuffer())) { yield_control_death(); return -1; } oc->input = oci; } oci->bufptr += oci->lenLastReq; gotnow = oci->bufcnt + oci->buffer - oci->bufptr; request = (fsReq *) oci->bufptr; /* not enough for a request */ if ((gotnow < SIZEOF(fsReq)) || (gotnow < (needed = request_length(request, client)))) { oci->lenLastReq = 0; if ((gotnow < SIZEOF(fsReq)) || needed == 0) needed = SIZEOF(fsReq); else if (needed > MAXBUFSIZE) { yield_control_death(); return -1; } /* see if we need to shift up a partial request so the rest can fit */ if ((gotnow == 0) || ((oci->bufptr - oci->buffer + needed) > oci->size)) { if ((gotnow > 0) && (oci->bufptr != oci->buffer)) memmove( oci->buffer, oci->bufptr, gotnow); /* grow buffer if necessary */ if (needed > oci->size) { char *ibuf; ibuf = (char *) fsrealloc(oci->buffer, needed); if (!ibuf) { yield_control_death(); return -1; } oci->size = needed; oci->buffer = ibuf; } oci->bufptr = oci->buffer; oci->bufcnt = gotnow; } /* fill 'er up */ if (oc->trans_conn == NULL) { yield_control_death(); return -1; } result = _FontTransRead(oc->trans_conn, oci->buffer + oci->bufcnt, oci->size - oci->bufcnt); if (result <= 0) { #if !(defined(SVR4) && defined(i386) && !defined(sun)) if ((result < 0) && ETEST(errno)) { yield_control_no_input(); return 0; } else #endif { yield_control_death(); return -1; } } oci->bufcnt += result; gotnow += result; /* free up space after huge requests */ if ((oci->size > BUFWATERMARK) && (oci->bufcnt < BUFSIZE) && (needed < BUFSIZE)) { char *ibuf; ibuf = (char *) fsrealloc(oci->buffer, BUFSIZE); if (ibuf) { oci->size = BUFSIZE; oci->buffer = ibuf; oci->bufptr = ibuf + oci->bufcnt - gotnow; } } request = (fsReq *) oci->bufptr; if ((gotnow < SIZEOF(fsReq)) || (gotnow < (needed = request_length(request, client)))) { yield_control_no_input(); return 0; } } if (needed == 0) needed = SIZEOF(fsReq); oci->lenLastReq = needed; /* * Check to see if client has at least one whole request in the buffer. If * there is only a partial request, treat like buffer is empty so that * select() will be called again and other clients can get into the queue. */ if (gotnow >= needed + SIZEOF(fsReq)) { request = (fsReq *) (oci->bufptr + needed); if (gotnow >= needed + request_length(request, client)) FD_SET(fd, &ClientsWithInput); else yield_control_no_input(); } else { if (gotnow == needed) AvailableInput = oc; yield_control_no_input(); } if (++timesThisConnection >= MAX_TIMES_PER) yield_control(); client->requestBuffer = (pointer) oci->bufptr; return needed; }
static void error_conn_max(XtransConnInfo trans_conn) { int fd = _FontTransGetConnectionNumber (trans_conn); fsConnSetup conn; char pad[3]; char byteOrder = 0; int whichbyte = 1; struct timeval waittime; fd_set mask; waittime.tv_usec = BOTIMEOUT / MILLI_PER_SECOND; waittime.tv_usec = (BOTIMEOUT % MILLI_PER_SECOND) * (1000000 / MILLI_PER_SECOND); FD_ZERO(&mask); FD_SET(fd, &mask); (void) Select(fd + 1, &mask, NULL, NULL, &waittime); /* try to read the byteorder of the connection */ (void) _FontTransRead(trans_conn, &byteOrder, 1); if ((byteOrder == 'l') || (byteOrder == 'B')) { int num_alts; AlternateServerPtr altservers, as; int i, altlen = 0; num_alts = ListAlternateServers(&altservers); conn.status = AuthDenied; conn.major_version = FS_PROTOCOL; conn.minor_version = FS_PROTOCOL_MINOR; conn.num_alternates = num_alts; for (i = 0, as = altservers; i < num_alts; i++, as++) { altlen += (2 + as->namelen + 3) >> 2; } conn.alternate_len = altlen; /* blow off the auth info */ conn.auth_index = 0; conn.auth_len = 0; if (((*(char *) &whichbyte) && (byteOrder == 'B')) || (!(*(char *) &whichbyte) && (byteOrder == 'l'))) { conn.status = lswaps(conn.status); conn.major_version = lswaps(conn.major_version); conn.minor_version = lswaps(conn.minor_version); conn.alternate_len = lswaps(conn.alternate_len); } (void) _FontTransWrite(trans_conn, (char *) &conn, SIZEOF(fsConnSetup)); /* dump alternates */ for (i = 0, as = altservers; i < num_alts; i++, as++) { (void) _FontTransWrite(trans_conn, (char *) as, 2); /* XXX */ (void) _FontTransWrite(trans_conn, (char *) as->name, as->namelen); altlen = 2 + as->namelen; /* pad it */ if (altlen & 3) (void) _FontTransWrite(trans_conn, (char *) pad, ((4 - (altlen & 3)) & 3)); } }