/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
/*
* Copyright (c) 1980 Regents of the University of California.
* All rights reserved. The Berkeley Software License Agreement
* specifies the terms and conditions for redistribution.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#ifdef FILEC
/*
* Tenex style file name recognition, .. and more.
* History:
* Author: Ken Greer, Sept. 1975, CMU.
* Finally got around to adding to the Cshell., Ken Greer, Dec. 1981.
*/
#include "sh.h"
#include <dirent.h>
#include <pwd.h>
#include "sh.tconst.h"
#define FALSE 0
#define OFF 0
/*
* Put this here so the binary can be patched with adb to enable file
* completion by default. Filec controls completion, nobeep controls
* ringing the terminal bell on incomplete expansions.
*/
bool filec = 0;
static void
{
int omask;
#ifdef TRACE
tprintf("TRACE- setup_tty()\n");
#endif
if (on) {
/*
* The shell makes sure that the tty is not in some weird state
* and fixes it if it is. But it should be noted that the
* tenex routine will not work correctly in CBREAK or RAW mode
* so this code below is, therefore, mandatory.
*
* Also, in order to recognize the ESC (filename-completion)
* character, set EOL to ESC. This way, ESC will terminate
* the line, but still be in the input stream.
* EOT (filename list) will also terminate the line,
* but will not appear in the input stream.
*
* tty state will be restored if the user types ^C.
*/
reset();
}
} else {
/*
* Reset terminal state to what user had when invoked
*/
}
(void) sigsetmask(omask);
}
static void
termchars(void)
{
extern char *tgetstr();
static int been_here = 0;
char *s;
char *term;
#ifdef TRACE
tprintf("TRACE- termchars()\n");
#endif
if (been_here)
return;
return;
return;
BELL = s;
}
/*
* Move back to beginning of current line
*/
static void
back_to_col_1(void)
{
int omask;
#ifdef TRACE
tprintf("TRACE- back_to_col_1()\n");
#endif
(void) sigsetmask(omask);
}
/*
* Push string contents back into tty queue
*/
static void
{
tchar *p;
#ifdef TRACE
tprintf("TRACE- pushback()\n");
#endif
if (!echoflag)
for (p = string; *p; p++) {
if (j < 0) {
/* Error! But else what can we do? */
continue;
}
for (i = 0; i < j; ++i) {
if (retry++ < 5)
goto again;
/* probably no worth retrying any more */
}
}
}
(void) sigsetmask(omask);
}
/*
* Concatenate src onto tail of des.
* Des is a string whose maximum length is count.
* Always null terminate.
*/
void
{
#ifdef TRACE
tprintf("TRACE- catn()\n");
#endif
des++;
while (--count >= 0)
return;
*des = '\0';
}
static int
max(a, b)
{
return (a > b ? a : b);
}
/*
* Like strncpy but always leave room for trailing \0
* and always null terminate.
*/
void
{
#ifdef TRACE
tprintf("TRACE- copyn()\n");
#endif
while (--count >= 0)
return;
*des = '\0';
}
/*
* For qsort()
*/
static int
{
#ifdef TRACE
tprintf("TRACE- fcompare()\n");
#endif
}
static char
{
#ifdef TRACE
tprintf("TRACE- filetype()\n");
#endif
if (dir) {
if (nosym) {
return (' ');
} else {
return (' ');
}
return ('@');
return ('/');
return ('*');
}
return (' ');
}
/*
* Print sorted down columns
*/
static void
{
#ifdef TRACE
tprintf("TRACE- print_by_column()\n");
#endif
for (i = 0; i < count; i++)
/* for the file tag and space */
for (r = 0; r < rows; r++) {
for (c = 0; c < columns; c++) {
i = c * rows + r;
if (i < count) {
int w;
/*
* Print filename followed by
* '@' or '/' or '*' or ' '
*/
if (!looking_for_command) {
printf("%c",
w++;
}
for (; w < maxwidth; w++)
printf(" ");
}
}
printf("\n");
}
}
/*
* Expand file name with possible tilde usage
* expands to
*/
tchar *
{
tchar *o, *p;
#ifdef TRACE
tprintf("TRACE- tilde()\n");
#endif
if (old[0] != '~')
;
*p = '\0';
if (person[0] == '\0')
else {
return (NULL);
}
return (new);
}
/*
* Cause pending line to be printed
*/
static void
sim_retype(void)
{
#ifdef notdef
#ifdef TRACE
tprintf("TRACE- sim_retypr()\n");
#endif
#else
#ifdef TRACE
tprintf("TRACE- sim_retype()\n");
#endif
printprompt();
#endif
}
static int
beep_outc(int c)
{
buf[0] = c;
return 0;
}
static void
beep(void)
{
#ifdef TRACE
tprintf("TRACE- beep()\n");
#endif
}
/*
* Erase that silly ^[ and print the recognized part of the string.
*/
static void
{
#ifdef TRACE
tprintf("TRACE- print_recognized_stuff()\n");
#endif
/*
* An optimized erasing of that silly ^[
*
* One would think that line speeds have become fast enough that this
* isn't necessary, but it turns out that the visual difference is
* quite noticeable.
*/
flush();
switch (tswidth(recognized_part)) {
case 0:
/* erase two characters: ^[ */
break;
case 1:
/* overstrike the ^, erase the [ */
break;
default:
/* overstrike both characters ^[ */
break;
}
flush();
}
/*
* Parse full path in file into 2 parts: directory and file names
* Should leave final slash (/) at end of dir.
*/
static void
{
tchar *p;
#ifdef TRACE
tprintf("TRACE- extract_dir_and_name()\n");
#endif
if (p == NOSTR) {
dir[0] = '\0';
} else {
}
}
tchar *
{
/*
* For char * -> tchar * Conversion
*/
#ifdef TRACE
tprintf("TRACE- getentry()\n");
#endif
if (looking_for_lognames) {
return (NULL);
}
return (NULL);
}
static void
{
int i;
#ifdef TRACE
tprintf("TRACE- free_items()\n");
#endif
for (i = 0; items[i]; i++)
}
int omask;\
\
free_items(items);\
(void) sigsetmask(omask);\
}
/*
* Perform a RECOGNIZE or LIST command on string "word".
*/
static int
{
#ifdef TRACE
tprintf("TRACE- search2()\n");
#endif
if (looking_for_lognames) {
(void) setpwent();
} else {
return (0);
return (0);
}
again: /* search for matches */
continue;
/* Don't match . files on null prefix match */
continue;
printf("\nYikes!! Too many %s!!\n",
"names in password file":"files");
break;
}
MAXITEMS+1);
numitems++;
} else { /* RECOGNIZE command */
nignored++;
else if (recognize(extended_name,
break;
}
}
nignored = 0;
if (looking_for_lognames)
(void) setpwent();
else
goto again;
}
if (looking_for_lognames)
(void) endpwent();
else {
}
if (looking_for_lognames)
else
/* put back dir part */
/* add extended name */
return (numitems);
}
(int (*)(const void *, const void *))fcompare);
/*
* Never looking for commands in this version, so final
* argument forced to 0. If command name completion is
* reinstated, this must change.
*/
}
return (0);
}
/*
* Object: extend what user typed up to an ambiguity.
* Algorithm:
* On first match, copy full entry (assume it'll be the only match)
* On subsequent matches, shorten extended_name to the first
* character mismatch between extended_name and entry.
* If we shorten it back to the prefix length, stop searching.
*/
int
{
#ifdef TRACE
tprintf("TRACE- recognize()\n");
#endif
else { /* 2nd and subsequent matches */
int len = 0;
x = extended_name;
;
*x = '\0'; /* Shorten at 1st char diff */
return (-1); /* So stop now and save time */
}
return (0);
}
/*
* Return true if check items initial chars in template
* This differs from PWB imatch in that if check is null
* it items anything
*/
static int
{
#ifdef TRACE
tprintf("TRACE- is_prefix()\n");
#endif
do
if (*check == 0)
return (TRUE);
return (FALSE);
}
/*
* Return true if the chars in template appear at the
* end of check, i.e., are its suffix.
*/
static int
{
tchar *c, *t;
#ifdef TRACE
tprintf("TRACE- is_suffix()\n");
#endif
for (c = check; *c++; )
;
for (t = template; *t++; )
;
for (;;) {
if (t == template)
return (TRUE);
if (c == check || *--t != *--c)
return (FALSE);
}
}
int
{
int i;
#ifdef TRACE
tprintf("TRACE- tenex()\n");
#endif
termchars();
num_read = 0;
> 0) {
int space_left;
num_read += i;
/*
* read_() can return more than requested size if there
* is multibyte character at the end.
*/
break;
} else
printf("\n");
/*
* Find LAST occurence of a delimiter in the inputline.
* The word start is one character past it.
*/
--word_start) {
break;
}
/*
* Tabs in the input line cause trouble after a pushback.
* tty driver won't backspace over them because column
* positions are now incorrect. This is solved by retyping
* over current line.
*/
}
if (should_retype)
printprompt();
num_read = 0; /* chars will be reread */
/*
* Avoid a race condition by echoing what we're recognized
* _after_ pushing back the command line. This way, if the
* user waits until seeing this output before typing more
* stuff, the resulting keystrokes won't race with the STIed
* input we've pushed back. (Of course, if the user types
* ahead, the race still exists and it's quite possible that
* the pushed back input line will interleave with the
* keystrokes in unexpected ways.)
*/
/* print from str_end on */
beep();
}
}
return (num_read);
}
static int
{
#ifdef TRACE
tprintf("TRACE- ignored()\n");
#endif
return (FALSE);
return (TRUE);
return (FALSE);
}
#endif /* FILEC */