Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP
Path: utzoo!mnetor!uunet!husc6!rutgers!iuvax!pur-ee!uiucdcs!uxc.cso.uiuc.edu!uicsrd!kai
From: kai@uicsrd.csrd.uiuc.edu
Newsgroups: comp.sources.bugs
Subject: bug fix for SCREEN pgm
Message-ID: <49800003@uicsrd>
Date: Tue, 24-Nov-87 17:27:00 EST
Article-I.D.: uicsrd.49800003
Posted: Tue Nov 24 17:27:00 1987
Date-Received: Sun, 29-Nov-87 18:03:30 EST
Lines: 94
Nf-ID: #N:uicsrd:49800003:000:3084
Nf-From: uicsrd.csrd.uiuc.edu!kai    Nov 24 16:27:00 1987


I have modified the ReceiveMsg() routine in file screen.c of the virtual
terminal manager program "screen" to fix a problem that occured on one of our
machines, but could potentially occur on any UNIX machine.  The problem
occurred when you were already running screen, and you tried to create a new
window by executing the command "screen ".  The message area on the
bottom left side of the screen displayed "Short message (2048 bytes)", and
the command  was never executed.  The source of the fix is included in
this posting.

As the article "A 4.2BSD Interprocess Communication Primer, Draft of July 19,
1984" states; "A Stream socket provides for the bidirectional, reliable,
sequenced, and unduplicated flow of data WITHOUT RECORD BOUNDARIES".

The original ReceiveMsg() routine expected all 2060 bytes sent from a
"client" screen pgm to a "server" screen pgm to make it over in one
write/read combination.  Because stream sockets can not be relied upon to
maintain record boundaries, this is not always the case, so I changed it to
loop until all 2060 bytes are read (usually one or two tries).

I wrote a test client/server model to prove that UNIX domain stream sockets
work without record boundaries.  The server loops waiting for connections,
then reading from the socket until EOF, reporting the size of each block
read.  The client reads from standard input (up to a maximum of 8K blocks) and
writes exactly what it reads out to the socket, reporting the size of each
block read (and subsequently written).

The results were interesting.  I ran the server on one window in screen, and
the client in another, so I could interactively compare the two program
results of block sizes.  I tried "./client < file", where file was a 25K text
file, and client read and wrote three 8K blocks, and one fragment trailing
block.  Server, however, read a mixture of 2K and 4K blocks.  Running the same
test on a different brand system produced the same behaviour, but different
size blocks read.  The code is available upon request.


Patrick Wolfe

pwolfe@kai.com
..!{uunet,ihnp4}!uiucuxc!kailand!pwolfe



Here is the fixed routine ReceiveMsg in file screen.c in it's entirety:


static ReceiveMsg (s) {
    register ns;
    struct sockaddr_un a;
    int len = sizeof (a),
	left;
    struct msg m;
    char *n;

    if ((ns = accept (s, (struct sockaddr *)&a, &len)) == -1) {
	Msg (errno, "accept");
	return;
    }
    /*
     *  read variable size stream socket
     *  messages until the structure m is full
     */
    n = (char *) &m;
    left = sizeof (m);
    while ((left > 0) && ((len = read (ns, n, left)) > 0)) {
	left -= len;
	n += len;
	}
    close (ns);
    if (len == -1) {
	Msg (errno, "read");
	return;
	}
    else if (left > 0) {
	Msg (0, "Short message (%d bytes)", len);
	return;
    }
    switch (m.type) {
    case MSG_CREATE:
	ExecCreate (&m);
	break;
    case MSG_ERROR:
	Msg (0, "%s", m.m.message);
	break;
    default:
	Msg (0, "Invalid message (type %d).", m.type);
    }
}


Patrick Wolfe

pwolfe@kai.com
..!{uunet,ihnp4}!uiucuxc!kailand!pwolfe