shepperd@dms.UUCP (Dave Shepperd) (11/10/89)
# This is a shell archive. Remove anything before this line, # then unpack it by saving it in a file and typing "sh file". # # Wrapped by shepperd on Wed Nov 8 20:49:57 PST 1989 # Contents: cledab echo x - cledab sed 's/^@//' > "cledab" <<'@//E*O*F cledab//' } static int dump_ledbuf(lb,msg) struct led_buf *lb; unsigned char *msg; { struct led_buf *nlb; if (lb == 0) { printf("%s: lb = 0\n",msg); return; } nlb = lb; do { printf("%s: lb = %X, next = %X, last = %X, td = %X\n\tttybf = %X, flags = %X\n", msg,nlb,nlb->next,nlb->last,nlb->ttybf->ttyp,nlb->ttybf,nlb->flags); nlb = nlb->next; } while (nlb != lb); return; } static int dump_buftree(tbp) struct tty_buf *tbp; { struct led_buf *lb; struct tty_buf *utbp; printf("Into dump_buftree(): tbp = %X\n",tbp); dump_ttybuf(tty_used,"Used"); dump_ttybuf(tty_free,"Free"); if (tbp != 0) { printf("lbtop = %X\n",tbp->lbtop); dump_ledbuf(tbp->lbtop,"Used"); } dump_ledbuf(ldb_free,"Free"); printf("Strike any key to continue: "); getchar(); printf("Out of dump_buftree()\n"); } static int dump_clist(clp,msg) struct clist *clp; unsigned char *msg; { struct cblock *cbp; int size; printf("Dump_clist() [%s]: ptr = %X\n",msg,clp); if (clp == 0 || clp->c_cf == 0) { printf("clist is empty\n"); return; } printf("\tcc = %d, first = %X, last = %X\n",clp->c_cc,clp->c_cf,clp->c_cl); cbp = clp->c_cf; size = 0; do { unsigned char tstr[CLSIZE+1],*dst,*src; int i; dst = tstr; src = &cbp->c_data[(i=cbp->c_first)]; for (;i < cbp->c_last;++i) { unsigned char c; c = *src++; if (c < ' ' || c > 126) c = '.'; *dst++ = c; } *dst = 0; printf("\t%X, next = %X, first = %d, last = %d, size = %d\n", cbp,cbp->c_next,cbp->c_first,cbp->c_last,cbp->c_last-cbp->c_first); printf("\tstr = {%s}\n",tstr); size += cbp->c_last-cbp->c_first; if (cbp == clp->c_cl) break; cbp = cbp->c_next; } while (cbp != 0); if (size != clp->c_cc) { printf("\tAccumulated size of %d doesn't match c_cc size of %d\n", size,clp->c_cc); } printf("Type any char to continue"); getchar(); printf("\n"); } #endif #if MULTI_LB static struct led_buf *find_ledbuf(); /* forward reference to function */ /************************************************************************** * Put a led_buf back on the free list. */ static int free_lb(lb,tbp) struct led_buf *lb; struct tty_buf *tbp; /* * At entry: * lb - ptr to led_buf to free * tbp - ptr to tty_buf to which the led_buf was assigned * Process context: MUST be task time. * At exit: * buffer is placed on free list. ldb_free will be changed and * tbp->lbtop may be changed if the buffer to be freed is a the top * of the active que. tbp->lbtop will be set to zero if the freed * lb is the only one in the list. */ { if (lb->next == lb) { /* if end of chain */ tbp->lbtop = 0; /* no more lb's for this tb */ } else { lb->next->last = lb->last; /* pluck ourself from the que */ lb->last->next = lb->next; if (lb == tbp->lbtop) { /* if we're at the top, move top */ tbp->lbtop = lb->next; } } if (ldb_free == 0) { /* if the free list is empty */ lb->next = lb->last = lb; /* then we become the only member */ } else { /* otherwise stick us in the que */ lb->last = ldb_free->last; /* our new last is his old last */ lb->next = ldb_free; /* our next is old top */ lb->last->next = ldb_free->last = lb; /* tell others about us */ } ldb_free = lb; /* we become the new top no matter what */ #if MULTI_LB lb->proc = 0; /* not attached to any process anymore */ #endif lb->flags = 0; /* no flags */ lb->ttybf = 0; /* no tty_buf */ } #endif #include "cledefault.c" /************************************************************************* * Ran out of tty_buf's or led_buf's so ripple through the allocated ones * and deallocate any that are no longer being used. It is also called to * init the links in the structures. */ static int garbage_collect(oldtbp) struct tty_buf *oldtbp; /* * At entry: * Process context: task. NEVER call from an interrupt routine. * oldtbp - ptr to tbp buffer of buffer not to put on free list * tty_free points to first element in free list for tty_buf's * tty_used points to first element in used list for tty_buf's * ldb_free points to first element in free list for led_buf's * At exit: * all led_buff's assigned to defunct processes are placed back in the * free list. All tty_buf's that have no led_buf's assigned are * placed back in the free list. */ { struct tty_buf *tbp,*nxttbp,*lasttbp; struct led_buf *lb,*nxtlb,*lastlb; int cnt; if (tty_used == 0 && tty_free == 0) { /* if first time through */ lb = cle_buffers; #if MULTI_LB lb->next = lb->last = lb; /* put all led_buf's on free list */ ldb_free = lastlb = lb++; for (cnt=1;cnt<MAX_LEDBUFS;++cnt,++lb) { nxtlb = lastlb->next; (lb->next=nxtlb)->last = (lb->last=lastlb)->next = lb; } #endif tbp = cle_ttybuf; /* put all tty_buf's on free list */ tbp->next = tbp->last = tbp; #if !(MULTI_LB) lb->ttybf = tbp; /* cross link the 2 structs */ tbp->lbtop = lb++; #endif lasttbp = tbp++; for (cnt=1;cnt<MAX_TTYBUFS;++cnt,++tbp) { nxttbp = lasttbp->next; (tbp->next=nxttbp)->last = (tbp->last=lasttbp)->next = tbp; #if !(MULTI_LB) lb->ttybf = tbp; /* cross link the 2 structs */ tbp->lbtop = lb++; #endif } tty_free = cle_ttybuf; /* set the top pointer */ return; /* done */ } if ((tbp = tty_used) == 0) return; /* if no tty's, nothing to do */ #ifdef M_KERNEL do { lasttbp = tty_used; /* what to stop on */ #if MULTI_LB if ((lb = tbp->lbtop) != 0) do { /* if there're lb's */ struct led_buf *lbtop; lbtop = tbp->lbtop; /* incase the tbp->lbtop moves */ nxtlb = lb->next; /* incase lb is plucked from que */ if (lb->ttybf == 0 || lb->proc == 0 || lb->proc->p_pid != lb->pid || lb->proc->p_ppid != lb->ppid) { free_lb(lb,tbp); /* put the lb on free list */ if (tbp->lbtop == 0) break; /* stop if no more */ } lb = nxtlb; /* move on to next member */ } while (lb != tbp->lbtop); /* for all members in the lb que */ #endif nxttbp = tbp->next; /* point to next tty_buf */ #if MULTI_LB if (tbp->lbtop == 0 && tbp->f_sleep_read == 0 && (tbp->flags&TB_OPENING) == 0 && #else if (tbp->f_sleep_read == 0 && (tbp->flags&TB_OPEN) == 0 && #endif tbp != oldtbp) { if (nxttbp == tbp) { /* if end of chain */ tty_used = 0; /* no more tb's */ nxttbp = 0; /* stop the loop */ lasttbp = 0; } else { int ospl; ospl = spl6(); /* no interrupts for this */ tbp->next->last = tbp->last; /* pluck ourself from the que */ tbp->last->next = tbp->next; if (tbp == tty_used) { /* if we're at the top, move top */ tty_used = tbp->next; } splx(ospl); /* interrupts ok now */ } if (tty_free == 0) { /* if the free list is empty */ tbp->next = tbp->last = tbp; /* then we become the only member */ } else { /* otherwise stick us in the que */ struct tty_buf *tn; tn = tty_free->next; (tbp->next=tn)->last = (tbp->last=tty_free)->next = tbp; } tty_free = tbp; /* we become the top no matter what */ tbp->flags = 0; /* now zap any existing data in struct */ tbp->f_refresh = tbp->f_sleep_read = 0; setup_ansi_defaults(tbp); /* reset tbp buffer if any */ if (tbp->broadcast.c_cf != 0) { /* if have a cblock */ struct cblock *cnxt; int ospl; ospl = spl6(); while((cnxt=getcb(&tbp->broadcast)) != 0) putcf(cnxt); cle_kickit(tbp->ttyp); splx(ospl); } } tbp = nxttbp; /* move to next buf */ } while (tbp != lasttbp); /* for all members of list */ #endif /* M_KERNEL */ } /******************************************************************** * Get the next available led_buf from the freelist. */ static struct led_buf *get_ledbuf(tbp) struct tty_buf *tbp; /* * At entry: * Process context: task. Must never be called from interrupt routine. * tbp - ptr to tty_buf assigned to tty struct to which led_buf is to be * attached. * At exit: * returns ptr to led_buf if one is available else returns 0. * If led_buf is attached, it is placed at the head of the que; * tbp->lbtop will be moved in that case. The led_buf is initialised * for use. The history buffer is purged and the keydef buffer is * preset to defaults. */ { struct led_buf *lb,*next,*last; int cnt; unsigned char *chr; #if !(MULTI_LB) lb = tbp->lbtop; /* there's only 1 */ #else if (ldb_free == 0) { /* if no more free buffers */ garbage_collect(tbp); /* try to free up some */ if (ldb_free == 0) return 0; /* if still none, return empty */ } lb = ldb_free; /* pick up the one on top */ if (lb->next == lb) { /* if we're the only one */ ldb_free = 0; /* free list is now empty */ } else { lb->next->last = lb->last; /* pluck ourselves from free que */ lb->last->next = lb->next; ldb_free = lb->next; /* move free pointer */ } if (tbp->lbtop == 0) { /* if we're to be the only member */ lb->next = lb->last = lb; /* point to ourself */ } else { next = tbp->lbtop; /* point to new next */ last = next->last; (lb->last=last)->next = (lb->next=next)->last = lb; } tbp->lbtop = lb; lb->ttybf = tbp; /* connect led_buf to tty_buf */ #ifdef M_KERNEL lb->proc = u.u_procp; /* save pointer to process struct */ lb->pid = u.u_procp->p_pid; /* and requestor's pid */ lb->ppid = u.u_procp->p_ppid; /* and pid of parent */ #endif #endif lb->flags = (tbp->flags&TB_INSERT) ? LD_INSERT : 0; lb->old[0] = 1; /* zap history buffer */ lb->old[1] = 0; lb->prmptsz = 0; /* no prompt */ chr = lb->old + HISTBUFSIZ; /* zap the key def buffer */ *--chr = 0; /* no key defs anymore */ lb->key = chr; lb->owed = 0; return lb; /* done */ } #if MULTI_LB /******************************************************************** * Find the led_buf in the list belonging to this process. */ static struct led_buf *find_ledbuf(tbp,uproc) struct tty_buf *tbp; struct proc *uproc; /* * At entry: * Process context: task. Must never be called from interrupt routine. * tbp - ptr to tty_buf assigned to tty struct which has led_buf que * uproc - pointer to element in process table (used only to inspect * the p_pid and p_ppid fields). * At exit: * returns ptr to led_buf if one is found else returns 0. * If led_buf is found, it is placed at the head of the que; * tbp->lbtop may be moved in that case. */ { struct led_buf *lb,*next; int cont,cnt=0; if ((lb = tbp->lbtop) == 0) return 0; #ifdef M_KERNEL do { cont = 0; next = lb->next; /* save ptr to next */ if (lb->proc == 0 || lb->proc->p_stat == 0) { /* purge led_bufs for... */ if (lb == tbp->lbtop) cont = 1; /* if we're the top */ free_lb(lb,tbp); /* ...defunct procs */ if (tbp->lbtop == 0) { lb = 0; /* there aren't anymore */ break; } } else { if (lb->proc == uproc) { /* if found the one for this process */ if (lb->pid != uproc->p_pid || lb->ppid != uproc->p_ppid) { free_lb(lb,tbp); /* but process has gone defunct... */ lb = 0; /* ...put it back on the freelist */ } else if (lb != tbp->lbtop) { /* if not already at head of que */ struct led_buf *next,*last; lb->last->next = lb->next; /* pluck ourselves from the list */ lb->next->last = lb->last; next = tbp->lbtop; /* point to new next */ last = next->last; (lb->last=last)->next = (lb->next=next)->last = lb; tbp->lbtop = lb; /* and we're the new top */ } return lb; } } lb = next; ++cnt; } while ((cont || lb != tbp->lbtop) && cnt < MAX_TTYBUFS); return 0; /* not in the list */ #else return &cle_buffers[0]; #endif } #endif /* MULTI_LB */ /*************************************************************************** * Get a tty_buf from the free pool. */ static struct tty_buf *get_ttybuf(tp) struct tty *tp; /* * At entry: * Process context: task. Never call this from an interrupt routine. * tp - ptr to tty struct to which the tty_buf will become associated. * At exit: * returns ptr to tty_buf or 0 if there aren't any available. * tty_buf is removed from the free list and inserted into the used * list which may make tty_used and tty_free change values. */ { struct tty_buf *tbp,*next,*last; int cnt; unsigned char *chr; if (tty_free == 0) { /* if no more free buffers then */ garbage_collect(tbp); /* try to free up some */ if (tty_free == 0) return 0; /* if still none, give up */ } tbp = tty_free; /* take one from the top */ if (tbp->next == tbp) { /* if we're the last one... */ tty_free = 0; /* the list is now empty */ } else { tbp->next->last = tbp->last; /* extricate this one from the freelist */ tbp->last->next = tbp->next; tty_free = tbp->next; /* move free pointer */ } tbp->ttyp = tp; /* connect tty_buf to device */ tbp->f_refresh = tbp->f_sleep_read = 0; #if MULTI_LB tbp->lbtop = 0; /* no lb buffer assigned */ #else get_ledbuf(tbp); /* init the attached lb */ #endif next = tty_used; if (next == 0) { /* if we're the first one used */ tbp->next = tbp->last = tbp; /* point to ourself */ #ifdef M_KERNEL } else { int ospl; ospl = spl6(); /* no interrupts */ last = next->last; (tbp->last=last)->next = (tbp->next=next)->last = tbp; splx(ospl); /* interrupts ok now */ #endif } /* * The following sets up the default insert/overstrike mode */ tbp->flags = TB_INSERT; /* default to insert mode */ /* * Setup the default ansi strings to output to the terminal for various operations */ setup_ansi_defaults(tbp); /* * The following init's cross connect the input key to the desired edit function */ setup_key_defaults(tbp); /* * End of function setup */ tty_used = tbp; /* we become the new head of the que */ return tbp; /* done */ } /************************************************************************* * Find a tty_buf that's attached to a tty struct and move it to the head * of the que if it's in the list. */ static struct tty_buf *find_ttybuf(tp) struct tty *tp; /* * At entry: * Process context: task. Must not be called from interrupt. * tp - ptr to tty struct to match * At exit: * returns ptr to tty_buf or 0 if none found. Does not modify the * contents of any structures, so it is re-entrant and interruptable. */ { int cnt=0; struct tty_buf *tbp,*next,*last; if ((tbp=tty_used) == 0) return 0; /* not there */ do { if (tbp->ttyp == tp) { /* found it. Move ourselves to head */ #ifdef M_KERNEL if (tbp != tty_used) { /* if not already there */ int ospl; ospl = spl6(); tbp->next->last = tbp->last; /* unque us */ tbp->last->next = tbp->next; next = tty_used; /* get ptr to next and prev */ last = next->last; (tbp->last=last)->next = (tbp->next=next)->last = tbp; tty_used = tbp; /* move this too */ splx(ospl); } #endif return tbp; } tbp = tbp->next; /* loop */ ++cnt; } while ((tbp != tty_used) && cnt < MAX_TTYBUFS); /* through the whole list */ return 0; /* not there */ } /************************************************************************** * The routines cleopen, cleclose, cleread, clewrite and cleioctl are * called by the kernel (via a dispatch through the linesw array) and are * all executed at process task time. The routines cleinput and cleouput * are interrupt routines. Except for cleinput and cleioctl all the routines * have the same interface: a pointer to the tty struct assigned to the * real or pseudo terminal. cleinput has an extra flag argument which * indicates whether the input character is real or the result of the * terminal sending a break. cleioctl has an extra argument that has the * function code the ioctl is to do. **************************************************************************/ /************************************************************************** * Send saved broadcast message to terminal. */ static int send_brdcst(tbp,clr_flg) struct tty_buf *tbp; int clr_flg; /* * At entry: * Process context: task. * tbp - ptr to tty_buf which contains the message * clr_flg - true if the message line is to be precleared * At exit: * the cblock(s) holding the message are moved from the clist in tty_buf * to the t_outq clist. */ { #ifdef M_KERNEL int ospl; unsigned char c; struct cblock *bp; struct clist *bl,*tpc; tpc = &tbp->ttyp->t_outq; bl = &tbp->broadcast; if (clr_flg) cle_puts(tbp->ansi[ANSI_CLRLINE],tbp->ttyp); /* preclear the current line */ ospl = spl6(); /* no interrupts for the following */ while(1) { bp = getcb(bl); /* get next cblock from broadcast */ if (bp == 0) break; /* if 0, done */ putcb(bp,tpc); /* stick it on the t_outq */ } cle_kickit(tbp->ttyp); splx(ospl); /* interrupts ok now */ #endif } /*************************************************************************** * Open line discpline */ static struct tty_buf *open_it(tbp,td) struct tty_buf *tbp; struct tty *td; /* * At entry: * tbp - ptr to tty_buf to open (or 0 if not preassigned) * td - ptr to tty struct to open */ { int flag; #ifdef M_KERNEL if (tbp == 0) { garbage_collect(); /* free up some space */ tbp = get_ttybuf(td); /* get a tty_buf */ flag = 1; } else { flag = ((tbp->flags&TB_OPEN) == 0); /* true if not currently open */ } if (tbp != 0) { tbp->flags |= TB_OPEN|TB_OPENING; /* we're open */ if (flag) { show_pid(1," started by process ",td); cle_puts(tbp->ansi[ANSI_SETUP],td); } } else { if (flag) { cle_puts("\rNo buffers available to start cled\r\n",td); u.u_error = ERR_NOTTYBUF; /* return with error */ } } if (flag) cle_kickit(td); #endif return tbp; } /************************************************************************** * Open the line discipline. This procedure is called by kernel code when * the line discipline is selected. I haven't yet determined what exactly * the open is supposed to do, but since cled uses discipline 0, if IT (ld0) * isn't opened too, very strange terminal behavior results. */ int cleopen(tp) struct tty *tp; /* * At entry: * tp - ptr to tty struct * process context: task. * At exit: * discipline 0 is opened */ { #ifdef M_KERNEL (*linesw[0].l_open)(tp); open_it(find_ttybuf(tp),tp); #endif return (1); } /*************************************************************************** * Close the line discpline */ static int close_it(tbp,td) struct tty_buf *tbp; struct tty *td; /* * At entry: * tbp - ptr to tty_buf to close (or 0 if not preassigned) * td - ptr to tty struct to open */ { #ifdef M_KERNEL if (tbp != 0) { /* if there's a tbp */ int ospl; if (td->t_state&ISOPEN) { show_pid(0,"\rcled stopped by process ",td); cle_kickit(td); } if (tbp->f_sleep_read) { /* and sleeping */ wakeup(tbp); /* wakeup the sleepers */ tbp->f_sleep_read = 0; if (td->t_state&ISOPEN) tbp->flags |= TB_FLUSHIT; } ospl = spl6(); tbp->flags &= ~(TB_OPEN|TB_OPENING); /* not open anymore */ splx(ospl); } #endif } /************************************************************************** * Close the line discipline. This procedure is called by kernel code when * the line discipline is deselected. I haven't yet determined what exactly * the close is supposed to do, but a call to close discipline 0 is done * because it apparently needs it. */ int cleclose(tp) struct tty *tp; /* * At entry: * tp - ptr to tty struct * process context: task. * At exit: * discipline 0 is closed */ { #ifdef M_KERNEL (*tp->t_proc)(tp,T_RESUME); /* make sure output is running */ close_it(find_ttybuf(tp),tp); delay(HZ); /* wait 1 second */ ttyflush(tp,FWRITE|FREAD); /* then flush the ques */ (*linesw[0].l_close)(tp); #endif return (1); } #ifdef M_KERNEL /************************************************************************ * read timeout routine. This is a a kludge cuz I can't figure out who's * zapping the tty struct out from under cled. It usually happens after * the cleread routine has gone to sleep. It can be forced, however by * some other process intentionally changing the line number or other * tty flags while a read is in progress. This routine helps correct * the sitiuation. */ static int read_timeout(arg) struct tty_buf *arg; /* * At entry: * arg - ptr to the tty_buf belonging to the process doing the read * At exit: * TB_TIMEOUT set in the tty flags and a wakeup is delivered. */ { if (arg->f_sleep_read) wakeup(arg); arg->f_sleep_read = 0; return; } /********************************************************************** * Announce that's there's no room at the inn */ static int no_room(tp,typ) struct tty *tp; char *typ; /* * At entry: * tp - ptr to tty struct * typ - ascii string describing buffer type that we're out of * At exit: * message output to the terminal * line discipline reset to ld 0 */ { cle_puts("\rSorry, not enough ",tp); cle_puts(typ,tp); cle_puts(" buffers to run cled at this time.\r\n",tp); tp->t_line = 0; /* switch to line 0 */ (*linesw[0].l_read)(tp); /* use ld0's read */ return 1; } #endif /************************************************************************ * Read a line from the terminal. This routine exits when the user types * the specified eol character (normally a \r). */ int cleread(tp) /* called by the terminal driver */ struct tty *tp; /* * At entry: * Process context: task. * tp - ptr to tty struct * At exit: * process sleeps until user types one of an EOL, an EOF, a QUIT or * an INTR character (normally an \r, ^D, DEL and ^C characters * respectively). The line of text input from terminal is moved * to user's buffer as specified by u.u_count and u.u_base. An EOF * results in 0 chars being returned. This routine will not exit * normally if an interrupt or quit character is typed (the kernel * takes control via the signal and will cancel the I/O request * without this routine going through its normal exit sequence). * If the terminal has been set to "raw" mode, this read passes * control to discipline 0, otherwise the line editing functions * of cled become active while the line of input is being typed. */ { struct led_buf *lb; struct tty_buf *tbp; unsigned char *cp; int c,len,time_id; tbp = find_ttybuf(tp); /* get tty buffer */ #ifdef M_KERNEL if (tbp == 0) return no_room(tp,"tty"); if (u.u_count == 0 || ((tp->t_lflag&(ICANON|ECHO|ECHOE|ECHOK)) != (ICANON|ECHO|ECHOE|ECHOK))) { if (tbp != 0) tbp->flags |= TB_NOLINE; /* reading without ld */ (*linesw[0].l_read)(tp); /* use ld0's read */ return 1; } if ((tbp->flags&TB_OPEN) == 0) open_it(tbp,tp); #endif #if MULTI_LB lb = find_ledbuf(tbp,u.u_procp); /* get associated led_buf */ if (lb == 0) lb = get_ledbuf(tbp); /* get a new one */ #else lb = tbp->lbtop; #endif if (tbp->broadcast.c_cc != 0) { send_brdcst(tbp,0); cle_puts("\r\n",tp); tbp->f_refresh = 1; /* reprint the prompt if there is one */ } #ifdef M_KERNEL if (lb == 0) { close_it(tbp,tp); return no_room(tp,"led"); } #endif tbp->flags &= ~(TB_NOLINE|TB_OPENING); /* reading with line discipline */ #ifdef M_KERNEL if (lb->owed != 0) { /* if still owe data from last time */ len = lb->lcurs-lb->owed; /* how much data left to send */ if (len > 0) { /* if valid */ if (len > u.u_count) len = u.u_count; /* only as much as asked for */ copyout(lb->owed,u.u_base,len); /* give 'em what's left */ lb->owed += len; u.u_base += len; u.u_count -= len; if (lb->owed >= lb->lcurs) lb->owed = 0; /* owe no more */ return; /* keep going until all given */ } lb->owed = 0; /* owe no more */ } #endif lb->maxlin = COMBUFSIZ-1; /* max length of command line (cannot be > 255) */ lb->end_posn = lb->maxlin - 1; /* set the max pointer */ lb->lcurs = lb->buf; /* set the left side ptrs */ lb->rcurs = lb->bufend = lb->buf + lb->end_posn; /* and right side ptrs */ lb->state = NORMAL; /* start out normal */ lb->oldndx = 0; /* reset the index to the history file */ lb->oldmatlen = 0; /* for match history */ lb->flags &= ~(LD_DONE|LD_QUIT|LD_INTR|LD_EOF|LD_BACKUP|LD_INSERT); lb->flags |= (LD_DIRTY); /* buffer is dirty and insert mode */ if (tbp->flags&TB_INSERT) lb->flags |= LD_INSERT; /* set default mode */ tbp->flags |= TB_READING; /* tell top level someone is reading */ lb->defkey = 0; /* not defining a buffer */ lb->c_posn = 0; /* at left side */ *lb->lcurs = *lb->rcurs = 0; /* put nulls at both ends of the buffer */ #ifdef M_KERNEL tbp->iflag = tp->t_iflag; tbp->oflag = tp->t_oflag; tbp->lflag = tp->t_lflag; tbp->cflag = tp->t_cflag; for (c=0;c<NCC+2;++c) tbp->cc[c] = tp->t_cc[c]; while (tp->t_outq.c_cc != 0 || (tbp->flags&TB_WRITING) != 0) { cle_kickit(tp); /* make sure output is running */ delay(HZ/10); /* wait for output to clear */ } if (tbp->f_refresh) { /* if we start with refresh */ tbp->f_refresh = 0; reprint(lb); /* then put up the prompt et al */ cle_kickit(tp); /* make sure output is running */ } #endif while ((lb->flags&LD_DONE) == 0) { /* loop until a whole line is typed in */ #ifdef M_KERNEL int ospl; ospl = spl6(); /* disable tt interupts during rbi test */ if (tp->t_rawq.c_cc == 0) { /* if nothing in the input */ if (tbp->f_refresh) { /* got a punch through? */ tbp->f_refresh = 0; /* yep, reset it */ splx(ospl); /* re-enable interrupts */ reprint(lb); /* ...refresh the screen */ cle_kickit(tp); /* ...kick start the output */ continue; /* see if more input showed up */ } if ((tbp->flags&TB_OPEN) == 0) { /* we're no longer using this ld */ lb->flags |= LD_DONE|LD_EOF; /* signal eof */ cle_puts("\r\nTrying to cleread while cled turned off\r\n",tp); break; } if (tp->t_line != our_lineno || ((tp->t_lflag&(ICANON|ECHO|ECHOE|ECHOK)) != (ICANON|ECHO|ECHOE|ECHOK))) { cle_puts("\r\n\007cled warning: tty struct has been zapped. Reseting it.\r\n",tp); tp->t_iflag = tbp->iflag; tp->t_oflag = tbp->oflag; tp->t_lflag = tbp->lflag; tp->t_cflag = tbp->cflag; tp->t_line = our_lineno; for (c=0;c<NCC+2;++c) tp->t_cc[c] = tbp->cc[c]; tp->t_state |= ISOPEN; tbp->f_refresh = 1; continue; } time_id = timeout(read_timeout,tbp,HZ*15); /* set 15 second timeout */ tbp->f_sleep_read = 1; /* signal we're asleep */ if (sleep(tbp,PZERO+8|PCATCH)) { /* sleep for awhile */ untimeout(time_id); /* cancel timeout */ u.u_error = EINTR; /* got an attention */ return (-1); /* exit with an error */ } untimeout(time_id); /* cancel the timeout */ splx(ospl); /* just in case we come back at spl6 */ while (tp->t_outq.c_cc != 0 || (tbp->flags&TB_WRITING) != 0) { cle_kickit(tp); /* make sure output is running */ delay(HZ/10); /* wait for it to clear */ } if ((tbp->flags&TB_FLUSHIT) != 0) { eol(lb); /* goto eol */ d_bol(lb); /* delete to bol */ ospl = spl6(); tbp->flags &= ~TB_FLUSHIT; tbp->f_refresh = 1; splx(ospl); if ((tbp->flags&TB_OPEN) == 0) break; } continue; } splx(ospl); /* reset our priority */ c = getc(&tp->t_rawq); /* pickup the next char */ #else c = cle_getc(lb); #endif if (lb->state == NORMAL && c != 0) { if (c == tp->t_cc[VEOF]) { /* got an EOF? */ lb->flags |= LD_EOF; /* say we got an EOF */ lb->state = NCC_SPC|VEOL; /* and eol */ c = 0; } else if (c == tp->t_cc[VERASE]) { /* erase? */ lb->state = NCC_SPC|VERASE; /* signal special mode */ c = 0; } else if (c == tp->t_cc[VKILL]) { /* line kill? */ lb->state = NCC_SPC|VKILL; c = 0; } else if ((tp->t_cc[VEOL] == 0 && c == CR) || (c == tp->t_cc[VEOL])) { /* end of line? */ lb->state = NCC_SPC|VEOL; c = 0; } } lb->c = c; /* pass the char */ parse_it(lb); /* parse what we've got */ #ifdef M_KERNEL cle_kickit(tp); #endif } /* for all input chars */ cp = lb->lcurs; /* point to end of command line */ if ((lb->flags&LD_EOF) == 0) { *cp++ = '\n'; /* stuff in an EOL */ lb->lcurs = cp; } len = cp-lb->buf; tbp->flags &= ~TB_READING; /* no longer reading */ #ifdef M_KERNEL if (len != 0) { if (len > u.u_count) len = u.u_count; copyout(lb->buf,u.u_base,len); u.u_base += len; u.u_count -= len; cle_puts("\r\n",tp); } else { cle_puts(tbp->ansi[ANSI_MSGEOF],tp); } if (tp->t_delct > 0) --tp->t_delct; /* count down the delimiter */ if (tbp->broadcast.c_cc != 0) { /* got a broadcast message */ send_brdcst(tbp,0); /* blast the broadcast message */ cle_puts("\r\n",tp); /* follow it with a \n */ } cle_kickit(tp); /* kick start the output */ #else strncpy(u.u_base,lb->buf,len); *(u.u_base+len) = 0; #endif if (lb->buf+len >= lb->lcurs) { /* if he got all we had */ lb->owed = (unsigned char *)0; } else { lb->owed = lb->buf+len; /* else point to what to give 'em next */ } lb->prmptsz = 0; /* kill any existing prompt */ lb->prmpt[0] = 0; return 1; } #ifdef M_KERNEL /************************************************************************ * Kick start the output. This routine is called whenever there is data * in the t_outq buffer to make sure that it gets sent to the terminal. */ static int cle_kickit(tp) struct tty *tp; /* * At entry: * Process context: Task or Interrupt. May be called from either. * tp - ptr to tty struct * At exit: * If data present in t_outq and output not already running, then a * call to the terminal driver processor routine (t_proc) with the * output option selected is made which will cause data to be moved * from the t_outq clist to the t_obuf output array for subsequent * output to the hardware. */ { int ospl; ospl = spl6(); /* no interrupts for the next test */ if (tp->t_outq.c_cc != 0) { /* anything in the output que? */ if ((tp->t_state&(BUSY|TIMEOUT|TTSTOP)) == 0 || tp->t_tbuf.c_count == 0) { /* and output not already busy */ splx(ospl); /* interrupts ok now */ (*tp->t_proc)(tp,T_OUTPUT); /* kick start the output */ } } splx(ospl); /* reset the priority */ } /************************************************************************** * Put a character in the output que for subsequent output to the terminal */ static int cle_putc(c,tp) unsigned char c; struct tty *tp; /* * At entry: * Process context: Task or Interrupt. * c - char to output * tp - ptr to tty struct * At exit: * character is placed in the t_outq clist. If there's no more room, * it is discarded with no error message. */ { putc(c,&tp->t_outq); } /************************************************************************** * Put a null terminated string of characters in the output que for subsequent * output to the terminal. */ static int cle_puts(s,tp) unsigned char *s; struct tty *tp; /* * At entry: * Process context: Task or Interrupt. * s - ptr to null terminated string to output * tp - ptr to tty struct * At exit: * characters are placed in the t_outq clist. If there's no room for * the whole message, that that won't fit is discarded with no error. */ { register unsigned char *s1 = s; struct clist dumcl,*clp; struct cblock *srcp; int ospl,cnt; if (s1 == 0 || *s1 == 0) return; /* skip null msgs */ while(*s1++); /* skip to end of string */ cnt = s1-s-1; /* compute length of string */ dumcl.c_cc = 0; /* init our dummy clist */ dumcl.c_cf = dumcl.c_cl = 0; clp = &tp->t_outq; /* ptr to outq clist */ ospl = spl6(); /* book says hafta call at spl6() */ putcbp(&dumcl,s,cnt); /* put msg into dummy clist */ while((srcp = getcb(&dumcl)) != 0) putcb(srcp,clp); /* copy to outq */ splx(ospl); /* interrupts ok now */ return; } /************************************************************************* * Input interrupt routine. This routine is called after n characters have * been placed in the interrupt holding buffer (t_rbuf) and/or a certain * time has elapsed since the last input interrupt occurred (This technique * tends to reduce the CPU load somewhat by bunching input character * processing on dumb terminal ports). */ int cleinput(td,bflg) struct tty *td; int bflg; /* * At entry: * Process context: Interrupt * td - ptr to tty struct * bflg - not 0 if interrupt due to a BREAK, else 0 * At exit: * data in the t_rbuf buffer has been moved to the t_rawq clist. * If the terminal is not in raw mode, then checks for the INTR * and QUIT input chars were made and signals sent if so found. * A wakeup() has been issued to any processes waiting for input * from this port. */ { int i,indx,ospl; unsigned char c,*cp,*msg; struct led_buf *lb; struct tty_buf *tbp; tbp = tty_used; /* get ptr to top of tty_buf list */ i = 0; if (tbp != 0) do { /* find ptr belonging to this port */ if (tbp->ttyp == td) break; tbp = tbp->next; ++i; } while ((tbp != tty_used) && i < MAX_TTYBUFS); if ((td->t_lflag&(ICANON|ECHO|ECHOE|ECHOK)) != (ICANON|ECHO|ECHOE|ECHOK) || tbp == 0 || tbp->ttyp != td || (tbp->ttyp == td && (tbp->flags&TB_NOLINE) != 0)) { /* if terminal in "raw mode" or there's no tb ptr for it or the tb indicates to use no discipline then... */ (*linesw[0].l_input)(td,bflg); /* ...use normal mode */ return; } if (bflg == L_BREAK) { /* if got here due to a BREAK */ if ((td->t_lflag&ISIG) != 0 && (td->t_iflag&BRKINT) != 0) { cp = &c; /* if ISIG and BRKINT enabled */ c = td->t_cc[VINTR]; /* pretend we got an INTR char */ i = 1; /* only 1 char */ } else { return; /* else ignore it */ } } else { if (td->t_rbuf.c_ptr == (unsigned char *)0 || td->t_rbuf.c_count >= td->t_rbuf.c_size) { return; } i = td->t_rbuf.c_size-td->t_rbuf.c_count; /* compute byte count again */ cp = td->t_rbuf.c_ptr; /* point to first byte in string */ td->t_rbuf.c_count = td->t_rbuf.c_size; /* reset the length */ } for (;i>0; --i) { /* move all the chars */ int esc; if ((esc = td->t_state&CLESC) != 0) { /* remember whether this is escaped */ td->t_state &= ~CLESC; /* clear it for next time */ } c = *cp++; /* get a copy of the char */ if (esc == 0) { int quit,intr,swtch; quit = td->t_cc[VQUIT]; intr = td->t_cc[VINTR]; swtch = td->t_cc[VSWTCH]; if (c == quit || c == intr) { /* intr or quit? */ msg = (c == quit) ? tbp->ansi[ANSI_MSGQUIT] : tbp->ansi[ANSI_MSGINTR]; if ((td->t_lflag&NOFLSH) == 0) ttyflush(td,FWRITE|FREAD); while (*msg) putc(*msg++,&td->t_outq); cle_kickit(td); if (tbp->f_sleep_read) { tbp->f_sleep_read = 0; wakeup(tbp); } tbp->flags |= TB_FLUSHIT; signal(td->t_pgrp,(c == quit) ? SIGQUIT : SIGINT); /* signal an interrupt to process */ break; /* eat the rest of the input */ } if (c != 0 && c == swtch) { if ((*td->t_proc)(td,T_SWTCH) != T_SWTCH) { /* go to shl */ return; /* eat rest of input */ } } } if (c < 0x20 && tbp->keymap[c] == CLEFUN_PURGE) { ttyflush(td,FREAD); if (tbp->f_sleep_read) { tbp->flags |= TB_FLUSHIT; break; } } if (td->t_rawq.c_cc > 253 || putc(c,&td->t_rawq) == -1) { /* move the char */ tbp->flags |= TB_OVERUN; /* signal we got an overrun */ cle_putc(BEL,td); } else { if (esc == 0) { if (c < 0x20 && tbp->keymap[c] == CLEFUN_ESCAPE) { /* if this is an escape code */ td->t_state |= CLESC; /* signal last char is an escape */ } else if ( c != 0 && /* null is not a delimiter */ (c == td->t_cc[VEOL] || /* if user's spec'd delimiters */ c == td->t_cc[VEOL2] || c == td->t_cc[VEOF] || /* or an EOF char */ (c < 0x20 && tbp->keymap[c] == CLEFUN_NEWLINE))) { /* or mapped */ ++td->t_delct; /* count it so rdchk() works */ } } } } if (tbp->f_sleep_read) { tbp->f_sleep_read = 0; wakeup(tbp); } #ifdef M_UNIX if (td->t_state&IASLP) { /* if by some chance, we're turned on while */ ttiwake(td); /* LD 0 is reading, wake it up too */ } #endif return; } static int show_pid(disp,str,td) int disp; char *str; struct tty *td; { unsigned char tmp[10],*s; if (disp != 0) { cle_puts("\rcled version ",td); cle_puts(VERSION,td); } cle_puts(str,td); s = itoa(u.u_procp->p_pid,tmp,10); *s = 0; cle_puts(tmp,td); cle_puts(" (",td); s = itoa(u.u_procp->p_ppid,tmp,10); *s = 0; cle_puts(tmp,td); cle_puts(")\r\n",td); return; } /************************************************************************* * Line discipline IOCTL routine. */ cleioctl(td,f1,arg,mode) struct tty *td; int f1,mode; faddr_t arg; /* * At entry: * Process context: task. * td - ptr to tty struct * f1 - function to perform * At exit: * ioctl function is performed */ { struct tty_buf *tbp; struct led_buf *lb; tbp = find_ttybuf(td); /* see if we've a tty_buf assigned */ if (tbp != 0 && ((tbp->flags&(TB_READING|TB_WRITING)) != 0 || tbp->f_sleep_read != 0)) { cle_puts("\r\ncled warning: ioctl issued while terminal busy. stty bits may be zapped\r\n",td); cle_kickit(td); /* make sure output is running */ } if (f1 >= LDGETS) { /* if it's ours */ garbage_collect(tbp); /* free up some space */ if (tbp == 0) tbp = get_ttybuf(td); /* assign one if none present */ if (tbp == 0) { /* no free buffers */ u.u_error = ERR_NOTTYBUF; /* no free space error */ return; } #if MULTI_LB if ((lb=tbp->lbtop) != 0) { /* if there's a chain of led_bufs */ struct led_buf *us=0,*parent=0; do { if (u.u_procp->p_ppid == lb->pid) parent = lb; /* save parent's lb */ if (u.u_procp->p_pid == lb->pid) us = lb; /* save our lb */ } while ((lb=lb->next) != tbp->lbtop); if (us != 0) lb = us; /* use ours if we have one */ else if (parent != 0) lb = parent; /* use parent's if it has one */ else lb = 0; /* else there aren't any */ } #else lb = tbp->lbtop; #endif switch (f1) { struct set_key sk; case LDGETHB: { /* return history buffer (if present) */ if (lb == 0) { u.u_error = ERR_NOLBASS; return; } copyout(lb->old,arg,HISTBUFSIZ); return; } case LDGETBF: { /* return the keydef buffer */ char cnt,len; faddr_t outp; sk.modes = 0; if ((tbp->flags&TB_INSERT) != 0) { sk.modes |= CLEMODE_INSERT; } else { sk.modes |= CLEMODE_OVER; } if ((tbp->flags&TB_132) != 0) { sk.modes |= CLEMODE_132; } else { sk.modes |= CLEMODE_80; } sk.kdbuf_len = CLEKEY_MAX; /* gets all the keys */ copyout(tbp->keymap,arg+sizeof(sk),CLEKEY_MAX); outp = arg+sizeof(sk)+CLEKEY_MAX; for (cnt = 0;cnt < ANSI_COUNT; ++cnt) { char *s; copyout(&cnt,outp++,1); /* pass the string # */ s = tbp->ansi[cnt]; /* point to string */ while(*s++); /* skip to end */ len = s-tbp->ansi[cnt]; /* compute length including null */ copyout(tbp->ansi[cnt],outp,len); /* send it to user */ outp += len; /* move his pointer */ } sk.ansibuf_len = outp-(arg+sizeof(sk)+CLEKEY_MAX); copyout(&sk,arg,sizeof(sk)); return; } case LDSETBF: { /* set keys, modes and ansi strings */ int oldflag; copyin(arg,&sk,sizeof(sk)); oldflag = tbp->flags; if (sk.modes&CLEMODE_INSERT) tbp->flags |= TB_INSERT; else if (sk.modes&CLEMODE_OVER) tbp->flags &= ~TB_INSERT; if (sk.modes&CLEMODE_80) tbp->flags &= ~TB_132; else if (sk.modes&CLEMODE_132) tbp->flags |= TB_132; if (((oldflag^tbp->flags)&TB_132) != 0) { setcol_width(tbp->flags&TB_132,tbp); cle_kickit(tbp->ttyp); } if (sk.kdbuf_len > CLEKEY_MAX) { sk.kdbuf_len = CLEKEY_MAX; copyout(&sk,arg,sizeof(sk)); u.u_error = ERR_BADPARAM; return; } if (sk.kdbuf_len > 0) { #if _SPTALLOC unsigned char *tmp,*kp; #else unsigned char tmp[100],*kp; #endif int cnt,size; size = sk.kdbuf_len*2; #if _SPTALLOC kp = tmp = (unsigned char *)Sptalloc(size); #else if (size > sizeof(tmp)) { u.u_error = ERR_BADPARAM; return; } kp = tmp; #endif copyin(arg+sizeof(sk),tmp,size); for (cnt=0;cnt<sk.kdbuf_len;++cnt) { int key,func; key = *kp++; func = *kp++; if (key >= CLEKEY_MAX || func >= CLEFUN_MAX) { #if _SPTALLOC Sptfree(tmp,size); #endif sk.kdbuf_len = cnt; copyout(&sk,arg,sizeof(sk)); u.u_error = ERR_BADPARAM; return; } tbp->keymap[key] = func; } #if _SPTALLOC Sptfree(tmp,size); #endif } if (sk.ansibuf_len > 0) { /* setting some ansi defaults */ setup_ansi_defaults(tbp); /* reset all the defaults */ if (sk.ansibuf_len > 1) { /* if there's at least one string */ char *s; int nfg = 0; #if _SPTALLOC s = tbp->tmpbuf = (unsigned char *)Sptalloc(sk.ansibuf_len); #else s = tbp->tmpbuf; if (sk.ansibuf_len > ANSISIZE) { sk.ansibuf_len = ANSISIZE; copyout(&sk,arg,sizeof(sk)); u.u_error = ERR_BADPARAM; return; } #endif tbp->tmpsize = sk.ansibuf_len; copyin(arg+sizeof(sk)+sk.kdbuf_len*2,s,tbp->tmpsize); while (s < tbp->tmpbuf+tbp->tmpsize) { unsigned char *ap; int str; str = *s++; /* get string # */ if (str >= ANSI_COUNT) { /* if nfg */ nfg = 1; break; } ap = s; while (*ap && ap < tbp->tmpbuf+tbp->tmpsize) ++ap; if (*ap != 0) { nfg = 1; break; } tbp->ansi[str] = s; s = ap+1; } if (nfg) { sk.ansibuf_len = s - tbp->tmpbuf; copyout(&sk,arg,sizeof(sk)); u.u_error = ERR_BADPARAM; return; } } } return; } } } else { if (f1 == LDCLOSE) { /* if closing */ close_it(tbp,td); } else if (f1 == LDOPEN || f1 == LDCHG) { open_it(tbp,td); } (*linesw[0].l_ioctl)(td,f1,arg,mode); /* call ld 0 */ } cle_kickit(td); /* make sure output is running */ } /*************************************************************************** * Write some text to the terminal but catch any trailing data into a prompt * buffer. This routine is executed when no read is in progress on the * terminal, an lb buffer is assigned to the terminal and a write comes * through. */ static int catch_prompt(tbp,lb) struct tty_buf *tbp; struct led_buf *lb; /* * At entry: * tbp - ptr to tty_buf assigned to terminal * lb - ptr to led_buf assigned to terminal * u.u_base - ptr to message (u.u_count has length of message) * At exit: * the text from the trailing \n (if any) of the message has been copied to * the prompt buffer in the led_buf. If the last char of the message is * a \n, then prompt buffer is left empty. If there are no \n's in the * message, then the whole message is appended to any existing data in * the prompt buffer. Chars are removed from the beginning of the buffer * if the length of the new message exceeds the PRMPTBFSIZ parameter. */ { register unsigned char *dst,*src; register int len; int oldlen; unsigned char c,*temp; if (tbp->broadcast.c_cc != 0) { send_brdcst(tbp,1); /* send accum broadcast to terminal */ } copyin(u.u_base+u.u_count-1,&c,1); /* pickup the last byte */ if (c == '\n') { /* if last char is a \n */ lb->prmptsz = 0; /* stomp on any existing prompt */ lb->prmpt[0] = 0; /* make sure it is null terminated */ } else { /* else capture prompt */ #if _SPTALLOC unsigned char *temp; #else unsigned char temp[PROMPTBFSIZ]; #endif len = PROMPTBFSIZ-1; /* assume max length */ if (len > u.u_count) len = u.u_count; /* oops...not so much */ oldlen = len; #if _SPTALLOC temp = (unsigned char *)Sptalloc(oldlen+1); /* pick up some temp space */ #endif copyin(u.u_base+(u.u_count-len),temp,len); /* get user's data */ src = temp+len; /* point to end */ *src = 0; /* null terminate it */ for (;len > 0; --len) { /* look for cr/lf */ c = *--src; /* from the back to the front */ if (c == CR || c == LF) { ++src; /* found one, it stays with... */ break; /* ...old message */ } } if (len != 0 || oldlen == PROMPTBFSIZ-1) { /* if crlf's in input string... */ lb->prmptsz = 0; /* ...replace previous prompt */ } else { /* ...else glue new stuff on old */ if (oldlen+lb->prmptsz > PROMPTBFSIZ-1) { /* if new stuf won't fit */ len = (oldlen+lb->prmptsz)-(PROMPTBFSIZ-1); lb->prmptsz -= len; if (lb->prmptsz > 0) { /* move everybody left n places */ for (dst = lb->prmpt; *dst = *(dst+len); ++dst); } } } dst = lb->prmpt+lb->prmptsz; /* point to place for prompt */ while (*dst++ = *src++ ); /* copy in the string */ lb->prmptsz = dst-lb->prmpt-1; /* set the new length */ #if _SPTALLOC Sptfree(temp,oldlen+1); /* done with temp space */ #endif } } /*************************************************************************** * Breakthru. This routine is called when a message is to be sent to the * terminal while a read is in progress. The message is prefixed with a * \r<clear_to_eol> to make room on the current line for the new message * and all text up to and including the last \n is transmitted to the * terminal. Any text from the last \n to the end of the buffer is saved * in the broadcast clist which is transmitted either with the next * message to be written or when the read completes. In any case, the * refresh bit is set to cause the user's command line to be reprinted * after the write completes. */ static int breakthru(tbp) struct tty_buf *tbp; /* * At entry: * tbp - ptr to tty_buf * u.u_base - ptr to message to send to terminal * At exit: * user data is transmitted to the terminal */ { unsigned char last; int len; struct clist *bcl; bcl = &tbp->broadcast; /* ptr to broadcast clist */ copyin(u.u_base+u.u_count-1,&last,1); /* pickup the last byte */ if (last == '\n') { /* if msg ends in a nl */ if (bcl->c_cc > 0) { /* first dump anything we have */ send_brdcst(tbp,1); /* (preclearing the line) */ } else { cle_puts(tbp->ansi[ANSI_CLRLINE],tbp->ttyp); /* start with a fresh line */ } tbp->f_refresh = 1; /* and cause a refresh */ } else { /* otherwise, save it for later */ int len,oldlen; unsigned char *src,*dst; #if _SPTALLOC unsigned char *temp; #else unsigned char temp[PROMPTBFSIZ]; #endif len = 132; /* assume max length */ if (len > u.u_count) { /* user data is smaller than 1 line */ if (bcl->c_cc+u.u_count > len) { /* but would overflow */ send_brdcst(tbp,1); /* send accumulated text */ cle_puts("\r\n",tbp->ttyp); /* followed with a \r\n */ tbp->f_refresh = 1; /* reprint user's command */ } len = u.u_count; /* set length to user's */ } else { /* else userdata is longer */ if (bcl->c_cc > 0) { /* so send anything we currently have */ send_brdcst(tbp,1); } } oldlen = len; #if _SPTALLOC temp = (unsigned char *)Sptalloc(oldlen+1); /* pick up some temp space */ #endif copyin(u.u_base+(u.u_count-len),temp,len); /* get user's data */ src = temp+len; /* point to end */ *src = 0; /* null terminate it */ for (;len > 0; --len) { /* look for cr/lf */ unsigned char c; c = *--src; /* from the back to the front */ if (c == CR || c == LF) { ++src; /* found one, it stays with... */ break; /* ...old message */ } } len = oldlen-len; /* compute real length of message */ if (bcl->c_cl != 0) { /* if the clist is not empty */ int i; struct cblock *cbkp; cbkp = bcl->c_cl; i = CLSIZE-cbkp->c_last; /* room in last cblock */ if (i > 0) { dst = &cbkp->c_data[cbkp->c_last]; if (i > len) i = len; /* maximize it */ len -= i; /* take from our count */ u.u_count -= i; /* take from users' count */ bcl->c_cc += i; /* bump size */ cbkp->c_last += i; /* move end ptr */ while (i-- > 0) *dst++ = *src++; /* put text at end of last cblock */ } } if (len > 0) { /* if there's any text left */ int ospl; struct clist tcl; @//E*O*F cledab// chmod u=rw,g=r,o=r cledab echo Inspecting for damage in transit... temp=/tmp/shar$$; dtemp=/tmp/.shar$$ trap "rm -f $temp $dtemp; exit" 0 1 2 3 15 cat > $temp <<\!!! 1500 7617 49699 cledab !!! wc cledab | sed 's=[^ ]*/==' | diff -b $temp - >$dtemp if [ -s $dtemp ] then echo "Ouch [diff of wc output]:" ; cat $dtemp else echo "No problems found." fi exit 0 -- Dave Shepperd. shepperd@dms.UUCP or motcsd!dms!shepperd Atari Games Corporation, 675 Sycamore Drive, Milpitas CA 95035. Nobody knows what I'm saying. I don't even know what I'm saying.
pjh@mccc.uucp (Pete Holsberg) (11/11/89)
Dave, 3 and 4 made it here but 1 and 2 didn't. If that's true for other sites, could you repost them? Thanks. -- Pete Holsberg UUCP: {...!rutgers!}princeton!mccc!pjh Mercer College CompuServe: 70240,334 1200 Old Trenton Road GEnie: PJHOLSBERG Trenton, NJ 08690 Voice: 1-609-586-4800
williams@cs.umass.edu (11/12/89)
In article <1989Nov11.031013.12665@mccc.uucp>, pjh@mccc.uucp (Pete Holsberg) writes... > >Dave, > 3 and 4 made it here but 1 and 2 didn't. If that's true for >other sites, could you repost them? Thanks. >-- >Pete Holsberg UUCP: {...!rutgers!}princeton!mccc!pjh >Mercer College CompuServe: 70240,334 >1200 Old Trenton Road GEnie: PJHOLSBERG >Trenton, NJ 08690 Voice: 1-609-586-4800 We got them all. Unless there are LOTS of people who said they missed parts, please email them instead of reposting!