diff options
author | tjr <tjr@FreeBSD.org> | 2004-04-17 07:16:34 +0000 |
---|---|---|
committer | tjr <tjr@FreeBSD.org> | 2004-04-17 07:16:34 +0000 |
commit | 44c4d557e2436dfbb703a9fc3e78fac79c574d4b (patch) | |
tree | f46d7e51d83360c5b6bdacf5b08e16a415ed61b5 /contrib/less/filename.c | |
parent | c0c85bc41cb6c023adae56cf0a7e3495bd528cb2 (diff) | |
download | FreeBSD-src-44c4d557e2436dfbb703a9fc3e78fac79c574d4b.zip FreeBSD-src-44c4d557e2436dfbb703a9fc3e78fac79c574d4b.tar.gz |
Import less v381.
Diffstat (limited to 'contrib/less/filename.c')
-rw-r--r-- | contrib/less/filename.c | 487 |
1 files changed, 245 insertions, 242 deletions
diff --git a/contrib/less/filename.c b/contrib/less/filename.c index bfbbfdb..0b56bdc 100644 --- a/contrib/less/filename.c +++ b/contrib/less/filename.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2000 Mark Nudelman + * Copyright (C) 1984-2002 Mark Nudelman * * You may distribute under the terms of either the GNU General Public * License or the Less License, as specified in the README file. @@ -50,6 +50,7 @@ extern int force_open; extern int secure; +extern int use_lessopen; extern IFILE curr_ifile; extern IFILE old_ifile; #if SPACES_IN_FILENAMES @@ -61,24 +62,157 @@ extern char closequote; * Remove quotes around a filename. */ public char * -unquote_file(str) +shell_unquote(str) char *str; { -#if SPACES_IN_FILENAMES char *name; char *p; - if (*str != openquote) - return (save(str)); - name = (char *) ecalloc(strlen(str), sizeof(char)); - strcpy(name, str+1); - p = name + strlen(name) - 1; - if (*p == closequote) - *p = '\0'; + name = p = (char *) ecalloc(strlen(str)+1, sizeof(char)); + if (*str == openquote) + { + str++; + while (*str != '\0') + { + if (*str == closequote) + { + if (str[1] != closequote) + break; + str++; + } + *p++ = *str++; + } + } else + { + char *esc = get_meta_escape(); + int esclen = strlen(esc); + while (*str != '\0') + { + if (esclen > 0 && strncmp(str, esc, esclen) == 0) + str += esclen; + *p++ = *str++; + } + } + *p = '\0'; return (name); -#else - return (save(str)); -#endif +} + +/* + * Get the shell's escape character. + */ + public char * +get_meta_escape() +{ + char *s; + + s = lgetenv("LESSMETAESCAPE"); + if (s == NULL) + s = DEF_METAESCAPE; + return (s); +} + +/* + * Get the characters which the shell considers to be "metacharacters". + */ + static char * +metachars() +{ + static char *mchars = NULL; + + if (mchars == NULL) + { + mchars = lgetenv("LESSMETACHARS"); + if (mchars == NULL) + mchars = DEF_METACHARS; + } + return (mchars); +} + +/* + * Is this a shell metacharacter? + */ + static int +metachar(c) + char c; +{ + return (strchr(metachars(), c) != NULL); +} + +/* + * Insert a backslash before each metacharacter in a string. + */ + public char * +shell_quote(s) + char *s; +{ + char *p; + char *newstr; + int len; + char *esc = get_meta_escape(); + int esclen = strlen(esc); + int use_quotes = 0; + int have_quotes = 0; + + /* + * Determine how big a string we need to allocate. + */ + len = 1; /* Trailing null byte */ + for (p = s; *p != '\0'; p++) + { + len++; + if (*p == openquote || *p == closequote) + have_quotes = 1; + if (metachar(*p)) + { + if (esclen == 0) + { + /* + * We've got a metachar, but this shell + * doesn't support escape chars. Use quotes. + */ + use_quotes = 1; + } else + { + /* + * Allow space for the escape char. + */ + len += esclen; + } + } + } + if (use_quotes) + { + if (have_quotes) + /* + * We can't quote a string that contains quotes. + */ + return (NULL); + len = strlen(s) + 3; + } + /* + * Allocate and construct the new string. + */ + newstr = p = (char *) ecalloc(len, sizeof(char)); + if (use_quotes) + { + sprintf(newstr, "%c%s%c", openquote, s, closequote); + } else + { + while (*s != '\0') + { + if (metachar(*s)) + { + /* + * Add the escape char. + */ + strcpy(p, esc); + p += esclen; + } + *p++ = *s++; + } + *p = '\0'; + } + return (newstr); } /* @@ -107,7 +241,7 @@ dirfile(dirname, filename) /* * Make sure the file exists. */ - qpathname = unquote_file(pathname); + qpathname = shell_unquote(pathname); f = open(qpathname, OPEN_READ); if (f < 0) { @@ -274,6 +408,7 @@ fcomplete(s) char *s; { char *fpat; + char *qs; if (secure) return (NULL); @@ -303,17 +438,19 @@ fcomplete(s) fpat = (char *) ecalloc(strlen(s)+2, sizeof(char)); sprintf(fpat, "%s*", s); #endif - s = lglob(fpat); + qs = lglob(fpat); + s = shell_unquote(qs); if (strcmp(s,fpat) == 0) { /* * The filename didn't expand. */ - free(s); - s = NULL; + free(qs); + qs = NULL; } + free(s); free(fpat); - return (s); + return (qs); } #endif @@ -398,108 +535,6 @@ readfd(fd) return (buf); } -#if HAVE_SHELL - -/* - * Get the shell's escape character. - */ - static char * -get_meta_escape() -{ - char *s; - - s = lgetenv("LESSMETAESCAPE"); - if (s == NULL) - s = DEF_METAESCAPE; - return (s); -} - -/* - * Is this a shell metacharacter? - */ - static int -metachar(c) - char c; -{ - static char *metachars = NULL; - - if (metachars == NULL) - { - metachars = lgetenv("LESSMETACHARS"); - if (metachars == NULL) - metachars = DEF_METACHARS; - } - return (strchr(metachars, c) != NULL); -} - -/* - * Insert a backslash before each metacharacter in a string. - */ - public char * -esc_metachars(s) - char *s; -{ - char *p; - char *newstr; - int len; - char *esc; - int esclen; - - /* - * Determine how big a string we need to allocate. - */ - esc = get_meta_escape(); - esclen = strlen(esc); - len = 1; /* Trailing null byte */ - for (p = s; *p != '\0'; p++) - { - len++; - if (metachar(*p)) - { - if (*esc == '\0') - { - /* - * We've got a metachar, but this shell - * doesn't support escape chars. Give up. - */ - return (NULL); - } - /* - * Allow space for the escape char. - */ - len += esclen; - } - } - /* - * Allocate and construct the new string. - */ - newstr = p = (char *) ecalloc(len, sizeof(char)); - while (*s != '\0') - { - if (metachar(*s)) - { - /* - * Add the escape char. - */ - strcpy(p, esc); - p += esclen; - } - *p++ = *s++; - } - *p = '\0'; - return (newstr); -} - -#else /* HAVE_SHELL */ - - public char * -esc_metachars(s) - char *s; -{ - return (save(s)); -} - -#endif /* HAVE_SHELL */ #if HAVE_POPEN @@ -526,43 +561,32 @@ shellcmd(cmd) char *esccmd; /* - * Try to escape any metacharacters in the command. - * If we can't do that, just put the command in quotes. - * (But that doesn't work well if the command itself - * contains quotes.) + * Read the output of <$SHELL -c cmd>. + * Escape any metacharacters in the command. */ - if ((esccmd = esc_metachars(cmd)) == NULL) + esccmd = shell_quote(cmd); + if (esccmd == NULL) { - /* - * Cannot escape the metacharacters, so use quotes. - * Read the output of <$SHELL -c "cmd">. - */ - scmd = (char *) ecalloc(strlen(shell) + strlen(cmd) + 7, - sizeof(char)); - sprintf(scmd, "%s -c \"%s\"", shell, cmd); + fd = popen(cmd, "r"); } else { - /* - * Read the output of <$SHELL -c cmd>. - * No quotes; use the escaped cmd. - */ scmd = (char *) ecalloc(strlen(shell) + strlen(esccmd) + 5, sizeof(char)); - sprintf(scmd, "%s -c %s", shell, esccmd); + sprintf(scmd, "%s %s %s", shell, shell_coption(), esccmd); free(esccmd); + fd = popen(scmd, "r"); + free(scmd); } - fd = popen(scmd, "r"); - free(scmd); } else #endif { fd = popen(cmd, "r"); - /* - * Redirection in `popen' might have messed with the - * standard devices. Restore binary input mode. - */ - SET_BINARY(0); } + /* + * Redirection in `popen' might have messed with the + * standard devices. Restore binary input mode. + */ + SET_BINARY(0); return (fd); } @@ -582,7 +606,7 @@ lglob(filename) ofilename = fexpand(filename); if (secure) return (ofilename); - filename = unquote_file(ofilename); + filename = shell_unquote(ofilename); #ifdef DECL_GLOB_LIST { @@ -591,6 +615,7 @@ lglob(filename) */ int length; char *p; + char *qfilename; DECL_GLOB_LIST(list) GLOB_LIST(filename, list); @@ -603,23 +628,23 @@ lglob(filename) for (SCAN_GLOB_LIST(list, p)) { INIT_GLOB_LIST(list, p); - length += strlen(p) + 1; -#if SPACES_IN_FILENAMES - if (strchr(p, ' ') != NULL) - length += 2; /* Allow for quotes */ -#endif + qfilename = shell_quote(p); + if (qfilename != NULL) + { + length += strlen(qfilename) + 1; + free(qfilename); + } } gfilename = (char *) ecalloc(length, sizeof(char)); for (SCAN_GLOB_LIST(list, p)) { INIT_GLOB_LIST(list, p); -#if SPACES_IN_FILENAMES - if (strchr(p, ' ') != NULL) - sprintf(gfilename + strlen(gfilename), "%c%s%c ", - openquote, p, closequote); - else -#endif - sprintf(gfilename + strlen(gfilename), "%s ", p); + qfilename = shell_quote(p); + if (qfilename != NULL) + { + sprintf(gfilename + strlen(gfilename), "%s ", qfilename); + free(qfilename); + } } /* * Overwrite the final trailing space with a null terminator. @@ -637,9 +662,8 @@ lglob(filename) register char *p; register int len; register int n; -#if SPACES_IN_FILENAMES - register int spaces_in_file; -#endif + char *pathname; + char *qpathname; DECL_GLOB_NAME(fnd,drive,dir,fname,ext,handle) GLOB_FIRST_NAME(filename, &fnd, handle); @@ -655,36 +679,32 @@ lglob(filename) p = gfilename; do { n = strlen(drive) + strlen(dir) + strlen(fnd.GLOB_NAME) + 1; -#if SPACES_IN_FILENAMES - spaces_in_file = 0; - if (strchr(fnd.GLOB_NAME, ' ') != NULL || - strchr(filename, ' ') != NULL) - { - spaces_in_file = 1; - n += 2; - } -#endif - while (p - gfilename + n+2 >= len) + pathname = (char *) ecalloc(n, sizeof(char)); + sprintf(pathname, "%s%s%s", drive, dir, fnd.GLOB_NAME); + qpathname = shell_quote(pathname); + free(pathname); + if (qpathname != NULL) { - /* - * No room in current buffer. Allocate a bigger one. - */ - len *= 2; - *p = '\0'; - p = (char *) ecalloc(len, sizeof(char)); - strcpy(p, gfilename); - free(gfilename); - gfilename = p; - p = gfilename + strlen(gfilename); + n = strlen(qpathname); + while (p - gfilename + n + 2 >= len) + { + /* + * No room in current buffer. + * Allocate a bigger one. + */ + len *= 2; + *p = '\0'; + p = (char *) ecalloc(len, sizeof(char)); + strcpy(p, gfilename); + free(gfilename); + gfilename = p; + p = gfilename + strlen(gfilename); + } + strcpy(p, qpathname); + free(qpathname); + p += n; + *p++ = ' '; } -#if SPACES_IN_FILENAMES - if (spaces_in_file) - sprintf(p, "%c%s%s%s%c ", openquote, - drive, dir, fnd.GLOB_NAME, closequote); - else -#endif - sprintf(p, "%s%s%s ", drive, dir, fnd.GLOB_NAME); - p += n; } while (GLOB_NEXT_NAME(handle, &fnd) == 0); /* @@ -704,30 +724,30 @@ lglob(filename) char *s; char *lessecho; char *cmd; + char *esc; - lessecho = lgetenv("LESSECHO"); - if (lessecho == NULL || *lessecho == '\0') - lessecho = "lessecho"; - s = esc_metachars(filename); - if (s == NULL) + esc = get_meta_escape(); + if (strlen(esc) == 0) + esc = "-"; + esc = shell_quote(esc); + if (esc == NULL) { - /* - * There may be dangerous metachars in this name. - * We can't risk passing it to the shell. - * {{ For example, do "!;TAB" when the first file - * in the dir is named "rm". }} - */ free(filename); return (ofilename); } + lessecho = lgetenv("LESSECHO"); + if (lessecho == NULL || *lessecho == '\0') + lessecho = "lessecho"; /* * Invoke lessecho, and read its output (a globbed list of filenames). */ - cmd = (char *) ecalloc(strlen(lessecho) + strlen(s) + 24, sizeof(char)); - sprintf(cmd, "%s -p0x%x -d0x%x -- %s", - lessecho, openquote, closequote, s); + cmd = (char *) ecalloc(strlen(lessecho) + strlen(ofilename) + (7*strlen(metachars())) + 24, sizeof(char)); + sprintf(cmd, "%s -p0x%x -d0x%x -e%s ", lessecho, openquote, closequote, esc); + free(esc); + for (s = metachars(); *s != '\0'; s++) + sprintf(cmd + strlen(cmd), "-n0x%x ", *s); + sprintf(cmd + strlen(cmd), "-- %s", ofilename); fd = shellcmd(cmd); - free(s); free(cmd); if (fd == NULL) { @@ -774,14 +794,13 @@ open_altfile(filename, pf, pfd) return (NULL); #else char *lessopen; - char *gfilename; char *cmd; FILE *fd; #if HAVE_FILENO int returnfd = 0; #endif - if (secure) + if (!use_lessopen || secure) return (NULL); ch_ungetchar(-1); if ((lessopen = lgetenv("LESSOPEN")) == NULL) @@ -803,19 +822,10 @@ open_altfile(filename, pf, pfd) #endif } - gfilename = esc_metachars(filename); - if (gfilename == NULL) - { - /* - * Cannot escape metacharacters. - */ - return (NULL); - } - cmd = (char *) ecalloc(strlen(lessopen) + strlen(gfilename) + 2, + cmd = (char *) ecalloc(strlen(lessopen) + strlen(filename) + 2, sizeof(char)); - sprintf(cmd, lessopen, gfilename); + sprintf(cmd, lessopen, filename); fd = shellcmd(cmd); - free(gfilename); free(cmd); if (fd == NULL) { @@ -850,14 +860,14 @@ open_altfile(filename, pf, pfd) return (save("-")); } #endif - gfilename = readfd(fd); + cmd = readfd(fd); pclose(fd); - if (*gfilename == '\0') + if (*cmd == '\0') /* * Pipe is empty. This means there is no alt file. */ return (NULL); - return (gfilename); + return (cmd); #endif /* HAVE_POPEN */ } @@ -872,8 +882,6 @@ close_altfile(altfilename, filename, pipefd) { #if HAVE_POPEN char *lessclose; - char *gfilename; - char *galtfilename; FILE *fd; char *cmd; @@ -892,23 +900,10 @@ close_altfile(altfilename, filename, pipefd) } if ((lessclose = lgetenv("LESSCLOSE")) == NULL) return; - gfilename = esc_metachars(filename); - if (gfilename == NULL) - { - return; - } - galtfilename = esc_metachars(altfilename); - if (galtfilename == NULL) - { - free(gfilename); - return; - } - cmd = (char *) ecalloc(strlen(lessclose) + strlen(gfilename) + - strlen(galtfilename) + 2, sizeof(char)); - sprintf(cmd, lessclose, gfilename, galtfilename); + cmd = (char *) ecalloc(strlen(lessclose) + strlen(filename) + + strlen(altfilename) + 2, sizeof(char)); + sprintf(cmd, lessclose, filename, altfilename); fd = shellcmd(cmd); - free(galtfilename); - free(gfilename); free(cmd); if (fd != NULL) pclose(fd); @@ -924,7 +919,7 @@ is_dir(filename) { int isdir = 0; - filename = unquote_file(filename); + filename = shell_unquote(filename); #if HAVE_STAT { int r; @@ -960,15 +955,15 @@ bad_file(filename) { register char *m = NULL; - filename = unquote_file(filename); + filename = shell_unquote(filename); if (is_dir(filename)) { - static char is_dir[] = " is a directory"; + static char is_a_dir[] = " is a directory"; - m = (char *) ecalloc(strlen(filename) + sizeof(is_dir), + m = (char *) ecalloc(strlen(filename) + sizeof(is_a_dir), sizeof(char)); strcpy(m, filename); - strcat(m, is_dir); + strcat(m, is_a_dir); } else { #if HAVE_STAT @@ -1020,3 +1015,11 @@ filesize(f) return (seek_filesize(f)); } +/* + * + */ + public char * +shell_coption() +{ + return ("-c"); +} |