Merge branch 'master' of ssh://crater.dragonflybsd.org/repository/git/dragonfly
[dragonfly.git] / sys / kern / tty_subr.c
1 /*
2  * (MPSAFE)
3  *
4  * Copyright (c) 1994, David Greenman
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice unmodified, this list of conditions, and the following
12  *    disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * $FreeBSD: src/sys/kern/tty_subr.c,v 1.32 1999/08/28 00:46:21 peter Exp $
30  * $DragonFly: src/sys/kern/tty_subr.c,v 1.10 2006/12/23 00:35:04 swildner Exp $
31  */
32
33 /*
34  * MPSAFE NOTE: 
35  * Most functions here could use a separate lock to deal with concurrent
36  * access to the cblocks and cblock_*_list.
37  *
38  * Right now the tty_token must be held for all this.
39  */
40
41 /*
42  * clist support routines
43  *
44  * NOTE on cblock->c_cf:        This pointer may point at the base of a cblock,
45  *                              which is &cblock->c_info[0], but will never
46  *                              point at the end of a cblock (char *)(cblk + 1)
47  *                              
48  * NOTE on cblock->c_cl:        This pointer will never point at the base of
49  *                              a block but may point at the end of one.
50  *
51  * These routines may be used by more then just ttys, so a critical section
52  * must be used to access the free list, and for general safety.
53  */
54
55 #include <sys/param.h>
56 #include <sys/kernel.h>
57 #include <sys/systm.h>
58 #include <sys/malloc.h>
59 #include <sys/tty.h>
60 #include <sys/clist.h>
61 #include <sys/thread2.h>
62
63 static void clist_init (void *);
64 SYSINIT(clist, SI_SUB_CLIST, SI_ORDER_FIRST, clist_init, NULL)
65
66 static struct cblock *cfreelist = 0;
67 int cfreecount = 0;
68 static int cslushcount;
69 static int ctotcount;
70
71 #ifndef INITIAL_CBLOCKS
72 #define INITIAL_CBLOCKS 50
73 #endif
74
75 static struct cblock *cblock_alloc (void);
76 static void cblock_alloc_cblocks (int number);
77 static void cblock_free (struct cblock *cblockp);
78 static void cblock_free_cblocks (int number);
79
80 #include "opt_ddb.h"
81 #ifdef DDB
82 #include <ddb/ddb.h>
83
84 DB_SHOW_COMMAND(cbstat, cbstat)
85 {
86         int cbsize = CBSIZE;
87
88         kprintf(
89         "tot = %d (active = %d, free = %d (reserved = %d, slush = %d))\n",
90                ctotcount * cbsize, ctotcount * cbsize - cfreecount, cfreecount,
91                cfreecount - cslushcount * cbsize, cslushcount * cbsize);
92 }
93 #endif /* DDB */
94
95 /*
96  * Called from init_main.c
97  */
98 /* ARGSUSED*/
99 static void
100 clist_init(void *dummy)
101 {
102         /*
103          * Allocate an initial base set of cblocks as a 'slush'.
104          * We allocate non-slush cblocks with each initial ttyopen() and
105          * deallocate them with each ttyclose().
106          * We should adjust the slush allocation.  This can't be done in
107          * the i/o routines because they are sometimes called from
108          * interrupt handlers when it may be unsafe to call kmalloc().
109          */
110         lwkt_gettoken(&tty_token);
111         cblock_alloc_cblocks(cslushcount = INITIAL_CBLOCKS);
112         lwkt_reltoken(&tty_token);
113         KKASSERT(sizeof(struct cblock) == CBLOCK);
114 }
115
116 /*
117  * Remove a cblock from the cfreelist queue and return a pointer
118  * to it.
119  *
120  * May not block.
121  *
122  * NOTE: Must be called with tty_token held
123  */
124 static struct cblock *
125 cblock_alloc(void)
126 {
127         struct cblock *cblockp;
128
129         ASSERT_LWKT_TOKEN_HELD(&tty_token);
130
131         cblockp = cfreelist;
132         if (cblockp == NULL)
133                 panic("clist reservation botch");
134         KKASSERT(cblockp->c_head.ch_magic == CLIST_MAGIC_FREE);
135         cfreelist = cblockp->c_head.ch_next;
136         cblockp->c_head.ch_next = NULL;
137         cblockp->c_head.ch_magic = CLIST_MAGIC_USED;
138         cfreecount -= CBSIZE;
139         return (cblockp);
140 }
141
142 /*
143  * Add a cblock to the cfreelist queue.
144  *
145  * May not block, must be called in a critical section
146  *
147  * NOTE: Must be called with tty_token held
148  */
149 static void
150 cblock_free(struct cblock *cblockp)
151 {
152         ASSERT_LWKT_TOKEN_HELD(&tty_token);
153
154         if (isset(cblockp->c_quote, CBQSIZE * NBBY - 1))
155                 bzero(cblockp->c_quote, sizeof cblockp->c_quote);
156         KKASSERT(cblockp->c_head.ch_magic == CLIST_MAGIC_USED);
157         cblockp->c_head.ch_next = cfreelist;
158         cblockp->c_head.ch_magic = CLIST_MAGIC_FREE;
159         cfreelist = cblockp;
160         cfreecount += CBSIZE;
161 }
162
163 /*
164  * Allocate some cblocks for the cfreelist queue.
165  *
166  * This routine may block, but still must be called in a critical section
167  *
168  * NOTE: Must be called with tty_token held
169  */
170 static void
171 cblock_alloc_cblocks(int number)
172 {
173         int i;
174         struct cblock *cbp;
175
176         ASSERT_LWKT_TOKEN_HELD(&tty_token);
177
178         for (i = 0; i < number; ++i) {
179                 cbp = kmalloc(sizeof *cbp, M_TTYS, M_NOWAIT);
180                 if (cbp == NULL) {
181                         kprintf(
182 "clist_alloc_cblocks: M_NOWAIT kmalloc failed, trying M_WAITOK\n");
183                         cbp = kmalloc(sizeof *cbp, M_TTYS, M_WAITOK);
184                 }
185                 KKASSERT(((intptr_t)cbp & CROUND) == 0);
186                 /*
187                  * Freed cblocks have zero quotes and garbage elsewhere.
188                  * Set the may-have-quote bit to force zeroing the quotes.
189                  */
190                 setbit(cbp->c_quote, CBQSIZE * NBBY - 1);
191                 cbp->c_head.ch_magic = CLIST_MAGIC_USED;
192                 cblock_free(cbp);
193         }
194         ctotcount += number;
195 }
196
197 /*
198  * Set the cblock allocation policy for a clist.
199  */
200 void
201 clist_alloc_cblocks(struct clist *clistp, int ccmax, int ccreserved)
202 {
203         int dcbr;
204
205         /*
206          * Allow for wasted space at the head.
207          */
208         if (ccmax != 0)
209                 ccmax += CBSIZE - 1;
210         if (ccreserved != 0)
211                 ccreserved += CBSIZE - 1;
212
213         crit_enter();
214         lwkt_gettoken(&tty_token);
215         clistp->c_cbmax = roundup(ccmax, CBSIZE) / CBSIZE;
216         dcbr = roundup(ccreserved, CBSIZE) / CBSIZE - clistp->c_cbreserved;
217         if (dcbr >= 0) {
218                 clistp->c_cbreserved += dcbr;   /* atomic w/c_cbmax */
219                 cblock_alloc_cblocks(dcbr);     /* may block */
220         } else {
221                 KKASSERT(clistp->c_cbcount <= clistp->c_cbreserved);
222                 if (clistp->c_cbreserved + dcbr < clistp->c_cbcount)
223                         dcbr = clistp->c_cbcount - clistp->c_cbreserved;
224                 clistp->c_cbreserved += dcbr;   /* atomic w/c_cbmax */
225                 cblock_free_cblocks(-dcbr);     /* may block */
226         }
227         KKASSERT(clistp->c_cbreserved >= 0);
228         lwkt_reltoken(&tty_token);
229         crit_exit();
230 }
231
232 /*
233  * Free some cblocks from the cfreelist queue back to the
234  * system malloc pool.
235  *
236  * Must be called from within a critical section.  May block.
237  */
238 static void
239 cblock_free_cblocks(int number)
240 {
241         int i;
242
243         lwkt_gettoken(&tty_token);
244         for (i = 0; i < number; ++i)
245                 kfree(cblock_alloc(), M_TTYS);
246         ctotcount -= number;
247         lwkt_reltoken(&tty_token);
248 }
249
250 /*
251  * Free the cblocks reserved for a clist.
252  */
253 void
254 clist_free_cblocks(struct clist *clistp)
255 {
256         int cbreserved;
257
258         crit_enter();
259         lwkt_gettoken(&tty_token);
260         if (clistp->c_cbcount != 0)
261                 panic("freeing active clist cblocks");
262         cbreserved = clistp->c_cbreserved;
263         clistp->c_cbmax = 0;
264         clistp->c_cbreserved = 0;
265         cblock_free_cblocks(cbreserved); /* may block */
266         lwkt_reltoken(&tty_token);
267         crit_exit();
268 }
269
270 /*
271  * Get a character from the head of a clist.
272  */
273 int
274 clist_getc(struct clist *clistp)
275 {
276         int chr = -1;
277         struct cblock *cblockp;
278
279         crit_enter();
280         lwkt_gettoken(&tty_token);
281         if (clistp->c_cc) {
282                 KKASSERT(((intptr_t)clistp->c_cf & CROUND) != 0);
283                 cblockp = (struct cblock *)((intptr_t)clistp->c_cf & ~CROUND);
284                 chr = (u_char)*clistp->c_cf;
285
286                 /*
287                  * If this char is quoted, set the flag.
288                  */
289                 if (isset(cblockp->c_quote, clistp->c_cf - (char *)cblockp->c_info))
290                         chr |= TTY_QUOTE;
291
292                 /*
293                  * Advance to next character.
294                  */
295                 clistp->c_cf++;
296                 clistp->c_cc--;
297                 /*
298                  * If we have advanced the 'first' character pointer
299                  * past the end of this cblock, advance to the next one.
300                  * If there are no more characters, set the first and
301                  * last pointers to NULL. In either case, free the
302                  * current cblock.
303                  */
304                 KKASSERT(clistp->c_cf <= (char *)(cblockp + 1));
305                 if ((clistp->c_cf == (char *)(cblockp + 1)) ||
306                     (clistp->c_cc == 0)) {
307                         if (clistp->c_cc > 0) {
308                                 clistp->c_cf = cblockp->c_head.ch_next->c_info;
309                         } else {
310                                 clistp->c_cf = clistp->c_cl = NULL;
311                         }
312                         cblock_free(cblockp);
313                         if (--clistp->c_cbcount >= clistp->c_cbreserved)
314                                 ++cslushcount;
315                 }
316         }
317         lwkt_reltoken(&tty_token);
318         crit_exit();
319         return (chr);
320 }
321
322 /*
323  * Copy 'amount' of chars, beginning at head of clist 'clistp' to
324  * destination linear buffer 'dest'. Return number of characters
325  * actually copied.
326  */
327 int
328 q_to_b(struct clist *clistp, char *dest, int amount)
329 {
330         struct cblock *cblockp;
331         struct cblock *cblockn;
332         char *dest_orig = dest;
333         int numc;
334
335         crit_enter();
336         lwkt_gettoken(&tty_token);
337         while (clistp && amount && (clistp->c_cc > 0)) {
338                 KKASSERT(((intptr_t)clistp->c_cf & CROUND) != 0);
339                 cblockp = (struct cblock *)((intptr_t)clistp->c_cf & ~CROUND);
340                 cblockn = cblockp + 1; /* pointer arithmetic! */
341                 numc = min(amount, (char *)cblockn - clistp->c_cf);
342                 numc = min(numc, clistp->c_cc);
343                 bcopy(clistp->c_cf, dest, numc);
344                 amount -= numc;
345                 clistp->c_cf += numc;
346                 clistp->c_cc -= numc;
347                 dest += numc;
348                 /*
349                  * If this cblock has been emptied, advance to the next
350                  * one. If there are no more characters, set the first
351                  * and last pointer to NULL. In either case, free the
352                  * current cblock.
353                  */
354                 KKASSERT(clistp->c_cf <= (char *)cblockn);
355                 if ((clistp->c_cf == (char *)cblockn) || (clistp->c_cc == 0)) {
356                         if (clistp->c_cc > 0) {
357                                 KKASSERT(cblockp->c_head.ch_next != NULL);
358                                 clistp->c_cf = cblockp->c_head.ch_next->c_info;
359                         } else {
360                                 clistp->c_cf = clistp->c_cl = NULL;
361                         }
362                         cblock_free(cblockp);
363                         if (--clistp->c_cbcount >= clistp->c_cbreserved)
364                                 ++cslushcount;
365                 }
366         }
367         lwkt_reltoken(&tty_token);
368         crit_exit();
369         return (dest - dest_orig);
370 }
371
372 /*
373  * Flush 'amount' of chars, beginning at head of clist 'clistp'.
374  */
375 void
376 ndflush(struct clist *clistp, int amount)
377 {
378         struct cblock *cblockp;
379         struct cblock *cblockn;
380         int numc;
381
382         crit_enter();
383         lwkt_gettoken(&tty_token);
384         while (amount && (clistp->c_cc > 0)) {
385                 KKASSERT(((intptr_t)clistp->c_cf & CROUND) != 0);
386                 cblockp = (struct cblock *)((intptr_t)clistp->c_cf & ~CROUND);
387                 cblockn = cblockp + 1; /* pointer arithmetic! */
388                 numc = min(amount, (char *)cblockn - clistp->c_cf);
389                 numc = min(numc, clistp->c_cc);
390                 amount -= numc;
391                 clistp->c_cf += numc;
392                 clistp->c_cc -= numc;
393                 /*
394                  * If this cblock has been emptied, advance to the next
395                  * one. If there are no more characters, set the first
396                  * and last pointer to NULL. In either case, free the
397                  * current cblock.
398                  */
399                 KKASSERT(clistp->c_cf <= (char *)cblockn);
400                 if (clistp->c_cf == (char *)cblockn || clistp->c_cc == 0) {
401                         if (clistp->c_cc > 0) {
402                                 KKASSERT(cblockp->c_head.ch_next != NULL);
403                                 clistp->c_cf = cblockp->c_head.ch_next->c_info;
404                         } else {
405                                 clistp->c_cf = clistp->c_cl = NULL;
406                         }
407                         cblock_free(cblockp);
408                         if (--clistp->c_cbcount >= clistp->c_cbreserved)
409                                 ++cslushcount;
410                 }
411         }
412         lwkt_reltoken(&tty_token);
413         crit_exit();
414 }
415
416 /*
417  * Add a character to the end of a clist. Return -1 is no
418  * more clists, or 0 for success.
419  */
420 int
421 clist_putc(int chr, struct clist *clistp)
422 {
423         struct cblock *cblockp;
424
425         crit_enter();
426         lwkt_gettoken(&tty_token);
427
428         /*
429          * Note: this section may point c_cl at the base of a cblock.  This
430          * is a temporary violation of the requirements for c_cl, we
431          * increment it before returning.
432          */
433         if (clistp->c_cl == NULL) {
434                 if (clistp->c_cbreserved < 1) {
435                         lwkt_reltoken(&tty_token);
436                         crit_exit();
437                         kprintf("putc to a clist with no reserved cblocks\n");
438                         return (-1);            /* nothing done */
439                 }
440                 cblockp = cblock_alloc();
441                 clistp->c_cbcount = 1;
442                 clistp->c_cf = clistp->c_cl = cblockp->c_info;
443                 clistp->c_cc = 0;
444         } else {
445                 cblockp = (struct cblock *)((intptr_t)clistp->c_cl & ~CROUND);
446                 if (((intptr_t)clistp->c_cl & CROUND) == 0) {
447                         struct cblock *prev = (cblockp - 1);
448
449                         if (clistp->c_cbcount >= clistp->c_cbreserved) {
450                                 if (clistp->c_cbcount >= clistp->c_cbmax
451                                     || cslushcount <= 0) {
452                                         lwkt_reltoken(&tty_token);
453                                         crit_exit();
454                                         return (-1);
455                                 }
456                                 --cslushcount;
457                         }
458                         cblockp = cblock_alloc();
459                         clistp->c_cbcount++;
460                         prev->c_head.ch_next = cblockp;
461                         clistp->c_cl = cblockp->c_info;
462                 }
463         }
464
465         /*
466          * If this character is quoted, set the quote bit, if not, clear it.
467          */
468         if (chr & TTY_QUOTE) {
469                 setbit(cblockp->c_quote, clistp->c_cl - (char *)cblockp->c_info);
470                 /*
471                  * Use one of the spare quote bits to record that something
472                  * may be quoted.
473                  */
474                 setbit(cblockp->c_quote, CBQSIZE * NBBY - 1);
475         } else {
476                 clrbit(cblockp->c_quote, clistp->c_cl - (char *)cblockp->c_info);
477         }
478
479         *clistp->c_cl++ = chr;
480         clistp->c_cc++;
481
482         lwkt_reltoken(&tty_token);
483         crit_exit();
484         return (0);
485 }
486
487 /*
488  * Copy data from linear buffer to clist chain. Return the
489  * number of characters not copied.
490  */
491 int
492 b_to_q(char *src, int amount, struct clist *clistp)
493 {
494         struct cblock *cblockp;
495         char *firstbyte, *lastbyte;
496         u_char startmask, endmask;
497         int startbit, endbit, num_between, numc;
498
499         /*
500          * Avoid allocating an initial cblock and then not using it.
501          * c_cc == 0 must imply c_cbount == 0.
502          */
503         if (amount <= 0)
504                 return (amount);
505
506         crit_enter();
507         lwkt_gettoken(&tty_token);
508
509         /*
510          * Note: this section may point c_cl at the base of a cblock.  This
511          * is a temporary violation of the requirements for c_cl.  Since
512          * amount is non-zero we will not return with it in that state.
513          */
514         if (clistp->c_cl == NULL) {
515                 if (clistp->c_cbreserved < 1) {
516                         lwkt_reltoken(&tty_token);
517                         crit_exit();
518                         kprintf("b_to_q to a clist with no reserved cblocks.\n");
519                         return (amount);        /* nothing done */
520                 }
521                 cblockp = cblock_alloc();
522                 clistp->c_cbcount = 1;
523                 clistp->c_cf = clistp->c_cl = cblockp->c_info;
524                 clistp->c_cc = 0;
525         } else {
526                 /*
527                  * c_cl may legally point past the end of the block, which
528                  * falls through to the 'get another cblock' code below.
529                  */
530                 cblockp = (struct cblock *)((intptr_t)clistp->c_cl & ~CROUND);
531         }
532
533         while (amount) {
534                 /*
535                  * Get another cblock if needed.
536                  */
537                 if (((intptr_t)clistp->c_cl & CROUND) == 0) {
538                         struct cblock *prev = cblockp - 1;
539
540                         if (clistp->c_cbcount >= clistp->c_cbreserved) {
541                                 if (clistp->c_cbcount >= clistp->c_cbmax
542                                     || cslushcount <= 0) {
543                                         lwkt_reltoken(&tty_token);
544                                         crit_exit();
545                                         return (amount);
546                                 }
547                                 --cslushcount;
548                         }
549                         cblockp = cblock_alloc();
550                         clistp->c_cbcount++;
551                         prev->c_head.ch_next = cblockp;
552                         clistp->c_cl = cblockp->c_info;
553                 }
554
555                 /*
556                  * Copy a chunk of the linear buffer up to the end
557                  * of this cblock.
558                  */
559                 numc = min(amount, (char *)(cblockp + 1) - clistp->c_cl);
560                 bcopy(src, clistp->c_cl, numc);
561
562                 /*
563                  * Clear quote bits if they aren't known to be clear.
564                  * The following could probably be made into a separate
565                  * "bitzero()" routine, but why bother?
566                  */
567                 if (isset(cblockp->c_quote, CBQSIZE * NBBY - 1)) {
568                         startbit = clistp->c_cl - (char *)cblockp->c_info;
569                         endbit = startbit + numc - 1;
570
571                         firstbyte = (u_char *)cblockp->c_quote + (startbit / NBBY);
572                         lastbyte = (u_char *)cblockp->c_quote + (endbit / NBBY);
573
574                         /*
575                          * Calculate mask of bits to preserve in first and
576                          * last bytes.
577                          */
578                         startmask = NBBY - (startbit % NBBY);
579                         startmask = 0xff >> startmask;
580                         endmask = (endbit % NBBY);
581                         endmask = 0xff << (endmask + 1);
582
583                         if (firstbyte != lastbyte) {
584                                 *firstbyte &= startmask;
585                                 *lastbyte &= endmask;
586
587                                 num_between = lastbyte - firstbyte - 1;
588                                 if (num_between)
589                                         bzero(firstbyte + 1, num_between);
590                         } else {
591                                 *firstbyte &= (startmask | endmask);
592                         }
593                 }
594
595                 /*
596                  * ...and update pointer for the next chunk.
597                  */
598                 src += numc;
599                 clistp->c_cl += numc;
600                 clistp->c_cc += numc;
601                 amount -= numc;
602                 /*
603                  * If we go through the loop again, it's always
604                  * for data in the next cblock, so by adding one (cblock),
605                  * (which makes the pointer 1 beyond the end of this
606                  * cblock) we prepare for the assignment of 'prev'
607                  * above.
608                  */
609                 ++cblockp;
610         }
611         lwkt_reltoken(&tty_token);
612         crit_exit();
613         return (amount);
614 }
615
616 /*
617  * Get the next character in the clist. Store it at dst. Don't
618  * advance any clist pointers, but return a pointer to the next
619  * character position.
620  *
621  * Must be called at spltty().  This routine may not run in a critical
622  * section and so may not call the cblock allocator/deallocator.
623  */
624 char *
625 nextc(struct clist *clistp, char *cp, int *dst)
626 {
627         struct cblock *cblockp;
628
629         ++cp;
630         /*
631          * See if the next character is beyond the end of
632          * the clist.
633          */
634         lwkt_gettoken(&tty_token);
635         if (clistp->c_cc && (cp != clistp->c_cl)) {
636                 /*
637                  * If the next character is beyond the end of this
638                  * cblock, advance to the next cblock.
639                  */
640                 if (((intptr_t)cp & CROUND) == 0)
641                         cp = ((struct cblock *)cp - 1)->c_head.ch_next->c_info;
642                 cblockp = (struct cblock *)((intptr_t)cp & ~CROUND);
643
644                 /*
645                  * Get the character. Set the quote flag if this character
646                  * is quoted.
647                  */
648                 *dst = (u_char)*cp | (isset(cblockp->c_quote, cp - (char *)cblockp->c_info) ? TTY_QUOTE : 0);
649
650                 lwkt_reltoken(&tty_token);
651                 return (cp);
652         }
653
654         lwkt_reltoken(&tty_token);
655         return (NULL);
656 }
657
658 /*
659  * "Unput" a character from a clist.
660  */
661 int
662 clist_unputc(struct clist *clistp)
663 {
664         struct cblock *cblockp = 0, *cbp = 0;
665         int chr = -1;
666
667         crit_enter();
668         lwkt_gettoken(&tty_token);
669
670         if (clistp->c_cc) {
671                 /*
672                  * note that clistp->c_cl will never point at the base
673                  * of a cblock (cblock->c_info) (see assert this later on),
674                  * but it may point past the end of one.  We temporarily
675                  * violate this in the decrement below but then we fix it up.
676                  */
677                 --clistp->c_cc;
678                 --clistp->c_cl;
679
680                 chr = (u_char)*clistp->c_cl;
681
682                 cblockp = (struct cblock *)((intptr_t)clistp->c_cl & ~CROUND);
683
684                 /*
685                  * Set quote flag if this character was quoted.
686                  */
687                 if (isset(cblockp->c_quote, (u_char *)clistp->c_cl - cblockp->c_info))
688                         chr |= TTY_QUOTE;
689
690                 /*
691                  * If all of the characters have been unput in this
692                  * cblock, then find the previous one and free this
693                  * one.
694                  *
695                  * if c_cc is 0 clistp->c_cl may end up pointing at
696                  * cblockp->c_info, which is illegal, but the case will be 
697                  * taken care of near the end of the routine.  Otherwise
698                  * there *MUST* be another cblock, find it.
699                  */
700                 KKASSERT(clistp->c_cl >= (char *)cblockp->c_info);
701                 if (clistp->c_cc && (clistp->c_cl == (char *)cblockp->c_info)) {
702                         cbp = (struct cblock *)((intptr_t)clistp->c_cf & ~CROUND);
703
704                         while (cbp->c_head.ch_next != cblockp)
705                                 cbp = cbp->c_head.ch_next;
706                         cbp->c_head.ch_next = NULL;
707
708                         /*
709                          * When the previous cblock is at the end, the 'last'
710                          * pointer always points (invalidly) one past.
711                          */
712                         clistp->c_cl = (char *)(cbp + 1);
713                         cblock_free(cblockp);
714                         if (--clistp->c_cbcount >= clistp->c_cbreserved)
715                                 ++cslushcount;
716                 }
717         }
718
719         /*
720          * If there are no more characters on the list, then
721          * free the last cblock.   It should not be possible for c->cl
722          * to be pointing past the end of a block due to our decrement
723          * of it way above.
724          */
725         if (clistp->c_cc == 0 && clistp->c_cl) {
726                 KKASSERT(((intptr_t)clistp->c_cl & CROUND) != 0);
727                 cblockp = (struct cblock *)((intptr_t)clistp->c_cl & ~CROUND);
728                 cblock_free(cblockp);
729                 if (--clistp->c_cbcount >= clistp->c_cbreserved)
730                         ++cslushcount;
731                 clistp->c_cf = clistp->c_cl = NULL;
732         }
733
734         lwkt_reltoken(&tty_token);
735         crit_exit();
736         return (chr);
737 }
738
739 /*
740  * Move characters in source clist to destination clist,
741  * preserving quote bits.
742  */
743 void
744 catq(struct clist *src_clistp, struct clist *dest_clistp)
745 {
746         int chr;
747
748         lwkt_gettoken(&tty_token);
749         crit_enter();
750         /*
751          * If the destination clist is empty (has no cblocks atttached),
752          * and there are no possible complications with the resource counters,
753          * then we simply assign the current clist to the destination.
754          */
755         if (!dest_clistp->c_cf
756             && src_clistp->c_cbcount <= src_clistp->c_cbmax
757             && src_clistp->c_cbcount <= dest_clistp->c_cbmax) {
758                 dest_clistp->c_cf = src_clistp->c_cf;
759                 dest_clistp->c_cl = src_clistp->c_cl;
760                 src_clistp->c_cf = src_clistp->c_cl = NULL;
761
762                 dest_clistp->c_cc = src_clistp->c_cc;
763                 src_clistp->c_cc = 0;
764                 dest_clistp->c_cbcount = src_clistp->c_cbcount;
765                 src_clistp->c_cbcount = 0;
766
767                 crit_exit();
768                 lwkt_reltoken(&tty_token);
769                 return;
770         }
771         crit_exit();
772
773         /*
774          * XXX  This should probably be optimized to more than one
775          * character at a time.
776          */
777         while ((chr = clist_getc(src_clistp)) != -1)
778                 clist_putc(chr, dest_clistp);
779         lwkt_reltoken(&tty_token);
780 }