# 2.11BSD#431 - /usr/src/bin/tcsh/sh.file.c

##### Functions

    tenex             X

##### Variables

    filec             X

##### Macros

    ESC               X
    FALSE             X
    FREE_ITEMS        X
    MAXITEMS          X
    OFF               X
    ON                X
    TRUE              X

##### typedef's

    COMMAND           X

       1: /* $Header: /home/hyperion/mu/christos/src/sys/tcsh-6.00/RCS/sh.file.c,v 3.0 1991/07/04 21:49:28 christos Exp $ */
       2: /*
       3:  * sh.file.c: File completion for csh.
       4:  */
       5: /*-
       6:  * Copyright (c) 1980, 1991 The Regents of the University of California.
       7:  * All rights reserved.
       8:  *
       9:  * Redistribution and use in source and binary forms, with or without
      10:  * modification, are permitted provided that the following conditions
      11:  * are met:
      12:  * 1. Redistributions of source code must retain the above copyright
      13:  *    notice, this list of conditions and the following disclaimer.
      14:  * 2. Redistributions in binary form must reproduce the above copyright
      15:  *    notice, this list of conditions and the following disclaimer in the
      16:  *    documentation and/or other materials provided with the distribution.
      17:  * 3. All advertising materials mentioning features or use of this software
      18:  *    must display the following acknowledgement:
      19:  *	This product includes software developed by the University of
      20:  *	California, Berkeley and its contributors.
      21:  * 4. Neither the name of the University nor the names of its contributors
      22:  *    may be used to endorse or promote products derived from this software
      23:  *    without specific prior written permission.
      24:  *
      25:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
      26:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      27:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      28:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
      29:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      30:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      31:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      32:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      33:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      34:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      35:  * SUCH DAMAGE.
      36:  */
      37: #ifdef FILEC
      38: #include "config.h"
      39: #ifndef lint
      40: static char *rcsid()
      41:     { return "$Id: sh.file.c,v 3.0 1991/07/04 21:49:28 christos Exp $"; }
      42: #endif
      43:
      44: #include "sh.h"
      45:
      46: /*
      47:  * Tenex style file name recognition, .. and more.
      48:  * History:
      49:  *	Author: Ken Greer, Sept. 1975, CMU.
      50:  *	Finally got around to adding to the Cshell., Ken Greer, Dec. 1981.
      51:  */
      52:
      53: #define ON  1
      54: #define OFF 0
      55: #ifndef TRUE
      56: #define TRUE 1
      57: #endif
      58: #ifndef FALSE
      59: #define FALSE 0
      60: #endif
      61:
      62: #define ESC '\033'
      63:
      64: typedef enum {
      65:     LIST, RECOGNIZE
      66: }       COMMAND;
      67:
      68: static  void     setup_tty      __P((int));
      69: static  void     back_to_col_1      __P((void));
      70: static  void     pushback       __P((Char *));
      71: static  void     catn           __P((Char *, Char *, int));
      72: static  void     copyn          __P((Char *, Char *, int));
      73: static  Char     filetype       __P((Char *, Char *));
      74: static  void     print_by_column    __P((Char *, Char *[], int));
      75: static  Char    *tilde          __P((Char *, Char *));
      76: static  void     retype         __P((void));
      77: static  void     beep           __P((void));
      78: static  void     print_recog_stuff  __P((Char *));
      79: static  void     extract_dir_and_name   __P((Char *, Char *, Char *));
      80: static  Char    *getentry       __P((DIR *, int));
      81: static  void     free_items     __P((Char **));
      82: static  int  tsearch        __P((Char *, COMMAND, int));
      83: static  int  recognize      __P((Char *, Char *, int, int));
      84: static  int  is_prefix      __P((Char *, Char *));
      85: static  int  is_suffix      __P((Char *, Char *));
      86: static  int  ignored        __P((Char *));
      87:
      88:
      89: /*
      90:  * Put this here so the binary can be patched with adb to enable file
      91:  * completion by default.  Filec controls completion, nobeep controls
      92:  * ringing the terminal bell on incomplete expansions.
      93:  */
      94: bool    filec = 0;
      95:
      96: static void
      97: setup_tty(on)
      98:     int     on;
      99: {
     100: #ifdef TERMIOS
     101:     static struct termios tchars;
     102:
     103:     if (on) {
     104:     (void) tcgetattr(SHIN, &tchars);
     105:     tchars.c_cc[VEOL] = ESC;
     106:     if (tchars.c_lflag & ICANON)
     107:         on = TCSANOW;
     108:     else {
     109:         on = TCSAFLUSH;
     110:         tchars.c_lflag |= ICANON;
     111:     }
     112:         (void) tcsetattr(SHIN, on, &tchars);
     113:     }
     114:     else {
     115:     tchars.c_cc[VEOL] = _POSIX_VDISABLE;
     116:     (void) tcsetattr(SHIN, TCSANOW, &tchars);
     117:     }
     118: #else
     119:     struct sgttyb sgtty;
     120:     static struct tchars tchars;/* INT, QUIT, XON, XOFF, EOF, BRK */
     121:
     122:     if (on) {
     123:     (void) ioctl(SHIN, TIOCGETC, (ioctl_t) & tchars);
     124:     tchars.t_brkc = ESC;
     125:     (void) ioctl(SHIN, TIOCSETC, (ioctl_t) & tchars);
     126:     /*
     127: 	 * This must be done after every command: if the tty gets into raw or
     128: 	 * cbreak mode the user can't even type 'reset'.
     129: 	 */
     130:     (void) ioctl(SHIN, TIOCGETP, (ioctl_t) & sgtty);
     131:     if (sgtty.sg_flags & (RAW | CBREAK)) {
     132:         sgtty.sg_flags &= ~(RAW | CBREAK);
     133:         (void) ioctl(SHIN, TIOCSETP, (ioctl_t) & sgtty);
     134:     }
     135:     }
     136:     else {
     137:     tchars.t_brkc = -1;
     138:     (void) ioctl(SHIN, TIOCSETC, (ioctl_t) & tchars);
     139:     }
     140: #endif
     141: }
     142:
     143: /*
     144:  * Move back to beginning of current line
     145:  */
     146: static void
     147: back_to_col_1()
     148: {
     149: #ifdef TERMIOS
     150:     struct termios tty, tty_normal;
     151:     sigmask_t     omask;
     152:
     153:     omask = sigblock(sigmask(SIGINT));
     154:     (void) tcgetattr(SHOUT, &tty);
     155:     tty_normal = tty;
     156:     tty.c_iflag &= ~INLCR;
     157:     tty.c_oflag &= ~ONLCR;
     158:     (void) tcsetattr(SHOUT, TCSANOW, &tty);
     159:     (void) write(SHOUT, "\r", 1);
     160:     (void) tcsetattr(SHOUT, TCSANOW, &tty_normal);
     161:     (void) sigsetmask(omask);
     162: #else
     163:     struct sgttyb tty, tty_normal;
     164:     sigmask_t     omask;
     165:
     166:     omask = sigblock(sigmask(SIGINT));
     167:     (void) ioctl(SHIN, TIOCGETP, (ioctl_t) & tty);
     168:     tty_normal = tty;
     169:     tty.sg_flags &= ~CRMOD;
     170:     (void) ioctl(SHIN, TIOCSETN, (ioctl_t) & tty);
     171:     (void) write(SHOUT, "\r", 1);
     172:     (void) ioctl(SHIN, TIOCSETN, (ioctl_t) & tty_normal);
     173:     (void) sigsetmask(omask);
     174: #endif
     175: }
     176:
     177: /*
     178:  * Push string contents back into tty queue
     179:  */
     180: static void
     181: pushback(string)
     182:     Char   *string;
     183: {
     184: #ifdef TERMIOS
     185:     register Char *p;
     186:     struct termios tty, tty_normal;
     187:     sigmask_t     omask;
     188:     char    c;
     189:
     190:     omask = sigblock(sigmask(SIGINT));
     191:     (void) tcgetattr(SHOUT, &tty);
     192:     tty_normal = tty;
     193:     tty.c_lflag &= ~(ECHOKE | ECHO | ECHOE | ECHOK | ECHONL | ECHOPRT | ECHOCTL);
     194:     (void) tcsetattr(SHOUT, TCSANOW, &tty);
     195:
     196:     for (p = string; c = *p; p++)
     197:     (void) ioctl(SHOUT, TIOCSTI, (ioctl_t) & c);
     198:     (void) tcsetattr(SHOUT, TCSANOW, &tty_normal);
     199:     (void) sigsetmask(omask);
     200: #else
     201:     register Char *p;
     202:     struct sgttyb tty, tty_normal;
     203:     sigmask_t     omask;
     204:     char    c;
     205:
     206:     omask = sigblock(sigmask(SIGINT));
     207:     (void) ioctl(SHOUT, TIOCGETP, (ioctl_t) & tty);
     208:     tty_normal = tty;
     209:     tty.sg_flags &= ~ECHO;
     210:     (void) ioctl(SHOUT, TIOCSETN, (ioctl_t) & tty);
     211:
     212:     for (p = string; c = *p; p++)
     213:     (void) ioctl(SHOUT, TIOCSTI, (ioctl_t) & c);
     214:     (void) ioctl(SHOUT, TIOCSETN, (ioctl_t) & tty_normal);
     215:     (void) sigsetmask(omask);
     216: #endif
     217: }
     218:
     219: /*
     220:  * Concatenate src onto tail of des.
     221:  * Des is a string whose maximum length is count.
     222:  * Always null terminate.
     223:  */
     224: static void
     225: catn(des, src, count)
     226:     register Char *des, *src;
     227:     register count;
     228: {
     229:     while (--count >= 0 && *des)
     230:     des++;
     231:     while (--count >= 0)
     232:     if ((*des++ = *src++) == 0)
     233:         return;
     234:     *des = '\0';
     235: }
     236:
     237: /*
     238:  * Like strncpy but always leave room for trailing \0
     239:  * and always null terminate.
     240:  */
     241: static void
     242: copyn(des, src, count)
     243:     register Char *des, *src;
     244:     register count;
     245: {
     246:     while (--count >= 0)
     247:     if ((*des++ = *src++) == 0)
     248:         return;
     249:     *des = '\0';
     250: }
     251:
     252: static  Char
     253: filetype(dir, file)
     254:     Char   *dir, *file;
     255: {
     256:     Char    path[MAXPATHLEN];
     257:     struct stat statb;
     258:
     259:     catn(Strcpy(path, dir), file, sizeof(path) / sizeof(Char));
     260:     if (lstat(short2str(path), &statb) == 0) {
     261:     switch (statb.st_mode & S_IFMT) {
     262:     case S_IFDIR:
     263:         return ('/');
     264:
     265:     case S_IFLNK:
     266:         if (stat(short2str(path), &statb) == 0 &&   /* follow it out */
     267:         S_ISDIR(statb.st_mode))
     268:         return ('>');
     269:         else
     270:         return ('@');
     271:
     272:     case S_IFSOCK:
     273:         return ('=');
     274:
     275:     default:
     276:         if (statb.st_mode & 0111)
     277:         return ('*');
     278:     }
     279:     }
     280:     return (' ');
     281: }
     282:
     283: static struct winsize win;
     284:
     285: /*
     286:  * Print sorted down columns
     287:  */
     288: static void
     289: print_by_column(dir, items, count)
     290:     Char   *dir, *items[];
     291:     int     count;
     292: {
     293:     register int i, rows, r, c, maxwidth = 0, columns;
     294:
     295:     if (ioctl(SHOUT, TIOCGWINSZ, (ioctl_t) & win) < 0 || win.ws_col == 0)
     296:     win.ws_col = 80;
     297:     for (i = 0; i < count; i++)
     298:     maxwidth = maxwidth > (r = Strlen(items[i])) ? maxwidth : r;
     299:     maxwidth += 2;      /* for the file tag and space */
     300:     columns = win.ws_col / maxwidth;
     301:     if (columns == 0)
     302:     columns = 1;
     303:     rows = (count + (columns - 1)) / columns;
     304:     for (r = 0; r < rows; r++) {
     305:     for (c = 0; c < columns; c++) {
     306:         i = c * rows + r;
     307:         if (i < count) {
     308:         register int w;
     309:
     310:         xprintf("%s", short2str(items[i]));
     311:         xputchar(dir ? filetype(dir, items[i]) : ' ');
     312:         if (c < columns - 1) {  /* last column? */
     313:             w = Strlen(items[i]) + 1;
     314:             for (; w < maxwidth; w++)
     315:             xputchar(' ');
     316:         }
     317:         }
     318:     }
     319:     xputchar('\r');
     320:     xputchar('\n');
     321:     }
     322: }
     323:
     324: /*
     325:  * Expand file name with possible tilde usage
     326:  *	~person/mumble
     327:  * expands to
     328:  *	home_directory_of_person/mumble
     329:  */
     330: static Char *
     331: tilde(new, old)
     332:     Char   *new, *old;
     333: {
     334:     register Char *o, *p;
     335:     register struct passwd *pw;
     336:     static Char person[40];
     337:
     338:     if (old[0] != '~')
     339:     return (Strcpy(new, old));
     340:
     341:     for (p = person, o = &old[1]; *o && *o != '/'; *p++ = *o++);
     342:     *p = '\0';
     343:     if (person[0] == '\0')
     344:     (void) Strcpy(new, value(STRhome));
     345:     else {
     346:     pw = getpwnam(short2str(person));
     347:     if (pw == NULL)
     348:         return (NULL);
     349:     (void) Strcpy(new, str2short(pw->pw_dir));
     350:     }
     351:     (void) Strcat(new, o);
     352:     return (new);
     353: }
     354:
     355: /*
     356:  * Cause pending line to be printed
     357:  */
     358: static void
     359: retype()
     360: {
     361: #ifdef TERMIOS
     362:     struct termios tty;
     363:
     364:     (void) tcgetattr(SHOUT, &tty);
     365:     tty.c_lflag |= PENDIN;
     366:     (void) tcsetattr(SHOUT, TCSANOW, &tty);
     367: #else
     368:     int     pending_input = LPENDIN;
     369:
     370:     (void) ioctl(SHOUT, TIOCLBIS, (ioctl_t) & pending_input);
     371: #endif
     372: }
     373:
     374: static void
     375: beep()
     376: {
     377:     if (adrof(STRnobeep) == 0)
     378:     (void) write(SHOUT, "\007", 1);
     379: }
     380:
     381: /*
     382:  * Erase that silly ^[ and
     383:  * print the recognized part of the string
     384:  */
     385: static void
     386: print_recog_stuff(recog_part)
     387:     Char   *recog_part;
     388: {
     389:     /* An optimized erasing of that silly ^[ */
     390:     putraw('\b');
     391:     putraw('\b');
     392:     switch (Strlen(recog_part)) {
     393:
     394:     case 0:         /* erase two Characters: ^[ */
     395:     putraw(' ');
     396:     putraw(' ');
     397:     putraw('\b');
     398:     putraw('\b');
     399:     break;
     400:
     401:     case 1:         /* overstrike the ^, erase the [ */
     402:     xprintf("%s", short2str(recog_part));
     403:     putraw(' ');
     404:     putraw('\b');
     405:     break;
     406:
     407:     default:            /* overstrike both Characters ^[ */
     408:     xprintf("%s", short2str(recog_part));
     409:     break;
     410:     }
     411:     flush();
     412: }
     413:
     414: /*
     415:  * Parse full path in file into 2 parts: directory and file names
     416:  * Should leave final slash (/) at end of dir.
     417:  */
     418: static void
     419: extract_dir_and_name(path, dir, name)
     420:     Char   *path, *dir, *name;
     421: {
     422:     register Char *p;
     423:
     424:     p = Strrchr(path, '/');
     425:     if (p == NULL) {
     426:     copyn(name, path, MAXNAMLEN);
     427:     dir[0] = '\0';
     428:     }
     429:     else {
     430:     copyn(name, ++p, MAXNAMLEN);
     431:     copyn(dir, path, p - path);
     432:     }
     433: }
     434:
     435: static Char *
     436: getentry(dir_fd, look_lognames)
     437:     DIR    *dir_fd;
     438:     int     look_lognames;
     439: {
     440:     register struct passwd *pw;
     441:     register struct dirent *dirp;
     442:
     443:     if (look_lognames) {
     444:     if ((pw = getpwent()) == NULL)
     445:         return (NULL);
     446:     return (str2short(pw->pw_name));
     447:     }
     448:     if (dirp = readdir(dir_fd))
     449:     return (str2short(dirp->d_name));
     450:     return (NULL);
     451: }
     452:
     453: static void
     454: free_items(items)
     455:     register Char **items;
     456: {
     457:     register int i;
     458:
     459:     for (i = 0; items[i]; i++)
     460:     xfree((ptr_t) items[i]);
     461:     xfree((ptr_t) items);
     462: }
     463:
     464: #define FREE_ITEMS(items) { \
     465:     sigmask_t omask;\
     466: \
     467:     omask = sigblock(sigmask(SIGINT));\
     468:     free_items(items);\
     469:     items = NULL;\
     470:     (void) sigsetmask(omask);\
     471: }
     472:
     473: /*
     474:  * Perform a RECOGNIZE or LIST command on string "word".
     475:  */
     476: static int
     477: tsearch(word, command, max_word_length)
     478:     Char   *word;
     479:     int     max_word_length;
     480:     COMMAND command;
     481: {
     482:     static Char **items = NULL;
     483:     register DIR *dir_fd;
     484:     register numitems = 0, ignoring = TRUE, nignored = 0;
     485:     register name_length, look_lognames;
     486:     Char    tilded_dir[MAXPATHLEN + 1], dir[MAXPATHLEN + 1];
     487:     Char    name[MAXNAMLEN + 1], extended_name[MAXNAMLEN + 1];
     488:     Char   *entry;
     489:
     490: #define MAXITEMS 1024
     491:
     492:     if (items != NULL)
     493:     FREE_ITEMS(items);
     494:
     495:     look_lognames = (*word == '~') && (Strchr(word, '/') == NULL);
     496:     if (look_lognames) {
     497:     (void) setpwent();
     498:     copyn(name, &word[1], MAXNAMLEN);   /* name sans ~ */
     499:     dir_fd = NULL;
     500:     }
     501:     else {
     502:     extract_dir_and_name(word, dir, name);
     503:     if (tilde(tilded_dir, dir) == 0)
     504:         return (0);
     505:     dir_fd = opendir(*tilded_dir ? short2str(tilded_dir) : ".");
     506:     if (dir_fd == NULL)
     507:         return (0);
     508:     }
     509:
     510: again:              /* search for matches */
     511:     name_length = Strlen(name);
     512:     for (numitems = 0; entry = getentry(dir_fd, look_lognames);) {
     513:     if (!is_prefix(name, entry))
     514:         continue;
     515:     /* Don't match . files on null prefix match */
     516:     if (name_length == 0 && entry[0] == '.' &&
     517:         !look_lognames)
     518:         continue;
     519:     if (command == LIST) {
     520:         if (numitems >= MAXITEMS) {
     521:         xprintf("\nYikes!! Too many %s!!\n",
     522:             look_lognames ?
     523:             "names in password file" : "files");
     524:         break;
     525:         }
     526:         if (items == NULL)
     527:         items = (Char **) xcalloc(sizeof(items[0]), MAXITEMS);
     528:         items[numitems] = (Char *) xmalloc((size_t) (Strlen(entry) + 1) *
     529:                            sizeof(Char));
     530:         copyn(items[numitems], entry, MAXNAMLEN);
     531:         numitems++;
     532:     }
     533:     else {          /* RECOGNIZE command */
     534:         if (ignoring && ignored(entry))
     535:         nignored++;
     536:         else if (recognize(extended_name,
     537:                    entry, name_length, ++numitems))
     538:         break;
     539:     }
     540:     }
     541:     if (ignoring && numitems == 0 && nignored > 0) {
     542:     ignoring = FALSE;
     543:     nignored = 0;
     544:     if (look_lognames)
     545:         (void) setpwent();
     546:     else
     547:         rewinddir(dir_fd);
     548:     goto again;
     549:     }
     550:
     551:     if (look_lognames)
     552:     (void) endpwent();
     553:     else
     554:     (void) closedir(dir_fd);
     555:     if (numitems == 0)
     556:     return (0);
     557:     if (command == RECOGNIZE) {
     558:     if (look_lognames)
     559:         copyn(word, STRtilde, 1);
     560:     else
     561:         /* put back dir part */
     562:         copyn(word, dir, max_word_length);
     563:     /* add extended name */
     564:     catn(word, extended_name, max_word_length);
     565:     return (numitems);
     566:     }
     567:     else {          /* LIST */
     568:     qsort((ptr_t) items, numitems, sizeof(items[0]), sortscmp);
     569:     print_by_column(look_lognames ? NULL : tilded_dir,
     570:             items, numitems);
     571:     if (items != NULL)
     572:         FREE_ITEMS(items);
     573:     }
     574:     return (0);
     575: }
     576:
     577: /*
     578:  * Object: extend what user typed up to an ambiguity.
     579:  * Algorithm:
     580:  * On first match, copy full entry (assume it'll be the only match)
     581:  * On subsequent matches, shorten extended_name to the first
     582:  * Character mismatch between extended_name and entry.
     583:  * If we shorten it back to the prefix length, stop searching.
     584:  */
     585: static int
     586: recognize(extended_name, entry, name_length, numitems)
     587:     Char   *extended_name, *entry;
     588:     int     name_length, numitems;
     589: {
     590:     if (numitems == 1)      /* 1st match */
     591:     copyn(extended_name, entry, MAXNAMLEN);
     592:     else {          /* 2nd & subsequent matches */
     593:     register Char *x, *ent;
     594:     register int len = 0;
     595:
     596:     x = extended_name;
     597:     for (ent = entry; *x && *x == *ent++; x++, len++);
     598:     *x = '\0';      /* Shorten at 1st Char diff */
     599:     if (len == name_length) /* Ambiguous to prefix? */
     600:         return (-1);    /* So stop now and save time */
     601:     }
     602:     return (0);
     603: }
     604:
     605: /*
     606:  * Return true if check matches initial Chars in template.
     607:  * This differs from PWB imatch in that if check is null
     608:  * it matches anything.
     609:  */
     610: static int
     611: is_prefix(check, template)
     612:     register Char *check, *template;
     613: {
     614:     do
     615:     if (*check == 0)
     616:         return (TRUE);
     617:     while (*check++ == *template++);
     618:     return (FALSE);
     619: }
     620:
     621: /*
     622:  *  Return true if the Chars in template appear at the
     623:  *  end of check, I.e., are it's suffix.
     624:  */
     625: static int
     626: is_suffix(check, template)
     627:     Char   *check, *template;
     628: {
     629:     register Char *c, *t;
     630:
     631:     for (c = check; *c++;);
     632:     for (t = template; *t++;);
     633:     for (;;) {
     634:     if (t == template)
     635:         return 1;
     636:     if (c == check || *--t != *--c)
     637:         return 0;
     638:     }
     639: }
     640:
     641: int
     642: tenex(in_line, in_li_size)
     643:     Char   *in_line;
     644:     int     in_li_size;
     645: {
     646:     register int numitems, num_read;
     647:     char    tin_line[BUFSIZ];
     648:
     649:
     650:     setup_tty(ON);
     651:
     652:     while ((num_read = read(SHIN, tin_line, BUFSIZ)) > 0) {
     653:     int     i;
     654:     static Char delims[] = {' ', '\'', '"', '\t', ';', '&', '<',
     655:     '>', '(', ')', '|', '^', '%', '\0'};
     656:     register Char *str_end, *word_start, last_Char, should_retype;
     657:     register int space_left;
     658:     COMMAND command;
     659:
     660:     for (i = 0; i < num_read; i++)
     661:         in_line[i] = (unsigned char) tin_line[i];
     662:     last_Char = in_line[num_read - 1] & ASCII;
     663:
     664:     if (last_Char == '\n' || num_read == in_li_size)
     665:         break;
     666:     command = (last_Char == ESC) ? RECOGNIZE : LIST;
     667:     if (command == LIST)
     668:         xputchar('\n');
     669:     str_end = &in_line[num_read];
     670:     if (last_Char == ESC)
     671:         --str_end;      /* wipeout trailing cmd Char */
     672:     *str_end = '\0';
     673:     /*
     674: 	 * Find LAST occurence of a delimiter in the in_line. The word start
     675: 	 * is one Character past it.
     676: 	 */
     677:     for (word_start = str_end; word_start > in_line; --word_start)
     678:         if (Strchr(delims, word_start[-1]))
     679:         break;
     680:     space_left = in_li_size - (word_start - in_line) - 1;
     681:     numitems = tsearch(word_start, command, space_left);
     682:
     683:     if (command == RECOGNIZE) {
     684:         /* print from str_end on */
     685:         print_recog_stuff(str_end);
     686:         if (numitems != 1)  /* Beep = No match/ambiguous */
     687:         beep();
     688:     }
     689:
     690:     /*
     691: 	 * Tabs in the input line cause trouble after a pushback. tty driver
     692: 	 * won't backspace over them because column positions are now
     693: 	 * incorrect. This is solved by retyping over current line.
     694: 	 */
     695:     should_retype = FALSE;
     696:     if (Strchr(in_line, '\t')) {    /* tab Char in input line? */
     697:         back_to_col_1();
     698:         should_retype = TRUE;
     699:     }
     700:     if (command == LIST)    /* Always retype after a LIST */
     701:         should_retype = TRUE;
     702:     if (should_retype)
     703:         printprompt();
     704:     pushback(in_line);
     705:     if (should_retype)
     706:         retype();
     707:     }
     708:     setup_tty(OFF);
     709:     return (num_read);
     710: }
     711:
     712: static int
     713: ignored(entry)
     714:     register Char *entry;
     715: {
     716:     struct varent *vp;
     717:     register Char **cp;
     718:
     719:     if ((vp = adrof(STRfignore)) == NULL || (cp = vp->vec) == NULL)
     720:     return (FALSE);
     721:     for (; *cp != NULL; cp++)
     722:     if (is_suffix(entry, *cp))
     723:         return (TRUE);
     724:     return (FALSE);
     725: }
     726: #endif				/* FILEC */

