1 /***********************************************************************
2 * *
3 * This software is part of the ast package *
4 * Copyright (c) 1984-2011 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Eclipse Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
8 * *
9 * A copy of the License is available at *
10 * http://www.eclipse.org/org/documents/epl-v10.html *
11 * (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12 * *
13 * Information and Software Systems Research *
14 * AT&T Research *
15 * Florham Park NJ *
16 * *
17 * David Korn <dgk@research.att.com> *
18 * Pat Sullivan *
19 * *
20 ***********************************************************************/
21 /*
22 * edit.c - common routines for vi and emacs one line editors in shell
23 *
24 * David Korn P.D. Sullivan
25 * AT&T Bell Laboratories AT&T Bell Laboratories
26 * Room 3C-526B Room 1B-286
27 * Murray Hill, N. J. 07974 Columbus, OH 43213
28 * Tel. x7975 Tel. x 2655
29 *
30 * Coded April 1983.
31 */
32
33 #ifdef KSHELL
34 # include "defs.h"
35 # include "terminal.h"
36 # include "builtins.h"
37 # include "sym.h"
38 #else
39 # include "io.h"
40 # include "terminal.h"
41 # undef SIG_NORESTART
42 # define SIG_NORESTART 1
43 # define _sobuf ed_errbuf
44 extern char ed_errbuf[];
45 const char e_version[] = "\n@(#)$Id: edit library (AT&T Research) 1988-11-16 i $\0\n";
46 #endif /* KSHELL */
47 #include "history.h"
48 #include "edit.h"
49
50 #include <error.h>
51
52 #define BAD -1
53 #define GOOD 0
54 #define SYSERR -1
55
56 #ifdef OLDTERMIO
57 # undef tcgetattr
58 # undef tcsetattr
59 #endif /* OLDTERMIO */
60
61 #ifdef RT
62 # define VENIX 1
63 #endif /* RT */
64
65 #define lookahead editb.e_index
66 #define env editb.e_env
67 #define previous editb.e_lbuf
68 #define fildes editb.e_fd
69 #define in_raw editb.e_addnl
70
71
72 #ifdef _hdr_sgtty
73 # ifdef TIOCGETP
74 static int l_mask;
75 static struct tchars l_ttychars;
76 static struct ltchars l_chars;
77 static char l_changed; /* set if mode bits changed */
78 # define L_CHARS 4
79 # define T_CHARS 2
80 # define L_MASK 1
81 # endif /* TIOCGETP */
82 #endif /* _hdr_sgtty */
83
84 #ifndef IODELAY
85 # undef _SELECT5_
86 #endif /* IODELAY */
87 #ifdef _SELECT5_
88 # ifndef included_sys_time
89 # define included_sys_time 1
90 # include <sys/time.h>
91 # endif /* included_sys_time */
92 static int delay;
93 # ifndef KSHELL
94 int tty_speeds[] = {0, 50, 75, 110, 134, 150, 200, 300,
95 600,1200,1800,2400,9600,19200,0};
96 # endif /* KSHELL */
97 #endif /* _SELECT5_ */
98
99 #ifdef KSHELL
100 extern char *sh_tilde();
101 static char macro[] = "_??";
102 # define slowsig() (sh.trapnote&SIGSLOW)
103 #else
104 struct edit editb = { 0 };
105 # define slowsig() (0)
106 #endif /* KSHELL */
107
108
109 static struct termios savetty;
110 static int savefd = -1;
111 #ifdef future
112 static int compare();
113 #endif
114 #if VSH || ESH
115 static struct termios ttyparm; /* initial tty parameters */
116 static struct termios nttyparm; /* raw tty parameters */
117 static char bellchr[] = "\7"; /* bell char */
118 # define tenex 1
119 # ifdef tenex
120 static char *overlay();
121 # endif /* tenex */
122 #endif /* VSH || ESH */
123
124
125 /*
126 * This routine returns true if fd refers to a terminal
127 * This should be equivalent to isatty
128 */
129
tty_check(fd)130 int tty_check(fd)
131 int fd;
132 {
133 savefd = -1;
134 return(tty_get(fd,(struct termios*)0)==0);
135 }
136
137 /*
138 * Get the current terminal attributes
139 * This routine remembers the attributes and just returns them if it
140 * is called again without an intervening tty_set()
141 */
142
tty_get(fd,tty)143 int tty_get(fd, tty)
144 int fd;
145 struct termios *tty;
146 {
147 if(fd != savefd)
148 {
149 #ifndef SIG_NORESTART
150 VOID (*savint)() = st.intfn;
151 st.intfn = 0;
152 #endif /* SIG_NORESTART */
153 while(tcgetattr(fd,&savetty) == SYSERR)
154 {
155 if(errno !=EINTR)
156 {
157 #ifndef SIG_NORESTART
158 st.intfn = savint;
159 #endif /* SIG_NORESTART */
160 return(SYSERR);
161 }
162 errno = 0;
163 }
164 #ifndef SIG_NORESTART
165 st.intfn = savint;
166 #endif /* SIG_NORESTART */
167 savefd = fd;
168 }
169 if(tty)
170 *tty = savetty;
171 return(0);
172 }
173
174 /*
175 * Set the terminal attributes
176 * If fd<0, then current attributes are invalidated
177 */
178
179 /* VARARGS 2 */
tty_set(fd,action,tty)180 int tty_set(fd, action, tty)
181 int fd, action;
182 struct termios *tty;
183 {
184 if(fd >=0)
185 {
186 #ifndef SIG_NORESTART
187 VOID (*savint)() = st.intfn;
188 #endif /* SIG_NORESTART */
189 #ifdef future
190 if(savefd>=0 && compare(&savetty,tty,sizeof(struct termios)))
191 return(0);
192 #endif
193 #ifndef SIG_NORESTART
194 st.intfn = 0;
195 #endif /* SIG_NORESTART */
196 while(tcsetattr(fd, action, tty) == SYSERR)
197 {
198 if(errno !=EINTR)
199 {
200 #ifndef SIG_NORESTART
201 st.intfn = savint;
202 #endif /* SIG_NORESTART */
203 return(SYSERR);
204 }
205 errno = 0;
206 }
207 #ifndef SIG_NORESTART
208 st.intfn = savint;
209 #endif /* SIG_NORESTART */
210 savetty = *tty;
211 }
212 savefd = fd;
213 return(0);
214 }
215
216 #if ESH || VSH
217 /*{ TTY_COOKED( fd )
218 *
219 * This routine will set the tty in cooked mode.
220 * It is also called by error.done().
221 *
222 }*/
223
tty_cooked(fd)224 void tty_cooked(fd)
225 register int fd;
226 {
227
228 if(editb.e_raw==0)
229 return;
230 if(fd < 0)
231 fd = savefd;
232 #ifdef L_MASK
233 /* restore flags */
234 if(l_changed&L_MASK)
235 ioctl(fd,TIOCLSET,&l_mask);
236 if(l_changed&T_CHARS)
237 /* restore alternate break character */
238 ioctl(fd,TIOCSETC,&l_ttychars);
239 if(l_changed&L_CHARS)
240 /* restore alternate break character */
241 ioctl(fd,TIOCSLTC,&l_chars);
242 l_changed = 0;
243 #endif /* L_MASK */
244 /*** don't do tty_set unless ttyparm has valid data ***/
245 if(savefd<0 || tty_set(fd, TCSANOW, &ttyparm) == SYSERR)
246 return;
247 editb.e_raw = 0;
248 return;
249 }
250
251 /*{ TTY_RAW( fd )
252 *
253 * This routine will set the tty in raw mode.
254 *
255 }*/
256
tty_raw(fd)257 int tty_raw(fd)
258 register int fd;
259 {
260 #ifdef L_MASK
261 struct ltchars lchars;
262 #endif /* L_MASK */
263 if(editb.e_raw==RAWMODE)
264 return(GOOD);
265 #ifndef RAWONLY
266 if(editb.e_raw != ALTMODE)
267 #endif /* RAWONLY */
268 {
269 if(tty_get(fd,&ttyparm) == SYSERR)
270 return(BAD);
271 }
272 #if L_MASK || VENIX
273 if(!(ttyparm.sg_flags&ECHO) || (ttyparm.sg_flags&LCASE))
274 return(BAD);
275 nttyparm = ttyparm;
276 nttyparm.sg_flags &= ~(ECHO | TBDELAY);
277 # ifdef CBREAK
278 nttyparm.sg_flags |= CBREAK;
279 # else
280 nttyparm.sg_flags |= RAW;
281 # endif /* CBREAK */
282 editb.e_erase = ttyparm.sg_erase;
283 editb.e_kill = ttyparm.sg_kill;
284 editb.e_eof = cntl('D');
285 if( tty_set(fd, TCSADRAIN, &nttyparm) == SYSERR )
286 return(BAD);
287 editb.e_ttyspeed = (ttyparm.sg_ospeed>=B1200?FAST:SLOW);
288 # ifdef _SELECT5_
289 delay = tty_speeds[ttyparm.sg_ospeed];
290 # endif /* _SELECT5_ */
291 # ifdef TIOCGLTC
292 /* try to remove effect of ^V and ^Y and ^O */
293 if(ioctl(fd,TIOCGLTC,&l_chars) != SYSERR)
294 {
295 lchars = l_chars;
296 lchars.t_lnextc = -1;
297 lchars.t_flushc = -1;
298 lchars.t_dsuspc = -1; /* no delayed stop process signal */
299 if(ioctl(fd,TIOCSLTC,&lchars) != SYSERR)
300 l_changed |= L_CHARS;
301 }
302 # endif /* TIOCGLTC */
303 #else
304
305 if (!(ttyparm.c_lflag & ECHO ))
306 return(BAD);
307
308 # ifdef FLUSHO
309 ttyparm.c_lflag &= ~FLUSHO;
310 # endif /* FLUSHO */
311 nttyparm = ttyparm;
312 # ifndef u370
313 nttyparm.c_iflag &= ~(IGNPAR|PARMRK|INLCR|IGNCR|ICRNL);
314 nttyparm.c_iflag |= BRKINT;
315 # else
316 nttyparm.c_iflag &=
317 ~(IGNBRK|PARMRK|INLCR|IGNCR|ICRNL|INPCK);
318 nttyparm.c_iflag |= (BRKINT|IGNPAR);
319 # endif /* u370 */
320 nttyparm.c_lflag &= ~(ICANON|ECHO|ECHOK);
321 nttyparm.c_cc[VTIME] = 0;
322 nttyparm.c_cc[VMIN] = 1;
323 # ifdef VDISCARD
324 nttyparm.c_cc[VDISCARD] = 0;
325 # endif /* VDISCARD */
326 # ifdef VWERASE
327 nttyparm.c_cc[VWERASE] = 0;
328 # endif /* VWERASE */
329 # ifdef VLNEXT
330 nttyparm.c_cc[VLNEXT] = 0;
331 # endif /* VLNEXT */
332 editb.e_eof = ttyparm.c_cc[VEOF];
333 editb.e_erase = ttyparm.c_cc[VERASE];
334 editb.e_kill = ttyparm.c_cc[VKILL];
335 if( tty_set(fd, TCSADRAIN, &nttyparm) == SYSERR )
336 return(BAD);
337 editb.e_ttyspeed = (cfgetospeed(&ttyparm)>=B1200?FAST:SLOW);
338 #endif
339 editb.e_raw = RAWMODE;
340 return(GOOD);
341 }
342
343 #ifndef RAWONLY
344
345 /*
346 *
347 * Get tty parameters and make ESC and '\r' wakeup characters.
348 *
349 */
350
351 # ifdef TIOCGETC
tty_alt(fd)352 int tty_alt(fd)
353 register int fd;
354 {
355 int mask;
356 struct tchars ttychars;
357 if(editb.e_raw==ALTMODE)
358 return(GOOD);
359 if(editb.e_raw==RAWMODE)
360 tty_cooked(fd);
361 l_changed = 0;
362 if( editb.e_ttyspeed == 0)
363 {
364 if((tty_get(fd,&ttyparm) != SYSERR))
365 editb.e_ttyspeed = (ttyparm.sg_ospeed>=B1200?FAST:SLOW);
366 editb.e_raw = ALTMODE;
367 }
368 if(ioctl(fd,TIOCGETC,&l_ttychars) == SYSERR)
369 return(BAD);
370 if(ioctl(fd,TIOCLGET,&l_mask)==SYSERR)
371 return(BAD);
372 ttychars = l_ttychars;
373 mask = LCRTBS|LCRTERA|LCTLECH|LPENDIN|LCRTKIL;
374 if((l_mask|mask) != l_mask)
375 l_changed = L_MASK;
376 if(ioctl(fd,TIOCLBIS,&mask)==SYSERR)
377 return(BAD);
378 if(ttychars.t_brkc!=ESC)
379 {
380 ttychars.t_brkc = ESC;
381 l_changed |= T_CHARS;
382 if(ioctl(fd,TIOCSETC,&ttychars) == SYSERR)
383 return(BAD);
384 }
385 return(GOOD);
386 }
387 # else
388 # ifndef PENDIN
389 # define PENDIN 0
390 # endif /* PENDIN */
391 # ifndef IEXTEN
392 # define IEXTEN 0
393 # endif /* IEXTEN */
tty_alt(fd)394 int tty_alt(fd)
395 register int fd;
396 {
397 if(editb.e_raw==ALTMODE)
398 return(GOOD);
399 if(editb.e_raw==RAWMODE)
400 tty_cooked(fd);
401 if((tty_get(fd, &ttyparm)==SYSERR) || (!(ttyparm.c_lflag&ECHO)))
402 return(BAD);
403 # ifdef FLUSHO
404 ttyparm.c_lflag &= ~FLUSHO;
405 # endif /* FLUSHO */
406 nttyparm = ttyparm;
407 editb.e_eof = ttyparm.c_cc[VEOF];
408 # ifdef ECHOCTL
409 /* escape character echos as ^[ */
410 nttyparm.c_lflag |= (ECHOE|ECHOK|ECHOCTL|PENDIN|IEXTEN);
411 nttyparm.c_cc[VEOL2] = ESC;
412 # else
413 /* switch VEOL2 and EOF, since EOF isn't echo'd by driver */
414 nttyparm.c_iflag &= ~(IGNCR|ICRNL);
415 nttyparm.c_iflag |= INLCR;
416 nttyparm.c_lflag |= (ECHOE|ECHOK);
417 nttyparm.c_cc[VEOF] = ESC; /* make ESC the eof char */
418 nttyparm.c_cc[VEOL] = '\r'; /* make CR an eol char */
419 nttyparm.c_cc[VEOL2] = editb.e_eof; /* make EOF an eol char */
420 # endif /* ECHOCTL */
421 # ifdef VWERASE
422 nttyparm.c_cc[VWERASE] = cntl('W');
423 # endif /* VWERASE */
424 # ifdef VLNEXT
425 nttyparm.c_cc[VLNEXT] = cntl('V');
426 # endif /* VLNEXT */
427 editb.e_erase = ttyparm.c_cc[VERASE];
428 editb.e_kill = ttyparm.c_cc[VKILL];
429 if( tty_set(fd, TCSADRAIN, &nttyparm) == SYSERR )
430 return(BAD);
431 editb.e_ttyspeed = (cfgetospeed(&ttyparm)>=B1200?FAST:SLOW);
432 editb.e_raw = ALTMODE;
433 return(GOOD);
434 }
435
436 # endif /* TIOCGETC */
437 #endif /* RAWONLY */
438
439 /*
440 * ED_WINDOW()
441 *
442 * return the window size
443 */
444
445 #ifdef _sys_stream
446 # include <sys/stream.h>
447 #endif /* _sys_stream */
448 #ifdef _sys_ptem
449 # include <sys/ptem.h>
450 #endif /* _sys_ptem */
451 #ifdef _sys_jioctl
452 # include <sys/jioctl.h>
453 # define winsize jwinsize
454 # define ws_col bytesx
455 # ifdef TIOCGWINSZ
456 # undef TIOCGWINSZ
457 # endif /* TIOCGWINSZ */
458 # define TIOCGWINSZ JWINSIZE
459 #endif /* _sys_jioctl */
460
ed_window()461 int ed_window()
462 {
463 register int n = DFLTWINDOW-1;
464 register char *cp = nam_strval(COLUMNS);
465 if(cp)
466 {
467 n = (int)strtol(cp, (char**)0, 10)-1;
468 if(n > MAXWINDOW)
469 n = MAXWINDOW;
470 }
471 #ifdef TIOCGWINSZ
472 else
473 {
474 /* for 5620's and 630's */
475 struct winsize size;
476 if (ioctl(ERRIO, TIOCGWINSZ, &size) != -1)
477 if(size.ws_col > 0)
478 n = size.ws_col - 1;
479 }
480 #endif /*TIOCGWINSZ */
481 if(n < MINWINDOW)
482 n = MINWINDOW;
483 return(n);
484 }
485
486 /* E_FLUSH()
487 *
488 * Flush the output buffer.
489 *
490 */
491
ed_flush()492 void ed_flush()
493 {
494 register int n = editb.e_outptr-editb.e_outbase;
495 register int fd = ERRIO;
496 if(n<=0)
497 return;
498 write(fd,editb.e_outbase,(unsigned)n);
499 editb.e_outptr = editb.e_outbase;
500 #ifdef _SELECT5_
501 if(delay && n > delay/100)
502 {
503 /* delay until output drains */
504 struct timeval timeloc;
505 n *= 10;
506 timeloc.tv_sec = n/delay;
507 timeloc.tv_usec = (1000000*(n%delay))/delay;
508 select(0,(fd_set*)0,(fd_set*)0,(fd_set*)0,&timeloc);
509 }
510 #else
511 # ifdef IODELAY
512 if(editb.e_raw==RAWMODE && n > 16)
513 tty_set(fd, TCSADRAIN, &nttyparm);
514 # endif /* IODELAY */
515 #endif /* _SELECT5_ */
516 }
517
518 /*
519 * send the bell character ^G to the terminal
520 */
521
ed_ringbell()522 void ed_ringbell()
523 {
524 write(ERRIO,bellchr,1);
525 }
526
527 /*
528 * send a carriage return line feed to the terminal
529 */
530
ed_crlf()531 void ed_crlf()
532 {
533 #ifdef cray
534 ed_putchar('\r');
535 #endif /* cray */
536 #ifdef u370
537 ed_putchar('\r');
538 #endif /* u370 */
539 #ifdef VENIX
540 ed_putchar('\r');
541 #endif /* VENIX */
542 ed_putchar('\n');
543 ed_flush();
544 }
545
546 /* E_SETUP( max_prompt_size )
547 *
548 * This routine sets up the prompt string
549 * The following is an unadvertised feature.
550 * Escape sequences in the prompt can be excluded from the calculated
551 * prompt length. This is accomplished as follows:
552 * - if the prompt string starts with "%\r, or contains \r%\r", where %
553 * represents any char, then % is taken to be the quote character.
554 * - strings enclosed by this quote character, and the quote character,
555 * are not counted as part of the prompt length.
556 */
557
ed_setup(fd)558 void ed_setup(fd)
559 int fd;
560 {
561 register char *pp;
562 register char *last;
563 char *ppmax;
564 int myquote = 0;
565 int qlen = 1;
566 char inquote = 0;
567 editb.e_fd = fd;
568 p_setout(ERRIO);
569 #ifdef KSHELL
570 last = _sobuf;
571 #else
572 last = editb.e_prbuff;
573 #endif /* KSHELL */
574 if(hist_ptr)
575 {
576 register struct history *fp = hist_ptr;
577 editb.e_hismax = fp->fixind;
578 editb.e_hloff = 0;
579 editb.e_hismin = fp->fixind-fp->fixmax;
580 if(editb.e_hismin<0)
581 editb.e_hismin = 0;
582 }
583 else
584 {
585 editb.e_hismax = editb.e_hismin = editb.e_hloff = 0;
586 }
587 editb.e_hline = editb.e_hismax;
588 editb.e_wsize = ed_window()-2;
589 editb.e_crlf = (*last?YES:NO);
590 pp = editb.e_prompt;
591 ppmax = pp+PRSIZE-1;
592 *pp++ = '\r';
593 {
594 register int c;
595 while(c= *last++) switch(c)
596 {
597 case '\r':
598 if(pp == (editb.e_prompt+2)) /* quote char */
599 myquote = *(pp-1);
600 /*FALLTHROUGH*/
601
602 case '\n':
603 /* start again */
604 editb.e_crlf = YES;
605 qlen = 1;
606 inquote = 0;
607 pp = editb.e_prompt+1;
608 break;
609
610 case '\t':
611 /* expand tabs */
612 while((pp-editb.e_prompt)%TABSIZE)
613 {
614 if(pp >= ppmax)
615 break;
616 *pp++ = ' ';
617 }
618 break;
619
620 case BELL:
621 /* cut out bells */
622 break;
623
624 default:
625 if(c==myquote)
626 {
627 qlen += inquote;
628 inquote ^= 1;
629 }
630 if(pp < ppmax)
631 {
632 qlen += inquote;
633 *pp++ = c;
634 if(!inquote && !isprint(c))
635 editb.e_crlf = NO;
636 }
637 }
638 }
639 editb.e_plen = pp - editb.e_prompt - qlen;
640 *pp = 0;
641 if((editb.e_wsize -= editb.e_plen) < 7)
642 {
643 register int shift = 7-editb.e_wsize;
644 editb.e_wsize = 7;
645 pp = editb.e_prompt+1;
646 strcpy(pp,pp+shift);
647 editb.e_plen -= shift;
648 last[-editb.e_plen-2] = '\r';
649 }
650 p_flush();
651 editb.e_outptr = _sobuf;
652 editb.e_outbase = editb.e_outptr;
653 editb.e_outlast = editb.e_outptr + IOBSIZE-3;
654 }
655
656 #ifdef KSHELL
657 /*
658 * look for edit macro named _i
659 * if found, puts the macro definition into lookahead buffer and returns 1
660 */
661
ed_macro(i)662 ed_macro(i)
663 register int i;
664 {
665 register char *out;
666 struct namnod *np;
667 genchar buff[LOOKAHEAD+1];
668 if(i != '@')
669 macro[1] = i;
670 /* undocumented feature, macros of the form <ESC>[c evoke alias __c */
671 if(i=='_')
672 macro[2] = ed_getchar();
673 else
674 macro[2] = 0;
675 if (isalnum(i)&&(np=nam_search(macro,sh.alias_tree,N_NOSCOPE))&&(out=nam_strval(np)))
676 {
677 #ifdef MULTIBYTE
678 /* copy to buff in internal representation */
679 int c = out[LOOKAHEAD];
680 out[LOOKAHEAD] = 0;
681 i = ed_internal(out,buff);
682 out[LOOKAHEAD] = c;
683 #else
684 strncpy((char*)buff,out,LOOKAHEAD);
685 i = strlen((char*)buff);
686 #endif /* MULTIBYTE */
687 while(i-- > 0)
688 ed_ungetchar(buff[i]);
689 return(1);
690 }
691 return(0);
692 }
693 /*
694 * file name generation for edit modes
695 * non-zero exit for error, <0 ring bell
696 * don't search back past beginning of the buffer
697 * mode is '*' for inline expansion,
698 * mode is '\' for filename completion
699 * mode is '=' cause files to be listed in select format
700 */
701
ed_expand(outbuff,cur,eol,mode)702 ed_expand(outbuff,cur,eol,mode)
703 char outbuff[];
704 int *cur;
705 int *eol;
706 int mode;
707 {
708 int offset = staktell();
709 char *staksav = stakptr(0);
710 struct comnod *comptr = (struct comnod*)stakalloc(sizeof(struct comnod));
711 struct argnod *ap = (struct argnod*)stakseek(ARGVAL);
712 register char *out;
713 char *begin;
714 int addstar;
715 int istilde = 0;
716 int rval = 0;
717 int strip;
718 optflag savflags = opt_flags;
719 #ifdef MULTIBYTE
720 {
721 register int c = *cur;
722 register genchar *cp;
723 /* adjust cur */
724 cp = (genchar *)outbuff + *cur;
725 c = *cp;
726 *cp = 0;
727 *cur = ed_external((genchar*)outbuff,(char*)stakptr(0));
728 *cp = c;
729 *eol = ed_external((genchar*)outbuff,outbuff);
730 }
731 #endif /* MULTIBYTE */
732 out = outbuff + *cur;
733 comptr->comtyp = COMSCAN;
734 comptr->comarg = ap;
735 ap->argflag = (A_MAC|A_EXP);
736 ap->argnxt.ap = 0;
737 {
738 register int c;
739 int chktilde;
740 char *cp;
741 if(out>outbuff)
742 {
743 /* go to beginning of word */
744 do
745 {
746 out--;
747 c = *(unsigned char*)out;
748 }
749 while(out>outbuff && !isqmeta(c));
750 /* copy word into arg */
751 if(isqmeta(c))
752 out++;
753 }
754 else
755 out = outbuff;
756 begin = out;
757 chktilde = (*out=='~');
758 /* addstar set to zero if * should not be added */
759 addstar = '*';
760 strip = 1;
761 /* copy word to arg and do ~ expansion */
762 do
763 {
764 c = *(unsigned char*)out;
765 if(isexp(c))
766 addstar = 0;
767 if ((c == '/') && (addstar == 0))
768 strip = 0;
769 stakputc(c);
770 if(chktilde && (c==0 || c == '/'))
771 {
772 chktilde=0;
773 *out = 0;
774 if(cp=sh_tilde(begin))
775 {
776 istilde++;
777 stakseek(ARGVAL);
778 stakputs(cp);
779 stakputc(c);
780 if(c==0)
781 {
782 addstar = 0;
783 strip = 0;
784 }
785 }
786 *out = c;
787 }
788 out++;
789 } while (c && !isqmeta(c));
790
791 out--;
792 #ifdef tenex
793 if(mode=='\\')
794 addstar = '*';
795 #endif /* tenex */
796 *stakptr(staktell()-1) = addstar;
797 stakfreeze(1);
798 }
799 if(mode!='*')
800 on_option(MARKDIR);
801 {
802 register char **com;
803 int narg;
804 register int size;
805 VOID (*savfn)();
806 savfn = st.intfn;
807 com = arg_build(&narg,comptr);
808 st.intfn = savfn;
809 /* match? */
810 if (*com==0 || (!istilde && narg <= 1 && eq(ap->argval,*com)))
811 {
812 rval = -1;
813 goto done;
814 }
815 if(mode=='=')
816 {
817 if (strip)
818 {
819 register char **ptrcom;
820 for(ptrcom=com;*ptrcom;ptrcom++)
821 /* trim directory prefix */
822 *ptrcom = path_basename(*ptrcom);
823 }
824 p_setout(ERRIO);
825 newline();
826 p_list(narg,com);
827 p_flush();
828 goto done;
829 }
830 /* see if there is enough room */
831 size = *eol - (out-begin);
832 #ifdef tenex
833 if(mode=='\\')
834 {
835 /* just expand until name is unique */
836 size += strlen(*com);
837 }
838 else
839 #endif
840 {
841 size += narg;
842 {
843 char **savcom = com;
844 while (*com)
845 size += strlen(*com++);
846 com = savcom;
847 }
848 }
849 /* see if room for expansion */
850 if(outbuff+size >= &outbuff[MAXLINE])
851 {
852 com[0] = ap->argval;
853 com[1] = 0;
854 }
855 /* save remainder of the buffer */
856 strcpy(stakptr(0),out);
857 out = sh_copy(*com++, begin);
858 #ifdef tenex
859 if(mode=='\\')
860 {
861 if(*com==0 && out[-1]!='/')
862 *out++ = ' ';
863 while (*com && *begin)
864 out = overlay(begin,*com++);
865 if(*begin==0)
866 ed_ringbell();
867 }
868 else
869 #endif
870 while (*com)
871 {
872 *out++ = ' ';
873 out = sh_copy(*com++,out);
874 }
875 *cur = (out-outbuff);
876 /* restore rest of buffer */
877 out = sh_copy(stakptr(0),out);
878 *eol = (out-outbuff);
879 }
880 done:
881 stakset(staksav,offset);
882 opt_flags = savflags;
883 #ifdef MULTIBYTE
884 {
885 register int c;
886 /* first re-adjust cur */
887 out = outbuff + *cur;
888 c = *out;
889 *out = 0;
890 *cur = ed_internal(outbuff,(genchar*)stakptr(0));
891 *out = c;
892 outbuff[*eol+1] = 0;
893 *eol = ed_internal(outbuff,(genchar*)outbuff);
894 }
895 #endif /* MULTIBYTE */
896 return(rval);
897 }
898
899 # ifdef tenex
overlay(str,newstr)900 static char *overlay(str,newstr)
901 register char *str,*newstr;
902 {
903 while(*str && *str == *newstr++)
904 str++;
905 *str = 0;
906 return(str);
907 }
908 # endif
909
910 /*
911 * Enter the fc command on the current history line
912 */
ed_fulledit()913 ed_fulledit()
914 {
915 register char *cp;
916 if(!hist_ptr || (st.states&BUILTIN))
917 return(BAD);
918 /* use EDITOR on current command */
919 if(editb.e_hline == editb.e_hismax)
920 {
921 if(editb.e_eol<=0)
922 return(BAD);
923 editb.e_inbuf[editb.e_eol+1] = 0;
924 p_setout(hist_ptr->fixfd);
925 p_str((char*)editb.e_inbuf,0);
926 st.states |= FIXFLG;
927 hist_flush();
928 }
929 cp = sh_copy(e_runvi, (char*)editb.e_inbuf);
930 cp = sh_copy(sh_itos(editb.e_hline), cp);
931 editb.e_eol = (unsigned char*)cp - (unsigned char*)editb.e_inbuf;
932 return(GOOD);
933 }
934 #endif /* KSHELL */
935
936
937 /*
938 * routine to perform read from terminal for vi and emacs mode
939 */
940
941
942 int
ed_getchar()943 ed_getchar()
944 {
945 register int i;
946 register int c;
947 register int maxtry = MAXTRY;
948 unsigned nchar = READAHEAD; /* number of characters to read at a time */
949 #ifdef MULTIBYTE
950 static int curchar;
951 static int cursize;
952 #endif /* MULTIBYTE */
953 char readin[LOOKAHEAD] ;
954 if (lookahead)
955 {
956 c = previous[--lookahead];
957 /*** map '\r' to '\n' ***/
958 if(c == '\r' && !in_raw)
959 c = '\n';
960 return(c);
961 }
962
963 ed_flush() ;
964 /*
965 * you can't chance read ahead at the end of line
966 * or when the input is a pipe
967 */
968 #ifdef KSHELL
969 if((editb.e_cur>=editb.e_eol) || fnobuff(io_ftable[fildes]))
970 #else
971 if(editb.e_cur>=editb.e_eol)
972 #endif /* KSHELL */
973 nchar = 1;
974 /* Set 'i' to indicate read failed, in case intr set */
975 #ifdef MULTIBYTE
976 retry:
977 #endif /* MULTIBYTE */
978 i = -1;
979 errno = 0;
980 editb.e_inmacro = 0;
981 while(slowsig()==0 && maxtry--)
982 {
983 errno=0;
984 if ((i = read(fildes,readin, nchar)) != -1)
985 break;
986 }
987 #ifdef MULTIBYTE
988 lookahead = maxtry = i;
989 i = 0;
990 while (i < maxtry)
991 {
992 c = readin[i++] & STRIP;
993 next:
994 if(cursize-- > 0)
995 {
996 curchar = (curchar<<7) | (c&~HIGHBIT);
997 if(cursize==0)
998 {
999 c = curchar;
1000 goto gotit;
1001 }
1002 else if(i>=maxtry)
1003 goto retry;
1004 continue;
1005 }
1006 else if(curchar = echarset(c))
1007 {
1008 cursize = in_csize(curchar);
1009 if(curchar != 1)
1010 c = 0;
1011 curchar <<= 7*(ESS_MAXCHAR-cursize);
1012 if(c)
1013 goto next;
1014 else if(i>=maxtry)
1015 goto retry;
1016 continue;
1017 }
1018 gotit:
1019 previous[--lookahead] = c;
1020 #else
1021 while (i > 0)
1022 {
1023 c = readin[--i] & STRIP;
1024 previous[lookahead++] = c;
1025 #endif /* MULTIBYTE */
1026 #ifndef CBREAK
1027 if( c == '\0' )
1028 {
1029 /*** user break key ***/
1030 lookahead = 0;
1031 # ifdef KSHELL
1032 sh_fault(SIGINT);
1033 LONGJMP(env, UINTR);
1034 # endif /* KSHELL */
1035 }
1036 #endif /* !CBREAK */
1037 }
1038 #ifdef MULTIBYTE
1039 /* shift lookahead buffer if necessary */
1040 if(lookahead)
1041 {
1042 for(i=lookahead;i < maxtry;i++)
1043 previous[i-lookahead] = previous[i];
1044 }
1045 lookahead = maxtry-lookahead;
1046 #endif /* MULTIBYTE */
1047 if (lookahead > 0)
1048 return(ed_getchar());
1049 LONGJMP(env,(i==0?UEOF:UINTR)); /* What a mess! Give up */
1050 return(0);
1051 /* NOTREACHED */
1052 }
1053
1054 void ed_ungetchar(c)
1055 register int c;
1056 {
1057 if (lookahead < LOOKAHEAD)
1058 previous[lookahead++] = c;
1059 return;
1060 }
1061
1062 /*
1063 * put a character into the output buffer
1064 */
1065
1066 void ed_putchar(c)
1067 register int c;
1068 {
1069 register char *dp = editb.e_outptr;
1070 #ifdef MULTIBYTE
1071 register int d;
1072 /* check for place holder */
1073 if(c == MARKER)
1074 return;
1075 if(d = icharset(c))
1076 {
1077 if(d == 2)
1078 *dp++ = ESS2;
1079 else if(d == 3)
1080 *dp++ = ESS3;
1081 d = in_csize(d);
1082 while(--d>0)
1083 *dp++ = HIGHBIT|(c>>(7*d));
1084 c |= HIGHBIT;
1085 }
1086 #endif /* MULTIBYTE */
1087 if (c == '_')
1088 {
1089 *dp++ = ' ';
1090 *dp++ = '\b';
1091 }
1092 *dp++ = c;
1093 *dp = '\0';
1094 if(dp >= editb.e_outlast)
1095 ed_flush();
1096 else
1097 editb.e_outptr = dp;
1098 }
1099
1100 /*
1101 * copy virtual to physical and return the index for cursor in physical buffer
1102 */
1103 int ed_virt_to_phys(virt,phys,cur,voff,poff)
1104 genchar *virt;
1105 genchar *phys;
1106 int cur, voff, poff;
1107 {
1108 register genchar *sp = virt;
1109 register genchar *dp = phys;
1110 register int c;
1111 genchar *curp = sp + cur;
1112 genchar *dpmax = phys+MAXLINE;
1113 int r;
1114 #ifdef MULTIBYTE
1115 int d;
1116 #endif /* MULTIBYTE */
1117 sp += voff;
1118 dp += poff;
1119 for(r=poff;c= *sp;sp++)
1120 {
1121 if(curp == sp)
1122 r = dp - phys;
1123 #ifdef MULTIBYTE
1124 d = out_csize(icharset(c));
1125 if(d>1)
1126 {
1127 /* multiple width character put in place holders */
1128 *dp++ = c;
1129 while(--d >0)
1130 *dp++ = MARKER;
1131 /* in vi mode the cursor is at the last character */
1132 if(dp>=dpmax)
1133 break;
1134 continue;
1135 }
1136 else
1137 #endif /* MULTIBYTE */
1138 if(!isprint(c))
1139 {
1140 if(c=='\t')
1141 {
1142 c = dp-phys;
1143 if(is_option(EDITVI))
1144 c += editb.e_plen;
1145 c = TABSIZE - c%TABSIZE;
1146 while(--c>0)
1147 *dp++ = ' ';
1148 c = ' ';
1149 }
1150 else
1151 {
1152 *dp++ = '^';
1153 c ^= TO_PRINT;
1154 }
1155 /* in vi mode the cursor is at the last character */
1156 if(curp == sp && is_option(EDITVI))
1157 r = dp - phys;
1158 }
1159 *dp++ = c;
1160 if(dp>=dpmax)
1161 break;
1162 }
1163 *dp = 0;
1164 return(r);
1165 }
1166
1167 #ifdef MULTIBYTE
1168 /*
1169 * convert external representation <src> to an array of genchars <dest>
1170 * <src> and <dest> can be the same
1171 * returns number of chars in dest
1172 */
1173
1174 int ed_internal(src,dest)
1175 register unsigned char *src;
1176 genchar *dest;
1177 {
1178 register int c;
1179 register genchar *dp = dest;
1180 register int d;
1181 register int size;
1182 if((unsigned char*)dest == src)
1183 {
1184 genchar buffer[MAXLINE];
1185 c = ed_internal(src,buffer);
1186 ed_gencpy(dp,buffer);
1187 return(c);
1188 }
1189 while(c = *src++)
1190 {
1191 if(size = echarset(c))
1192 {
1193 d = (size==1?c:0);
1194 c = size;
1195 size = in_csize(c);
1196 c <<= 7*(ESS_MAXCHAR-size);
1197 if(d)
1198 {
1199 size--;
1200 c = (c<<7) | (d&~HIGHBIT);
1201 }
1202 while(size-- >0)
1203 c = (c<<7) | ((*src++)&~HIGHBIT);
1204 }
1205 *dp++ = c;
1206 }
1207 *dp = 0;
1208 return(dp-dest);
1209 }
1210
1211 /*
1212 * convert internal representation <src> into character array <dest>.
1213 * The <src> and <dest> may be the same.
1214 * returns number of chars in dest.
1215 */
1216
1217 int ed_external(src,dest)
1218 genchar *src;
1219 char *dest;
1220 {
1221 register int c;
1222 register char *dp = dest;
1223 register int d;
1224 char *dpmax = dp+sizeof(genchar)*MAXLINE-2;
1225 if((char*)src == dp)
1226 {
1227 char buffer[MAXLINE*sizeof(genchar)];
1228 c = ed_external(src,buffer);
1229 strcpy(dest,buffer);
1230 return(c);
1231 }
1232 while((c = *src++) && dp<dpmax)
1233 {
1234 if(d = icharset(c))
1235 {
1236 if(d == 2)
1237 *dp++ = ESS2;
1238 else if(d == 3)
1239 *dp++ = ESS3;
1240 d = in_csize(d);
1241 while(--d>0)
1242 *dp++ = HIGHBIT|(c>>(7*d));
1243 c |= HIGHBIT;
1244 }
1245 *dp++ = c;
1246 }
1247 *dp = 0;
1248 return(dp-dest);
1249 }
1250
1251 /*
1252 * copy <sp> to <dp>
1253 */
1254
1255 int ed_gencpy(dp,sp)
1256 register genchar *dp;
1257 register genchar *sp;
1258 {
1259 while(*dp++ = *sp++);
1260 }
1261
1262 /*
1263 * copy at most <n> items from <sp> to <dp>
1264 */
1265
1266 int ed_genncpy(dp,sp, n)
1267 register genchar *dp;
1268 register genchar *sp;
1269 register int n;
1270 {
1271 while(n-->0 && (*dp++ = *sp++));
1272 }
1273
1274 /*
1275 * find the string length of <str>
1276 */
1277
1278 int ed_genlen(str)
1279 register genchar *str;
1280 {
1281 register genchar *sp = str;
1282 while(*sp++);
1283 return(sp-str-1);
1284 }
1285 #endif /* MULTIBYTE */
1286 #endif /* ESH || VSH */
1287
1288 #ifdef MULTIBYTE
1289 /*
1290 * set the multibyte widths
1291 * format of string is x1[:y1][,x2[:y2][,x3[:y3]]]
1292 * returns 1 if string in not in this format, 0 otherwise.
1293 */
1294
1295 extern char int_charsize[];
1296 ed_setwidth(string)
1297 char *string;
1298 {
1299 register int indx = 0;
1300 register int state = 0;
1301 register int c;
1302 register int n = 0;
1303 static char widths[6] = {1,1};
1304 while(1) switch(c = *string++)
1305 {
1306 case ':':
1307 if(state!=1)
1308 return(1);
1309 state++;
1310 /* fall through */
1311
1312 case 0:
1313 case ',':
1314 if(state==0)
1315 return(1);
1316 widths[indx++] = n;
1317 if(state==1)
1318 widths[indx++] = n;
1319 if(c==0)
1320 {
1321 for(n=1;n<= 3;n++)
1322 {
1323 int_charsize[n] = widths[c++];
1324 int_charsize[n+4] = widths[c++];
1325 }
1326 return(0);
1327 }
1328 else if(c==',')
1329 state = 0;
1330 n = 0;
1331 break;
1332
1333 case '0': case '1': case '2': case '3': case '4':
1334 if(state&1)
1335 return(1);
1336 n = c - '0';
1337 state++;
1338 break;
1339
1340 default:
1341 return(1);
1342 }
1343 /* NOTREACHED */
1344 }
1345 #endif /* MULTIBYTE */
1346
1347 #ifdef future
1348 /*
1349 * returns 1 when <n> bytes starting at <a> and <b> are equal
1350 */
1351 static int compare(a,b,n)
1352 register char *a;
1353 register char *b;
1354 register int n;
1355 {
1356 while(n-->0)
1357 {
1358 if(*a++ != *b++)
1359 return(0);
1360 }
1361 return(1);
1362 }
1363 #endif
1364
1365 #ifdef OLDTERMIO
1366
1367 # include <sys/termio.h>
1368
1369 #ifndef ECHOCTL
1370 # define ECHOCTL 0
1371 #endif /* !ECHOCTL */
1372 char echoctl;
1373 static char tcgeta;
1374 static struct termio ott;
1375
1376 /*
1377 * For backward compatibility only
1378 * This version will use termios when possible, otherwise termio
1379 */
1380
1381
1382 tcgetattr(fd,tt)
1383 struct termios *tt;
1384 {
1385 register int r;
1386 register int i;
1387 tcgeta = 0;
1388 echoctl = (ECHOCTL!=0);
1389 if((r=ioctl(fd,TCGETS,tt))>=0 || errno!=EINVAL)
1390 return(r);
1391 if((r=ioctl(fd,TCGETA,&ott)) >= 0)
1392 {
1393 tt->c_lflag = ott.c_lflag;
1394 tt->c_oflag = ott.c_oflag;
1395 tt->c_iflag = ott.c_iflag;
1396 tt->c_cflag = ott.c_cflag;
1397 for(i=0; i<NCC; i++)
1398 tt->c_cc[i] = ott.c_cc[i];
1399 tcgeta++;
1400 echoctl = 0;
1401 }
1402 return(r);
1403 }
1404
1405 tcsetattr(fd,mode,tt)
1406 register int mode;
1407 struct termios *tt;
1408 {
1409 register int r;
1410 if(tcgeta)
1411 {
1412 register int i;
1413 ott.c_lflag = tt->c_lflag;
1414 ott.c_oflag = tt->c_oflag;
1415 ott.c_iflag = tt->c_iflag;
1416 ott.c_cflag = tt->c_cflag;
1417 for(i=0; i<NCC; i++)
1418 ott.c_cc[i] = tt->c_cc[i];
1419 if(tt->c_lflag&ECHOCTL)
1420 {
1421 ott.c_lflag &= ~(ECHOCTL|IEXTEN);
1422 ott.c_iflag &= ~(IGNCR|ICRNL);
1423 ott.c_iflag |= INLCR;
1424 ott.c_cc[VEOF]= ESC; /* ESC -> eof char */
1425 ott.c_cc[VEOL] = '\r'; /* CR -> eol char */
1426 ott.c_cc[VEOL2] = tt->c_cc[VEOF]; /* EOF -> eol char */
1427 }
1428 switch(mode)
1429 {
1430 case TCSANOW:
1431 mode = TCSETA;
1432 break;
1433 case TCSADRAIN:
1434 mode = TCSETAW;
1435 break;
1436 case TCSAFLUSH:
1437 mode = TCSETAF;
1438 }
1439 return(ioctl(fd,mode,&ott));
1440 }
1441 return(ioctl(fd,mode,tt));
1442 }
1443 #endif /* OLDTERMIO */
1444