From: gram@aim1.aztec.co.za (Graham Wheeler)
Subject: STREAMS help desperately needed
Organization: Aztec Information Management
Date: Wed, 29 Jul 1992 10:57:47 GMT

No-one has responded to my previous posts about the ldterm STREAMS module, so
I have resigned myself to having to handle all the termio ioctls myself. 
Unfortunately, things haven't got any better. The first ioctl that getty is
issuing to my module is a TCGETA. I am trying to handle this in as sensible
a way as I can (given the lousy documentation), and my machine now just
hangs up completely.

Here is what the manual (UNIX System V Release 4 Programmer's Guide: STREAMS)
says:

pg 7-13: The TCGETA call, if formed as an I_STR call with a data buffer pointer
	set to a value by the user, will always have a data buffer attached to
	b_cont from the main message block. If one assumes that the data block
	is not there and allocates a new buffer and assigned b_cont to point
	at it, the original buffer will be lost. Thus, before assuming that the
	ioctl message does not have a buffer attached, one should check first.

pg B-5: If a module processing an I_STR ioctl wants to send data to a user 
	process, it must use the M_IOCACK message which it constructs such that
	the M_IOCACK block is linked to one or more following M_DATA blocks
	containing the user data. The module must set ioc_count to the number
	of data bytes sent...

Here is my code (with lots of debuggery in):

static int PADuwput(queue_t *q, mblk_t *mp) {
	struct PAD *PAD;
	struct termio *tp;
	PAD = (struct PAD *) q->q_ptr;
	switch (mp->b_datap->db_type) {
	...
	case M_IOCTL: {
		...
		case TCGETA:
			PADdebug(2,iocp->ioc_count==TRANSPARENT?
					"Got transparent TCGETA ioctl\n":
					"Got TCGETA ioctl\n");
			dumpMessage(mp);
			/* It turns out it is not transparent, but an I_STR
				ioctl, so... */

			cmn_err(CE_CONT,"Non-transparent, ioc_count=%d\n",iocp->ioc_count);
			if (mp->b_cont==NULL) {
				cmn_err(CE_CONT,"Allocating termio buffer\n");
				mp->b_cont = allocb(sizeof(struct termio),BPRI_HI);
				iocp->ioc_count += sizeof(struct termio);
				mp->b_cont->b_wptr = mp->b_cont->b_rptr+sizeof(struct termio);
			}
			tp = (struct termio *)mp->b_cont->b_datap;
			tp->c_iflag = PAD->terminfo.c_iflag;
			tp->c_oflag = PAD->terminfo.c_oflag;
			tp->c_lflag = PAD->terminfo.c_lflag;
			cmn_err(CE_CONT,"ACKing IOCTL\n");
			mp->b_datap->db_type = M_IOCACK;
			qreply(q,mp);
			break;
		.....
		}
		.....
	}
	cmn_err(CE_CONT,"Finished in PADuwput\n");
	return 0;
}

============
The output I get is:

got TCGETA ioctl
Non-transparent, ioc_count=0
Allocating termio buffer
ACKing IOCTL
Finished in PADuwput

After which the machine dies (very quietly).

I am at a loss as to what to do next (other than writing my own getty!) I find
it strange that getty does not give me a termio buffer in the first place,
and even stranger that the whole OS dies as a consequence of this code.

PLEASE someone, save me from the depths of despair! Or I'll end up reverting
to writing `Goodbye cruel world' C programs (I certainly won't have a job
anymore).

Yours in desperation
G.


-- 
Graham Wheeler                     | "That which is weak conquers the strong,
Software Systems Engineer/Student  | that which is soft conquers the hard."
Aztec Information Management/UCT   | 		Lao Tzu - Tao Te Ching Ch. 78
gram@aim1.aztec.co.za / gram@cs.uct.ac.za 
Newsgroups: comp.unix.programmer