xref: /csrg-svn/sys/kern/tty.c (revision 5622)
1*5622Swnj /*	tty.c	4.20	82/01/25	*/
239Sbill 
339Sbill /*
4903Sbill  * TTY subroutines common to more than one line discipline
539Sbill  */
639Sbill #include "../h/param.h"
739Sbill #include "../h/systm.h"
839Sbill #include "../h/dir.h"
939Sbill #include "../h/user.h"
1039Sbill #include "../h/tty.h"
1139Sbill #include "../h/proc.h"
1239Sbill #include "../h/inode.h"
1339Sbill #include "../h/file.h"
1439Sbill #include "../h/reg.h"
1539Sbill #include "../h/conf.h"
1639Sbill #include "../h/buf.h"
17340Sbill #include "../h/dk.h"
1839Sbill 
1939Sbill char	partab[];
2039Sbill 
21146Sbill /*
2239Sbill  * Input mapping table-- if an entry is non-zero, when the
2339Sbill  * corresponding character is typed preceded by "\" the escape
2439Sbill  * sequence is replaced by the table value.  Mostly used for
2539Sbill  * upper-case only terminals.
2639Sbill  */
2739Sbill 
2839Sbill char	maptab[] ={
2939Sbill 	000,000,000,000,000,000,000,000,
3039Sbill 	000,000,000,000,000,000,000,000,
3139Sbill 	000,000,000,000,000,000,000,000,
3239Sbill 	000,000,000,000,000,000,000,000,
3339Sbill 	000,'|',000,000,000,000,000,'`',
3439Sbill 	'{','}',000,000,000,000,000,000,
3539Sbill 	000,000,000,000,000,000,000,000,
3639Sbill 	000,000,000,000,000,000,000,000,
3739Sbill 	000,000,000,000,000,000,000,000,
3839Sbill 	000,000,000,000,000,000,000,000,
3939Sbill 	000,000,000,000,000,000,000,000,
4039Sbill 	000,000,000,000,000,000,'~',000,
4139Sbill 	000,'A','B','C','D','E','F','G',
4239Sbill 	'H','I','J','K','L','M','N','O',
4339Sbill 	'P','Q','R','S','T','U','V','W',
4439Sbill 	'X','Y','Z',000,000,000,000,000,
4539Sbill };
4639Sbill 
47925Sbill short	tthiwat[16] =
48925Sbill    { 100,100,100,100,100,100,100,200,200,400,400,400,650,650,650,650 };
49925Sbill short	ttlowat[16] =
50925Sbill    {  30, 30, 30, 30, 30, 30, 30, 50, 50,120,120,120,125,125,125,125 };
51925Sbill 
5239Sbill #define	OBUFSIZ	100
5339Sbill 
5439Sbill /*
5539Sbill  * set default control characters.
5639Sbill  */
5739Sbill ttychars(tp)
5839Sbill register struct tty *tp;
5939Sbill {
60174Sbill 
6139Sbill 	tun.t_intrc = CINTR;
6239Sbill 	tun.t_quitc = CQUIT;
6339Sbill 	tun.t_startc = CSTART;
6439Sbill 	tun.t_stopc = CSTOP;
6539Sbill 	tun.t_eofc = CEOT;
6639Sbill 	tun.t_brkc = CBRK;
6739Sbill 	tp->t_erase = CERASE;
6839Sbill 	tp->t_kill = CKILL;
69174Sbill /* begin local */
70208Sbill 	tlun.t_suspc = CTRL(z);
71208Sbill 	tlun.t_dsuspc = CTRL(y);
72174Sbill 	tlun.t_rprntc = CTRL(r);
73174Sbill 	tlun.t_flushc = CTRL(o);
74174Sbill 	tlun.t_werasc = CTRL(w);
75174Sbill 	tlun.t_lnextc = CTRL(v);
76174Sbill 	tp->t_local = 0;
77174Sbill 	tp->t_lstate = 0;
78174Sbill /* end local */
7939Sbill }
8039Sbill 
8139Sbill /*
82903Sbill  * Wait for output to drain, then flush input waiting.
8339Sbill  */
84903Sbill wflushtty(tp)
855408Swnj 	register struct tty *tp;
8639Sbill {
8739Sbill 
88903Sbill 	(void) spl5();
89*5622Swnj 	while (tp->t_outq.c_cc && tp->t_state&TS_CARR_ON
90*5622Swnj 	    && tp->t_oproc) {		/* kludge for pty */
91903Sbill 		(*tp->t_oproc)(tp);
925408Swnj 		tp->t_state |= TS_ASLEEP;
93903Sbill 		sleep((caddr_t)&tp->t_outq, TTOPRI);
94903Sbill 	}
955426Swnj 	flushtty(tp, FREAD);
96903Sbill 	(void) spl0();
9739Sbill }
9839Sbill 
9939Sbill /*
100903Sbill  * flush all TTY queues
10139Sbill  */
102903Sbill flushtty(tp, rw)
103903Sbill register struct tty *tp;
10439Sbill {
105903Sbill 	register s;
106903Sbill 
107903Sbill 	s = spl6();
108903Sbill 	if (rw & FREAD) {
109903Sbill 		while (getc(&tp->t_canq) >= 0)
110903Sbill 			;
111903Sbill 		wakeup((caddr_t)&tp->t_rawq);
112903Sbill 	}
113903Sbill 	if (rw & FWRITE) {
114903Sbill 		wakeup((caddr_t)&tp->t_outq);
1155408Swnj 		tp->t_state &= ~TS_TTSTOP;
1165426Swnj 		(*cdevsw[major(tp->t_dev)].d_stop)(tp, rw);
117903Sbill 		while (getc(&tp->t_outq) >= 0)
118903Sbill 			;
119903Sbill 	}
120903Sbill 	if (rw & FREAD) {
121903Sbill 		while (getc(&tp->t_rawq) >= 0)
122903Sbill 			;
123903Sbill 		tp->t_delct = 0;
124903Sbill 		tp->t_rocount = 0;		/* local */
125903Sbill 		tp->t_rocol = 0;
126903Sbill 		tp->t_lstate = 0;
127903Sbill 	}
128903Sbill 	splx(s);
12939Sbill }
13039Sbill 
131903Sbill /*
132903Sbill  * Send stop character on input overflow.
133903Sbill  */
134903Sbill ttyblock(tp)
135903Sbill register struct tty *tp;
13639Sbill {
137903Sbill 	register x;
138903Sbill 	x = tp->t_rawq.c_cc + tp->t_canq.c_cc;
139903Sbill 	if (tp->t_rawq.c_cc > TTYHOG) {
140903Sbill 		flushtty(tp, FREAD|FWRITE);
1415408Swnj 		tp->t_state &= ~TS_TBLOCK;
142903Sbill 	}
143903Sbill 	if (x >= TTYHOG/2) {
144903Sbill 		if (putc(tun.t_stopc, &tp->t_outq)==0) {
1455408Swnj 			tp->t_state |= TS_TBLOCK;
146903Sbill 			tp->t_char++;
147903Sbill 			ttstart(tp);
148903Sbill 		}
149903Sbill 	}
15039Sbill }
15139Sbill 
15239Sbill /*
153903Sbill  * Restart typewriter output following a delay
154903Sbill  * timeout.
155903Sbill  * The name of the routine is passed to the timeout
156903Sbill  * subroutine and it is called during a clock interrupt.
157121Sbill  */
158903Sbill ttrstrt(tp)
159121Sbill register struct tty *tp;
160121Sbill {
161121Sbill 
1623351Swnj 	if (tp == 0) {
1633351Swnj 		printf("ttrstrt: arg was 0!\n");
1643351Swnj 		return;
1653351Swnj 	}
1665408Swnj 	tp->t_state &= ~TS_TIMEOUT;
167903Sbill 	ttstart(tp);
168121Sbill }
169121Sbill 
170121Sbill /*
171903Sbill  * Start output on the typewriter. It is used from the top half
172903Sbill  * after some characters have been put on the output queue,
173903Sbill  * from the interrupt routine to transmit the next
174903Sbill  * character, and after a timeout has finished.
17539Sbill  */
176903Sbill ttstart(tp)
177903Sbill register struct tty *tp;
17839Sbill {
179903Sbill 	register s;
18039Sbill 
181903Sbill 	s = spl5();
182*5622Swnj 	if((tp->t_state&(TS_TIMEOUT|TS_TTSTOP|TS_BUSY)) == 0 &&
183*5622Swnj 	    tp->t_oproc)		/* kludge for pty */
184903Sbill 		(*tp->t_oproc)(tp);
185903Sbill 	splx(s);
18639Sbill }
18739Sbill 
18839Sbill /*
189903Sbill  * Common code for tty ioctls.
19039Sbill  */
1911780Sbill /*ARGSUSED*/
1921904Swnj ttioctl(tp, com, addr, flag)
19339Sbill register struct tty *tp;
19439Sbill caddr_t addr;
19539Sbill {
1961904Swnj 	int dev;
19739Sbill 	unsigned t;
198174Sbill 	struct sgttyb iocb;
199191Sbill 	struct clist tq;
20039Sbill 	extern int nldisp;
201887Sbill 	register c;
202728Sbill 	int temp;
20339Sbill 
204903Sbill 	/*
205915Sbill 	 * This is especially so that isatty() will
206915Sbill 	 * fail when carrier is gone.
207915Sbill 	 */
2085408Swnj 	if ((tp->t_state&TS_CARR_ON) == 0) {
209915Sbill 		u.u_error = EBADF;
210915Sbill 		return (1);
211915Sbill 	}
212915Sbill 
2131904Swnj 	dev = tp->t_dev;
214915Sbill 	/*
215903Sbill 	 * If the ioctl involves modification,
216903Sbill 	 * insist on being able to write the device,
217903Sbill 	 * and hang if in the background.
218903Sbill 	 */
21939Sbill 	switch(com) {
22039Sbill 
221915Sbill 	case TIOCSETD:
222915Sbill 	case TIOCSETP:
223915Sbill 	case TIOCSETN:
224903Sbill 	case TIOCFLUSH:
225903Sbill 	case TIOCSETC:
226903Sbill 	case TIOCSLTC:
227903Sbill 	case TIOCSPGRP:
228903Sbill 	case TIOCLBIS:
229903Sbill 	case TIOCLBIC:
230903Sbill 	case TIOCLSET:
231903Sbill 	case TIOCSTI:
232915Sbill /* this is reasonable, but impractical...
233903Sbill 		if ((flag & FWRITE) == 0) {
234903Sbill 			u.u_error = EBADF;
235903Sbill 			return (1);
236903Sbill 		}
237915Sbill  */
238903Sbill 		while (tp->t_line == NTTYDISC &&
239903Sbill 		   u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp &&
240903Sbill 		   (u.u_procp->p_flag&SVFORK) == 0 &&
241903Sbill 		   u.u_signal[SIGTTOU] != SIG_IGN &&
242903Sbill 		   u.u_signal[SIGTTOU] != SIG_HOLD &&
243903Sbill 		   (u.u_procp->p_flag&SDETACH)==0) {
244903Sbill 			gsignal(u.u_procp->p_pgrp, SIGTTOU);
245903Sbill 			sleep((caddr_t)&lbolt, TTOPRI);
246903Sbill 		}
247903Sbill 		break;
248903Sbill 	}
249903Sbill 
25039Sbill 	/*
251903Sbill 	 * Process the ioctl.
25239Sbill 	 */
253903Sbill 	switch(com) {
254903Sbill 
255903Sbill 	/*
256903Sbill 	 * Get discipline number
257903Sbill 	 */
25839Sbill 	case TIOCGETD:
25939Sbill 		t = tp->t_line;
26039Sbill 		if (copyout((caddr_t)&t, addr, sizeof(t)))
26139Sbill 			u.u_error = EFAULT;
26239Sbill 		break;
26339Sbill 
26439Sbill 	/*
265903Sbill 	 * Set line discipline
26639Sbill 	 */
26739Sbill 	case TIOCSETD:
26839Sbill 		if (copyin(addr, (caddr_t)&t, sizeof(t))) {
26939Sbill 			u.u_error = EFAULT;
27039Sbill 			break;
27139Sbill 		}
27239Sbill 		if (t >= nldisp) {
27339Sbill 			u.u_error = ENXIO;
27439Sbill 			break;
27539Sbill 		}
276174Sbill 		(void) spl5();
27739Sbill 		if (tp->t_line)
27839Sbill 			(*linesw[tp->t_line].l_close)(tp);
27939Sbill 		if (t)
28039Sbill 			(*linesw[t].l_open)(dev, tp, addr);
28139Sbill 		if (u.u_error==0)
28239Sbill 			tp->t_line = t;
283174Sbill 		(void) spl0();
28439Sbill 		break;
28539Sbill 
28639Sbill 	/*
2875614Swnj 	 * Prevent more opens on channel
2885614Swnj 	 */
2895614Swnj 	case TIOCEXCL:
2905614Swnj 		tp->t_state |= TS_XCLUDE;
2915614Swnj 		break;
2925614Swnj 
2935614Swnj 	case TIOCNXCL:
2945614Swnj 		tp->t_state &= ~TS_XCLUDE;
2955614Swnj 		break;
2965614Swnj 
2975614Swnj 	/*
29839Sbill 	 * Set new parameters
29939Sbill 	 */
30039Sbill 	case TIOCSETP:
301191Sbill 	case TIOCSETN:
30239Sbill 		if (copyin(addr, (caddr_t)&iocb, sizeof(iocb))) {
30339Sbill 			u.u_error = EFAULT;
30439Sbill 			return(1);
30539Sbill 		}
306121Sbill 		(void) spl5();
3074484Swnj 		if (tp->t_flags&RAW || iocb.sg_flags&RAW ||
3084484Swnj 		    com == TIOCSETP)
3094484Swnj 			wflushtty(tp);
3104484Swnj 		else if ((tp->t_flags&CBREAK) != (iocb.sg_flags&CBREAK)) {
3114484Swnj 			if (iocb.sg_flags & CBREAK) {
3124484Swnj 				catq(&tp->t_rawq, &tp->t_canq);
3134484Swnj 				tq = tp->t_rawq;
3144484Swnj 				tp->t_rawq = tp->t_canq;
3154484Swnj 				tp->t_canq = tq;
3164484Swnj 			} else {
3174484Swnj 				tp->t_local |= LPENDIN;
3184484Swnj 				ttwakeup(tp);
319174Sbill 			}
320174Sbill 		}
3214484Swnj 		tp->t_ispeed = iocb.sg_ispeed;
3224484Swnj 		tp->t_ospeed = iocb.sg_ospeed;
323174Sbill 		tp->t_erase = iocb.sg_erase;
324174Sbill 		tp->t_kill = iocb.sg_kill;
325174Sbill 		tp->t_flags = iocb.sg_flags;
3263941Sbugs 		if (tp->t_flags & RAW) {
3275408Swnj 			tp->t_state &= ~TS_TTSTOP;
3283941Sbugs 			ttstart(tp);
3293941Sbugs 		}
330121Sbill 		(void) spl0();
33139Sbill 		break;
33239Sbill 
33339Sbill 	/*
334903Sbill 	 * Send current parameters to user
33539Sbill 	 */
33639Sbill 	case TIOCGETP:
337174Sbill 		iocb.sg_ispeed = tp->t_ispeed;
338174Sbill 		iocb.sg_ospeed = tp->t_ospeed;
339174Sbill 		iocb.sg_erase = tp->t_erase;
340174Sbill 		iocb.sg_kill = tp->t_kill;
341174Sbill 		iocb.sg_flags = tp->t_flags;
34239Sbill 		if (copyout((caddr_t)&iocb, addr, sizeof(iocb)))
34339Sbill 			u.u_error = EFAULT;
34439Sbill 		break;
34539Sbill 
34639Sbill 	/*
34739Sbill 	 * Hang up line on last close
34839Sbill 	 */
34939Sbill 	case TIOCHPCL:
3505408Swnj 		tp->t_state |= TS_HUPCLS;
35139Sbill 		break;
35239Sbill 
3533942Sbugs 	case TIOCFLUSH: {
3543942Sbugs 		int flags;
3553942Sbugs 		if (addr == 0)
3563942Sbugs 			flags = FREAD|FWRITE;
3573942Sbugs 		else if (copyin(addr, (caddr_t)&flags, sizeof (flags))) {
3583942Sbugs 			u.u_error = EFAULT;
3593983Sroot 			return(1);
3603942Sbugs 		}
3613942Sbugs 		flushtty(tp, flags);
36239Sbill 		break;
3633944Sbugs 	}
36439Sbill 
3655408Swnj 	case FIONBIO: {
3665408Swnj 		int nbio;
3675408Swnj 		if (copyin(addr, (caddr_t)&nbio, sizeof (nbio))) {
3685408Swnj 			u.u_error = EFAULT;
3695408Swnj 			return(1);
3705408Swnj 		}
3715408Swnj 		if (nbio)
3725408Swnj 			tp->t_state |= TS_NBIO;
3735408Swnj 		else
3745408Swnj 			tp->t_state &= ~TS_NBIO;
3755408Swnj 		break;
3765408Swnj 	}
3775408Swnj 
37839Sbill 	/*
379903Sbill 	 * Set and fetch special characters
38039Sbill 	 */
38139Sbill 	case TIOCSETC:
382174Sbill 		if (copyin(addr, (caddr_t)&tun, sizeof(struct tchars)))
38339Sbill 			u.u_error = EFAULT;
38439Sbill 		break;
38539Sbill 
38639Sbill 	case TIOCGETC:
387174Sbill 		if (copyout((caddr_t)&tun, addr, sizeof(struct tchars)))
38839Sbill 			u.u_error = EFAULT;
38939Sbill 		break;
39039Sbill 
391174Sbill /* local ioctls */
392903Sbill 	/*
393903Sbill 	 * Set/get local special characters.
394903Sbill 	 */
395174Sbill 	case TIOCSLTC:
396174Sbill 		if (copyin(addr, (caddr_t)&tlun, sizeof (struct ltchars)))
397174Sbill 			u.u_error = EFAULT;
398174Sbill 		break;
399174Sbill 
400174Sbill 	case TIOCGLTC:
401174Sbill 		if (copyout((caddr_t)&tlun, addr, sizeof (struct ltchars)))
402174Sbill 			u.u_error = EFAULT;
403174Sbill 		break;
404174Sbill 
405903Sbill 	/*
406903Sbill 	 * Return number of characters immediately available.
407903Sbill 	 */
408174Sbill 	case FIONREAD: {
4094484Swnj 		off_t nread = ttnread(tp);
410174Sbill 		if (copyout((caddr_t)&nread, addr, sizeof (off_t)))
411174Sbill 			u.u_error = EFAULT;
412174Sbill 		break;
413174Sbill 		}
414174Sbill 
415174Sbill 	/*
416174Sbill 	 * Should allow SPGRP and GPGRP only if tty open for reading.
417174Sbill 	 */
418174Sbill 	case TIOCSPGRP:
419728Sbill 		if (copyin(addr, (caddr_t)&tp->t_pgrp, sizeof (tp->t_pgrp)))
420728Sbill 			u.u_error = EFAULT;
421174Sbill 		break;
422174Sbill 
423174Sbill 	case TIOCGPGRP:
424174Sbill 		if (copyout((caddr_t)&tp->t_pgrp, addr, sizeof(tp->t_pgrp)))
425174Sbill 			u.u_error = EFAULT;
426174Sbill 		break;
427174Sbill 
428174Sbill 	/*
429174Sbill 	 * Modify local mode word.
430174Sbill 	 */
431174Sbill 	case TIOCLBIS:
432728Sbill 		if (copyin(addr, (caddr_t)&temp, sizeof (tp->t_local)))
433728Sbill 			u.u_error = EFAULT;
434728Sbill 		else
435728Sbill 			tp->t_local |= temp;
436174Sbill 		break;
437174Sbill 
438174Sbill 	case TIOCLBIC:
439728Sbill 		if (copyin(addr, (caddr_t)&temp, sizeof (tp->t_local)))
440728Sbill 			u.u_error = EFAULT;
441728Sbill 		else
442728Sbill 			tp->t_local &= ~temp;
443174Sbill 		break;
444174Sbill 
445174Sbill 	case TIOCLSET:
446728Sbill 		if (copyin(addr, (caddr_t)&temp, sizeof (tp->t_local)))
447728Sbill 			u.u_error = EFAULT;
448728Sbill 		else
449728Sbill 			tp->t_local = temp;
450174Sbill 		break;
451174Sbill 
452174Sbill 	case TIOCLGET:
453174Sbill 		if (copyout((caddr_t)&tp->t_local, addr, sizeof(tp->t_local)))
454174Sbill 			u.u_error = EFAULT;
455174Sbill 		break;
456174Sbill 
457903Sbill 	/*
458903Sbill 	 * Return number of characters in
459903Sbill 	 * the output.
460903Sbill 	 */
461213Sbill 	case TIOCOUTQ:
462213Sbill 		if (copyout((caddr_t)&tp->t_outq.c_cc, addr, sizeof(tp->t_outq.c_cc)))
463213Sbill 			u.u_error = EFAULT;
464213Sbill 		break;
465213Sbill 
466903Sbill 	/*
467903Sbill 	 * Simulate typing of a character at the terminal.
468903Sbill 	 */
469887Sbill 	case TIOCSTI:
470887Sbill 		c = fubyte(addr);
471887Sbill 		if (u.u_uid && u.u_ttyp != tp || c < 0)
472887Sbill 			u.u_error = EFAULT;
473887Sbill 		else
474887Sbill 			(*linesw[tp->t_line].l_rint)(c, tp);
475887Sbill 		break;
4765573Swnj 
4775573Swnj 	case TIOCSTOP:
4785573Swnj 		c = spl5();
4795573Swnj 		if ((tp->t_state & TS_TTSTOP) == 0) {
4805573Swnj 			tp->t_state |= TS_TTSTOP;
4815573Swnj 			(*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
4825573Swnj 		}
4835573Swnj 		splx(c);
4845573Swnj 		break;
4855573Swnj 
4865573Swnj 	case TIOCSTART:
4875573Swnj 		c = spl5();
4885573Swnj 		if ((tp->t_state & TS_TTSTOP) || (tp->t_local & LFLUSHO)) {
4895573Swnj 			tp->t_state &= ~TS_TTSTOP;
4905573Swnj 			tp->t_local &= ~LFLUSHO;
4915573Swnj 			ttstart(tp);
4925573Swnj 		}
4935573Swnj 		splx(c);
4945573Swnj 		break;
4955573Swnj 
496174Sbill /* end of locals */
497887Sbill 
49839Sbill 	default:
49939Sbill 		return(0);
50039Sbill 	}
50139Sbill 	return(1);
50239Sbill }
5034484Swnj 
5044484Swnj ttnread(tp)
5054484Swnj 	struct tty *tp;
5064484Swnj {
5074484Swnj 	int nread = 0;
5084484Swnj 
5094484Swnj 	if (tp->t_local & LPENDIN)
5104484Swnj 		ttypend(tp);
5114484Swnj 	nread = tp->t_canq.c_cc;
5124484Swnj 	if (tp->t_flags & (RAW|CBREAK))
5134484Swnj 		nread += tp->t_rawq.c_cc;
5144484Swnj 	return (nread);
5154484Swnj }
5164484Swnj 
5175408Swnj ttselect(dev, rw)
5184484Swnj 	dev_t dev;
5195408Swnj 	int rw;
5204484Swnj {
5214484Swnj 	register struct tty *tp = &cdevsw[major(dev)].d_ttys[minor(dev)];
5224484Swnj 	int nread;
5235408Swnj 	int s = spl5();
5244484Swnj 
5255408Swnj 	switch (rw) {
5264484Swnj 
5274484Swnj 	case FREAD:
5284484Swnj 		nread = ttnread(tp);
5294484Swnj 		if (nread > 0)
5305408Swnj 			goto win;
5314938Swnj 		if (tp->t_rsel && tp->t_rsel->p_wchan == (caddr_t)&selwait)
5325408Swnj 			tp->t_state |= TS_RCOLL;
5334484Swnj 		else
5344484Swnj 			tp->t_rsel = u.u_procp;
5355408Swnj 		break;
5364484Swnj 
5375408Swnj 	case FWRITE:
5385408Swnj 		if (tp->t_outq.c_cc <= TTLOWAT(tp))
5395408Swnj 			goto win;
5405408Swnj 		if (tp->t_wsel && tp->t_wsel->p_wchan == (caddr_t)&selwait)
5415408Swnj 			tp->t_state |= TS_WCOLL;
5425408Swnj 		else
5435408Swnj 			tp->t_wsel = u.u_procp;
5445408Swnj 		break;
5454484Swnj 	}
5465408Swnj 	splx(s);
5475408Swnj 	return (0);
5485408Swnj win:
5495408Swnj 	splx(s);
5505408Swnj 	return (1);
5514484Swnj }
552