1 /* $OpenBSD: edit.c,v 1.38 2013/06/03 15:41:59 tedu Exp $ */
4 * Command line editing - common code
16 #include <sys/ioctl.h>
22 static void x_sigwinch(int);
23 volatile sig_atomic_t got_sigwinch
;
24 static void check_sigwinch(void);
26 static int x_file_glob(int, const char *, int, char ***);
27 static int x_command_glob(int, const char *, int, char ***);
28 static int x_locate_word(const char *, int, int, int *, int *);
31 /* Called from main */
35 /* set to -2 to force initial binding */
36 edchars
.erase
= edchars
.kill
= edchars
.intr
= edchars
.quit
=
38 /* default value for deficient systems */
39 edchars
.werase
= 027; /* ^W */
41 if (setsig(&sigtraps
[SIGWINCH
], x_sigwinch
, SS_RESTORE_ORIG
|SS_SHTRAP
))
42 sigtraps
[SIGWINCH
].flags
|= TF_SHELL_USES
;
43 got_sigwinch
= 1; /* force initial check */
65 if (procpid
== kshpid
&& ioctl(tty_fd
, TIOCGWINSZ
, &ws
) >= 0) {
68 /* Do NOT export COLUMNS/LINES. Many applications
69 * check COLUMNS/LINES before checking ws.ws_col/row,
70 * so if the app is started with C/L in the environ
71 * and the window is then resized, the app won't
72 * see the change cause the environ doesn't change.
75 x_cols
= ws
.ws_col
< MIN_COLS
? MIN_COLS
:
78 if ((vp
= typeset("COLUMNS", 0, 0, 0, 0)))
79 setint(vp
, (long) ws
.ws_col
);
81 if (ws
.ws_row
&& (vp
= typeset("LINES", 0, 0, 0, 0)))
82 setint(vp
, (long) ws
.ws_row
);
88 * read an edited command line
91 x_read(char *buf
, size_t len
)
97 if (Flag(FEMACS
) || Flag(FGMACS
))
98 i
= x_emacs(buf
, len
);
106 i
= -1; /* internal error */
120 while ((n
= blocking_read(STDIN_FILENO
, &c
, 1)) < 0 && errno
== EINTR
)
128 return (int) (unsigned char) c
;
140 shf_putc(c
, shl_out
);
144 x_puts(const char *s
)
147 shf_putc(*s
++, shl_out
);
153 static bool x_cur_mode
;
156 if (x_cur_mode
== onoff
)
168 edchars
.erase
= cb
.c_cc
[VERASE
];
169 edchars
.kill
= cb
.c_cc
[VKILL
];
170 edchars
.intr
= cb
.c_cc
[VINTR
];
171 edchars
.quit
= cb
.c_cc
[VQUIT
];
172 edchars
.eof
= cb
.c_cc
[VEOF
];
173 edchars
.werase
= cb
.c_cc
[VWERASE
];
174 cb
.c_iflag
&= ~(INLCR
|ICRNL
);
175 cb
.c_lflag
&= ~(ISIG
|ICANON
|ECHO
);
176 /* osf/1 processes lnext when ~icanon */
177 cb
.c_cc
[VLNEXT
] = _POSIX_VDISABLE
;
178 /* sunos 4.1.x & osf/1 processes discard(flush) when ~icanon */
179 cb
.c_cc
[VDISCARD
] = _POSIX_VDISABLE
;
183 tcsetattr(tty_fd
, TCSADRAIN
, &cb
);
185 /* Convert unset values to internal `unset' value */
186 if (edchars
.erase
== _POSIX_VDISABLE
)
188 if (edchars
.kill
== _POSIX_VDISABLE
)
190 if (edchars
.intr
== _POSIX_VDISABLE
)
192 if (edchars
.quit
== _POSIX_VDISABLE
)
194 if (edchars
.eof
== _POSIX_VDISABLE
)
196 if (edchars
.werase
== _POSIX_VDISABLE
)
198 if (memcmp(&edchars
, &oldchars
, sizeof(edchars
)) != 0) {
200 x_emacs_keys(&edchars
);
204 tcsetattr(tty_fd
, TCSADRAIN
, &tty_state
);
211 set_editmode(const char *ed
)
213 static const enum sh_flag edit_flags
[] = {
224 if ((rcp
= strrchr(ed
, '/')))
226 for (i
= 0; i
< NELEM(edit_flags
); i
++)
227 if (strstr(ed
, options
[(int) edit_flags
[i
]].name
)) {
228 change_flag(edit_flags
[i
], OF_SPECIAL
, 1);
233 /* ------------------------------------------------------------------------- */
234 /* Misc common code for vi/emacs */
236 /* Handle the commenting/uncommenting of a line.
238 * 1 if a carriage return is indicated (comment added)
239 * 0 if no return (comment removed)
240 * -1 if there is an error (not enough room for comment chars)
241 * If successful, *lenp contains the new length. Note: cursor should be
242 * moved to the start of the line after (un)commenting.
245 x_do_comment(char *buf
, int bsize
, int *lenp
)
251 return 1; /* somewhat arbitrary - it's what at&t ksh does */
253 /* Already commented? */
257 for (j
= 0, i
= 1; i
< len
; i
++) {
258 if (!saw_nl
|| buf
[i
] != '#')
260 saw_nl
= buf
[i
] == '\n';
267 /* See if there's room for the #'s - 1 per \n */
268 for (i
= 0; i
< len
; i
++)
271 if (len
+ n
>= bsize
)
273 /* Now add them... */
274 for (i
= len
, j
= len
+ n
; --i
>= 0; ) {
285 /* ------------------------------------------------------------------------- */
286 /* Common file/command completion code for vi/emacs */
289 static char *add_glob(const char *str
, int slen
);
290 static void glob_table(const char *pat
, XPtrV
*wp
, struct table
*tp
);
291 static void glob_path(int flags
, const char *pat
, XPtrV
*wp
,
295 x_print_expansions(int nwords
, char *const *words
, int is_command
)
301 /* Check if all matches are in the same directory (in this
302 * case, we want to omit the directory name)
305 (prefix_len
= x_longest_prefix(nwords
, words
)) > 0) {
308 /* Special case for 1 match (prefix is whole word) */
310 prefix_len
= x_basename(words
[0], (char *) 0);
311 /* Any (non-trailing) slashes in non-common word suffixes? */
312 for (i
= 0; i
< nwords
; i
++)
313 if (x_basename(words
[i
] + prefix_len
, (char *) 0) >
316 /* All in same directory? */
318 while (prefix_len
> 0 && words
[0][prefix_len
- 1] != '/')
321 XPinit(l
, nwords
+ 1);
322 for (i
= 0; i
< nwords
; i
++)
323 XPput(l
, words
[i
] + prefix_len
);
324 XPput(l
, (char *) 0);
329 * Enumerate expansions
333 pr_list(use_copy
? (char **) XPptrv(l
) : words
);
336 XPfree(l
); /* not x_free_words() */
341 * - appends * to (copy of) str if no globbing chars found
342 * - does expansion, checks for no match, etc.
343 * - sets *wordsp to array of matching strings
344 * - returns number of matching strings
347 x_file_glob(int flags
, const char *str
, int slen
, char ***wordsp
)
353 struct source
*s
, *sold
;
358 toglob
= add_glob(str
, slen
);
361 * Convert "foo*" (toglob) to an array of strings (words)
364 s
= pushs(SWSTR
, ATEMP
);
365 s
->start
= s
->str
= toglob
;
367 if (yylex(ONEWORD
|UNESCAPE
) != LWORD
) {
369 internal_errorf(0, "fileglob: substitute error");
374 expand(yylval
.cp
, &w
, DOGLOB
|DOTILDE
|DOMARKDIRS
);
376 words
= (char **) XPclose(w
);
378 for (nwords
= 0; words
[nwords
]; nwords
++)
383 /* Check if file exists, also, check for empty
384 * result - happens if we tried to glob something
385 * which evaluated to an empty string (e.g.,
386 * "$FOO" when there is no FOO, etc).
388 if ((lstat(words
[0], &statb
) < 0) ||
389 words
[0][0] == '\0') {
390 x_free_words(nwords
, words
);
395 afree(toglob
, ATEMP
);
400 x_free_words(nwords
, words
);
407 /* Data structure used in x_command_glob() */
408 struct path_order_info
{
414 static int path_order_cmp(const void *aa
, const void *bb
);
416 /* Compare routine used in x_command_glob() */
418 path_order_cmp(const void *aa
, const void *bb
)
420 const struct path_order_info
*a
= (const struct path_order_info
*) aa
;
421 const struct path_order_info
*b
= (const struct path_order_info
*) bb
;
424 t
= strcmp(a
->word
+ a
->base
, b
->word
+ b
->base
);
425 return t
? t
: a
->path_order
- b
->path_order
;
429 x_command_glob(int flags
, const char *str
, int slen
, char ***wordsp
)
441 toglob
= add_glob(str
, slen
);
443 /* Convert "foo*" (toglob) to a pattern for future use */
444 pat
= evalstr(toglob
, DOPAT
|DOTILDE
);
445 afree(toglob
, ATEMP
);
449 glob_table(pat
, &w
, &keywords
);
450 glob_table(pat
, &w
, &aliases
);
451 glob_table(pat
, &w
, &builtins
);
452 for (l
= e
->loc
; l
; l
= l
->next
)
453 glob_table(pat
, &w
, &l
->funs
);
455 glob_path(flags
, pat
, &w
, path
);
456 if ((fpath
= str_val(global("FPATH"))) != null
)
457 glob_path(flags
, pat
, &w
, fpath
);
462 *wordsp
= (char **) 0;
468 if (flags
& XCF_FULLPATH
) {
469 /* Sort by basename, then path order */
470 struct path_order_info
*info
;
471 struct path_order_info
*last_info
= 0;
472 char **words
= (char **) XPptrv(w
);
476 info
= (struct path_order_info
*)
477 alloc(sizeof(struct path_order_info
) * nwords
, ATEMP
);
478 for (i
= 0; i
< nwords
; i
++) {
479 info
[i
].word
= words
[i
];
480 info
[i
].base
= x_basename(words
[i
], (char *) 0);
481 if (!last_info
|| info
[i
].base
!= last_info
->base
||
482 strncmp(words
[i
], last_info
->word
, info
[i
].base
) != 0) {
483 last_info
= &info
[i
];
486 info
[i
].path_order
= path_order
;
488 qsort(info
, nwords
, sizeof(struct path_order_info
),
490 for (i
= 0; i
< nwords
; i
++)
491 words
[i
] = info
[i
].word
;
492 afree((void *) info
, ATEMP
);
494 /* Sort and remove duplicate entries */
495 char **words
= (char **) XPptrv(w
);
498 qsortp(XPptrv(w
), (size_t) nwords
, xstrcmp
);
500 for (i
= j
= 0; i
< nwords
- 1; i
++) {
501 if (strcmp(words
[i
], words
[i
+ 1]))
502 words
[j
++] = words
[i
];
504 afree(words
[i
], ATEMP
);
506 words
[j
++] = words
[i
];
508 w
.cur
= (void **) &words
[j
];
512 *wordsp
= (char **) XPclose(w
);
517 #define IS_WORDC(c) !( ctype(c, C_LEX1) || (c) == '\'' || (c) == '"' || \
518 (c) == '`' || (c) == '=' || (c) == ':' )
521 x_locate_word(const char *buf
, int buflen
, int pos
, int *startp
,
527 /* Bad call? Probably should report error */
528 if (pos
< 0 || pos
> buflen
) {
533 /* The case where pos == buflen happens to take care of itself... */
536 /* Keep going backwards to start of word (has effect of allowing
537 * one blank after the end of a word)
539 for (; (start
> 0 && IS_WORDC(buf
[start
- 1])) ||
540 (start
> 1 && buf
[start
-2] == '\\'); start
--)
542 /* Go forwards to end of word */
543 for (end
= start
; end
< buflen
&& IS_WORDC(buf
[end
]); end
++) {
544 if (buf
[end
] == '\\' && (end
+1) < buflen
)
551 /* Figure out if this is a command */
552 for (p
= start
- 1; p
>= 0 && isspace(buf
[p
]); p
--)
554 iscmd
= p
< 0 || strchr(";|&()`", buf
[p
]);
556 /* If command has a /, path, etc. is not searched;
557 * only current directory is searched, which is just
558 * like file globbing.
560 for (p
= start
; p
< end
; p
++)
565 *is_commandp
= iscmd
;
574 x_cf_glob(int flags
, const char *buf
, int buflen
, int pos
, int *startp
,
575 int *endp
, char ***wordsp
, int *is_commandp
)
582 len
= x_locate_word(buf
, buflen
, pos
, startp
, &is_command
);
583 if (!(flags
& XCF_COMMAND
))
585 /* Don't do command globing on zero length strings - it takes too
586 * long and isn't very useful. File globs are more likely to be
587 * useful, so allow these.
589 if (len
== 0 && is_command
)
592 nwords
= (is_command
? x_command_glob
: x_file_glob
)(flags
,
593 buf
+ *startp
, len
, &words
);
595 *wordsp
= (char **) 0;
600 *is_commandp
= is_command
;
602 *endp
= *startp
+ len
;
607 /* Given a string, copy it and possibly add a '*' to the end. The
608 * new string is returned.
611 add_glob(const char *str
, int slen
)
615 bool saw_slash
= false;
620 toglob
= str_nsave(str
, slen
+ 1, ATEMP
); /* + 1 for "*" */
624 * If the pathname contains a wildcard (an unquoted '*',
625 * '?', or '[') or parameter expansion ('$'), or a ~username
626 * with no trailing slash, then it is globbed based on that
627 * value (i.e., without the appended '*').
629 for (s
= toglob
; *s
; s
++) {
630 if (*s
== '\\' && s
[1])
632 else if (*s
== '*' || *s
== '[' || *s
== '?' || *s
== '$' ||
633 (s
[1] == '(' /*)*/ && strchr("+@!", *s
)))
638 if (!*s
&& (*toglob
!= '~' || saw_slash
)) {
640 toglob
[slen
+ 1] = '\0';
647 * Find longest common prefix
650 x_longest_prefix(int nwords
, char *const *words
)
659 prefix_len
= strlen(words
[0]);
660 for (i
= 1; i
< nwords
; i
++)
661 for (j
= 0, p
= words
[i
]; j
< prefix_len
; j
++)
662 if (p
[j
] != words
[0][j
]) {
670 x_free_words(int nwords
, char **words
)
674 for (i
= 0; i
< nwords
; i
++)
676 afree(words
[i
], ATEMP
);
680 /* Return the offset of the basename of string s (which ends at se - need not
681 * be null terminated). Trailing slashes are ignored. If s is just a slash,
682 * then the offset is 0 (actually, length - 1).
693 x_basename(const char *s
, const char *se
)
697 if (se
== (char *) 0)
702 /* Skip trailing slashes */
703 for (p
= se
- 1; p
> s
&& *p
== '/'; p
--)
705 for (; p
> s
&& *p
!= '/'; p
--)
707 if (*p
== '/' && p
+ 1 < se
)
714 * Apply pattern matching to a table: all table entries that match a pattern
718 glob_table(const char *pat
, XPtrV
*wp
, struct table
*tp
)
723 for (ktwalk(&ts
, tp
); (te
= ktnext(&ts
)); ) {
724 if (gmatch(te
->name
, pat
, false))
725 XPput(*wp
, str_save(te
->name
, ATEMP
));
730 glob_path(int flags
, const char *pat
, XPtrV
*wp
, const char *path
)
737 int oldsize
, newsize
, i
, j
;
741 patlen
= strlen(pat
) + 1;
743 Xinit(xs
, xp
, patlen
+ 128, ATEMP
);
745 xp
= Xstring(xs
, xp
);
746 if (!(p
= strchr(sp
, ':')))
750 /* Copy sp into xp, stuffing any MAGIC characters
755 XcheckN(xs
, xp
, pathlen
* 2);
765 XcheckN(xs
, xp
, patlen
);
766 memcpy(xp
, pat
, patlen
);
768 oldsize
= XPsize(*wp
);
769 glob_str(Xstring(xs
, xp
), wp
, 1); /* mark dirs */
770 newsize
= XPsize(*wp
);
772 /* Check that each match is executable... */
773 words
= (char **) XPptrv(*wp
);
774 for (i
= j
= oldsize
; i
< newsize
; i
++) {
776 if ((search_access(words
[i
], X_OK
, &staterr
) >= 0) ||
777 (staterr
== EISDIR
)) {
779 if (!(flags
& XCF_FULLPATH
))
780 memmove(words
[j
], words
[j
] + pathlen
,
781 strlen(words
[j
] + pathlen
) + 1);
784 afree(words
[i
], ATEMP
);
786 wp
->cur
= (void **) &words
[j
];
795 * if argument string contains any special characters, they will
796 * be escaped and the result will be put into edit buffer by
797 * keybinding-specific function
800 x_escape(const char *s
, size_t len
, int (*putbuf_func
) (const char *, size_t))
803 const char *ifs
= str_val(local("IFS", 0));
806 for (add
= 0, wlen
= len
; wlen
- add
> 0; add
++) {
807 if (strchr("\"#$&'()*:;<=>?[\\]`{|}", s
[add
]) ||
808 strchr(ifs
, s
[add
])) {
809 if (putbuf_func(s
, add
) != 0) {
814 putbuf_func("\\", 1);
815 putbuf_func(&s
[add
], 1);
820 add
= -1; /* after the increment it will go to 0 */
823 if (wlen
> 0 && rval
== 0)
824 rval
= putbuf_func(s
, wlen
);