#### Defined functions

back_to_col_1 defined in line 146; used 1 times

- in line 697

beep defined in line 374; used 1 times

- in line 687

catn defined in line 224; used 2 times

- in line 259, 564

copyn defined in line 241; used 8 times

- in line 426-431(3), 498, 530, 559-562(2), 591

extract_dir_and_name defined in line 418; used 1 times

- in line 502

filetype defined in line 252; used 1 times

- in line 311

free_items defined in line 453; used 1 times

- in line 468

getentry defined in line 435; used 1 times

- in line 512

ignored defined in line 712; used 1 times

- in line 534

is_prefix defined in line 610; used 1 times

- in line 513

is_suffix defined in line 625; used 1 times

- in line 722

print_by_column defined in line 288; used 1 times

- in line 569

print_recog_stuff defined in line 385; used 1 times

- in line 685

pushback defined in line 180; used 1 times

- in line 704

rcsid defined in line 40; never used
recognize defined in line 585; used 1 times

- in line 536

retype defined in line 358; used 1 times

- in line 706

setup_tty defined in line 96; used 2 times

- in line 650, 708

tenex defined in line 641; never used
tilde defined in line 330; used 1 times

- in line 503

tsearch defined in line 476; used 1 times

- in line 681

#### Defined variables

filec defined in line 94; never used
win defined in line 283; used 4 times

- in line 295-300(4)

#### Defined typedef's

COMMAND defined in line 66; used 3 times

- in line 480-82(2), 658

#### Defined macros

ESC defined in line 62; used 4 times

- in line 105, 124, 666-670(2)

FALSE defined in line 59; used 6 times

- in line 58, 542, 618, 695, 720-724(2)

FREE_ITEMS defined in line 464; used 2 times

- in line 493, 572

MAXITEMS defined in line 490; used 2 times

- in line 520, 527

OFF defined in line 54; used 1 times

- in line 708

ON defined in line 53; used 1 times

- in line 650

TRUE defined in line 56; used 6 times

- in line 55, 484, 616, 698-701(2), 723

Last modified: 1991-08-30 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1292 |