1a5f0fb15SPaul Saab /* 2*c77c4889SXin LI * Copyright (C) 1984-2024 Mark Nudelman 3a5f0fb15SPaul Saab * 4a5f0fb15SPaul Saab * You may distribute under the terms of either the GNU General Public 5a5f0fb15SPaul Saab * License or the Less License, as specified in the README file. 6a5f0fb15SPaul Saab * 796e55cc7SXin LI * For more information, see the README file. 8a5f0fb15SPaul Saab */ 9a5f0fb15SPaul Saab 10a5f0fb15SPaul Saab 11a5f0fb15SPaul Saab /* 12a5f0fb15SPaul Saab * lessecho [-ox] [-cx] [-pn] [-dn] [-a] file ... 13a5f0fb15SPaul Saab * Simply echos its filename arguments on standard output. 14a5f0fb15SPaul Saab * But any argument containing spaces is enclosed in quotes. 15a5f0fb15SPaul Saab * 16a5f0fb15SPaul Saab * -ox Specifies "x" to be the open quote character. 17a5f0fb15SPaul Saab * -cx Specifies "x" to be the close quote character. 18a5f0fb15SPaul Saab * -pn Specifies "n" to be the open quote character, as an integer. 19a5f0fb15SPaul Saab * -dn Specifies "n" to be the close quote character, as an integer. 20000ba3e8STim J. Robbins * -mx Specifies "x" to be a metachar. 21000ba3e8STim J. Robbins * -nn Specifies "n" to be a metachar, as an integer. 22000ba3e8STim J. Robbins * -ex Specifies "x" to be the escape char for metachars. 23000ba3e8STim J. Robbins * -fn Specifies "x" to be the escape char for metachars, as an integer. 24a5f0fb15SPaul Saab * -a Specifies that all arguments are to be quoted. 25a5f0fb15SPaul Saab * The default is that only arguments containing spaces are quoted. 26a5f0fb15SPaul Saab */ 27a5f0fb15SPaul Saab 28a5f0fb15SPaul Saab #include "less.h" 29a5f0fb15SPaul Saab 3096e55cc7SXin LI static char *version = "$Revision: 1.15 $"; 31a5f0fb15SPaul Saab 32a5f0fb15SPaul Saab static int quote_all = 0; 33a5f0fb15SPaul Saab static char openquote = '"'; 34a5f0fb15SPaul Saab static char closequote = '"'; 35000ba3e8STim J. Robbins static char *meta_escape = "\\"; 36000ba3e8STim J. Robbins static char meta_escape_buf[2]; 3795270f73SXin LI static char* metachars = NULL; 38000ba3e8STim J. Robbins static int num_metachars = 0; 3995270f73SXin LI static int size_metachars = 0; 40a5f0fb15SPaul Saab 41d713e089SXin LI static void pr_usage(void) 42a5f0fb15SPaul Saab { 43a5f0fb15SPaul Saab fprintf(stderr, 44000ba3e8STim J. Robbins "usage: lessecho [-ox] [-cx] [-pn] [-dn] [-mx] [-nn] [-ex] [-fn] [-a] file ...\n"); 45a5f0fb15SPaul Saab } 46a5f0fb15SPaul Saab 47d713e089SXin LI static void pr_version(void) 48a5f0fb15SPaul Saab { 49a5f0fb15SPaul Saab char *p; 50a5f0fb15SPaul Saab char buf[10]; 51a5f0fb15SPaul Saab char *pbuf = buf; 52a5f0fb15SPaul Saab 53a5f0fb15SPaul Saab for (p = version; *p != ' '; p++) 54a5f0fb15SPaul Saab if (*p == '\0') 55a5f0fb15SPaul Saab return; 56a5f0fb15SPaul Saab for (p++; *p != '$' && *p != ' ' && *p != '\0'; p++) 57a5f0fb15SPaul Saab *pbuf++ = *p; 58a5f0fb15SPaul Saab *pbuf = '\0'; 59a5f0fb15SPaul Saab printf("%s\n", buf); 60a5f0fb15SPaul Saab } 61a5f0fb15SPaul Saab 62d713e089SXin LI static void pr_error(char *s) 63a5f0fb15SPaul Saab { 64a5f0fb15SPaul Saab fprintf(stderr, "%s\n", s); 65a5f0fb15SPaul Saab exit(1); 66a5f0fb15SPaul Saab } 67a5f0fb15SPaul Saab 68d713e089SXin LI static long lstrtol(char *s, char **pend, int radix) 69a5f0fb15SPaul Saab { 70a5f0fb15SPaul Saab int v; 71a5f0fb15SPaul Saab int neg = 0; 72a5f0fb15SPaul Saab long n = 0; 73a5f0fb15SPaul Saab 74a5f0fb15SPaul Saab /* Skip leading white space. */ 75a5f0fb15SPaul Saab while (*s == ' ' || *s == '\t') 76a5f0fb15SPaul Saab s++; 77a5f0fb15SPaul Saab 78a5f0fb15SPaul Saab /* Check for a leading + or -. */ 79a5f0fb15SPaul Saab if (*s == '-') 80a5f0fb15SPaul Saab { 81a5f0fb15SPaul Saab neg = 1; 82a5f0fb15SPaul Saab s++; 83a5f0fb15SPaul Saab } else if (*s == '+') 84a5f0fb15SPaul Saab { 85a5f0fb15SPaul Saab s++; 86a5f0fb15SPaul Saab } 87a5f0fb15SPaul Saab 88a5f0fb15SPaul Saab /* Determine radix if caller does not specify. */ 89a5f0fb15SPaul Saab if (radix == 0) 90a5f0fb15SPaul Saab { 91a5f0fb15SPaul Saab radix = 10; 92a5f0fb15SPaul Saab if (*s == '0') 93a5f0fb15SPaul Saab { 94a5f0fb15SPaul Saab switch (*++s) 95a5f0fb15SPaul Saab { 96a5f0fb15SPaul Saab case 'x': 97a5f0fb15SPaul Saab radix = 16; 98a5f0fb15SPaul Saab s++; 99a5f0fb15SPaul Saab break; 100a5f0fb15SPaul Saab default: 101a5f0fb15SPaul Saab radix = 8; 102a5f0fb15SPaul Saab break; 103a5f0fb15SPaul Saab } 104a5f0fb15SPaul Saab } 105a5f0fb15SPaul Saab } 106a5f0fb15SPaul Saab 107a5f0fb15SPaul Saab /* Parse the digits of the number. */ 108a5f0fb15SPaul Saab for (;;) 109a5f0fb15SPaul Saab { 110a5f0fb15SPaul Saab if (*s >= '0' && *s <= '9') 111a5f0fb15SPaul Saab v = *s - '0'; 112a5f0fb15SPaul Saab else if (*s >= 'a' && *s <= 'f') 113a5f0fb15SPaul Saab v = *s - 'a' + 10; 114a5f0fb15SPaul Saab else if (*s >= 'A' && *s <= 'F') 115a5f0fb15SPaul Saab v = *s - 'A' + 10; 116a5f0fb15SPaul Saab else 117a5f0fb15SPaul Saab break; 118a5f0fb15SPaul Saab if (v >= radix) 119a5f0fb15SPaul Saab break; 120a5f0fb15SPaul Saab n = n * radix + v; 121a5f0fb15SPaul Saab s++; 122a5f0fb15SPaul Saab } 123a5f0fb15SPaul Saab 124a5f0fb15SPaul Saab if (pend != NULL) 125a5f0fb15SPaul Saab { 126a5f0fb15SPaul Saab /* Skip trailing white space. */ 127a5f0fb15SPaul Saab while (*s == ' ' || *s == '\t') 128a5f0fb15SPaul Saab s++; 129a5f0fb15SPaul Saab *pend = s; 130a5f0fb15SPaul Saab } 131a5f0fb15SPaul Saab if (neg) 132a5f0fb15SPaul Saab return (-n); 133a5f0fb15SPaul Saab return (n); 134a5f0fb15SPaul Saab } 135a5f0fb15SPaul Saab 136*c77c4889SXin LI static void add_metachar(char ch) 13795270f73SXin LI { 13895270f73SXin LI if (num_metachars+1 >= size_metachars) 13995270f73SXin LI { 14095270f73SXin LI char *p; 14195270f73SXin LI size_metachars = (size_metachars > 0) ? size_metachars*2 : 16; 142*c77c4889SXin LI p = (char *) malloc((size_t) size_metachars); 14395270f73SXin LI if (p == NULL) 14495270f73SXin LI pr_error("Cannot allocate memory"); 14595270f73SXin LI 14695270f73SXin LI if (metachars != NULL) 14795270f73SXin LI { 14895270f73SXin LI strcpy(p, metachars); 14995270f73SXin LI free(metachars); 15095270f73SXin LI } 15195270f73SXin LI metachars = p; 15295270f73SXin LI } 15395270f73SXin LI metachars[num_metachars++] = ch; 15495270f73SXin LI metachars[num_metachars] = '\0'; 15595270f73SXin LI } 15695270f73SXin LI 157d713e089SXin LI static int is_metachar(int ch) 15895270f73SXin LI { 15995270f73SXin LI return (metachars != NULL && strchr(metachars, ch) != NULL); 16095270f73SXin LI } 161a5f0fb15SPaul Saab 162a5f0fb15SPaul Saab #if !HAVE_STRCHR 163d713e089SXin LI char * strchr(char *s, char c) 164a5f0fb15SPaul Saab { 165a5f0fb15SPaul Saab for ( ; *s != '\0'; s++) 166a5f0fb15SPaul Saab if (*s == c) 167a5f0fb15SPaul Saab return (s); 168a5f0fb15SPaul Saab if (c == '\0') 169a5f0fb15SPaul Saab return (s); 170a5f0fb15SPaul Saab return (NULL); 171a5f0fb15SPaul Saab } 172a5f0fb15SPaul Saab #endif 173a5f0fb15SPaul Saab 174d713e089SXin LI int main(int argc, char *argv[]) 175a5f0fb15SPaul Saab { 176a5f0fb15SPaul Saab char *arg; 177a5f0fb15SPaul Saab char *s; 178a5f0fb15SPaul Saab int no_more_options; 179a5f0fb15SPaul Saab 180a5f0fb15SPaul Saab no_more_options = 0; 181a5f0fb15SPaul Saab while (--argc > 0) 182a5f0fb15SPaul Saab { 183a5f0fb15SPaul Saab arg = *++argv; 184a5f0fb15SPaul Saab if (*arg != '-' || no_more_options) 185a5f0fb15SPaul Saab break; 186a5f0fb15SPaul Saab switch (*++arg) 187a5f0fb15SPaul Saab { 188a5f0fb15SPaul Saab case 'a': 189a5f0fb15SPaul Saab quote_all = 1; 190a5f0fb15SPaul Saab break; 191a5f0fb15SPaul Saab case 'c': 192a5f0fb15SPaul Saab closequote = *++arg; 193a5f0fb15SPaul Saab break; 194a5f0fb15SPaul Saab case 'd': 195*c77c4889SXin LI closequote = (char) lstrtol(++arg, &s, 0); 196a5f0fb15SPaul Saab if (s == arg) 197000ba3e8STim J. Robbins pr_error("Missing number after -d"); 198000ba3e8STim J. Robbins break; 199000ba3e8STim J. Robbins case 'e': 200000ba3e8STim J. Robbins if (strcmp(++arg, "-") == 0) 201000ba3e8STim J. Robbins meta_escape = ""; 202000ba3e8STim J. Robbins else 203000ba3e8STim J. Robbins meta_escape = arg; 204000ba3e8STim J. Robbins break; 205000ba3e8STim J. Robbins case 'f': 206*c77c4889SXin LI meta_escape_buf[0] = (char) lstrtol(++arg, &s, 0); 20795270f73SXin LI meta_escape_buf[1] = '\0'; 208000ba3e8STim J. Robbins meta_escape = meta_escape_buf; 209000ba3e8STim J. Robbins if (s == arg) 210000ba3e8STim J. Robbins pr_error("Missing number after -f"); 211000ba3e8STim J. Robbins break; 212000ba3e8STim J. Robbins case 'o': 213000ba3e8STim J. Robbins openquote = *++arg; 214000ba3e8STim J. Robbins break; 215000ba3e8STim J. Robbins case 'p': 216*c77c4889SXin LI openquote = (char) lstrtol(++arg, &s, 0); 217000ba3e8STim J. Robbins if (s == arg) 218000ba3e8STim J. Robbins pr_error("Missing number after -p"); 219000ba3e8STim J. Robbins break; 220000ba3e8STim J. Robbins case 'm': 22195270f73SXin LI add_metachar(*++arg); 222000ba3e8STim J. Robbins break; 223000ba3e8STim J. Robbins case 'n': 224*c77c4889SXin LI add_metachar((char) lstrtol(++arg, &s, 0)); 225000ba3e8STim J. Robbins if (s == arg) 226000ba3e8STim J. Robbins pr_error("Missing number after -n"); 227a5f0fb15SPaul Saab break; 228a5f0fb15SPaul Saab case '?': 229a5f0fb15SPaul Saab pr_usage(); 230a5f0fb15SPaul Saab return (0); 231a5f0fb15SPaul Saab case '-': 232a5f0fb15SPaul Saab if (*++arg == '\0') 233a5f0fb15SPaul Saab { 234a5f0fb15SPaul Saab no_more_options = 1; 235a5f0fb15SPaul Saab break; 236a5f0fb15SPaul Saab } 237a5f0fb15SPaul Saab if (strcmp(arg, "version") == 0) 238a5f0fb15SPaul Saab { 239a5f0fb15SPaul Saab pr_version(); 240a5f0fb15SPaul Saab return (0); 241a5f0fb15SPaul Saab } 242a5f0fb15SPaul Saab if (strcmp(arg, "help") == 0) 243a5f0fb15SPaul Saab { 244a5f0fb15SPaul Saab pr_usage(); 245a5f0fb15SPaul Saab return (0); 246a5f0fb15SPaul Saab } 247a5f0fb15SPaul Saab pr_error("Invalid option after --"); 248*c77c4889SXin LI return (0); 249a5f0fb15SPaul Saab default: 250a5f0fb15SPaul Saab pr_error("Invalid option letter"); 251a5f0fb15SPaul Saab } 252a5f0fb15SPaul Saab } 253a5f0fb15SPaul Saab 254a5f0fb15SPaul Saab while (argc-- > 0) 255a5f0fb15SPaul Saab { 256000ba3e8STim J. Robbins int has_meta = 0; 257a5f0fb15SPaul Saab arg = *argv++; 258000ba3e8STim J. Robbins for (s = arg; *s != '\0'; s++) 259000ba3e8STim J. Robbins { 26095270f73SXin LI if (is_metachar(*s)) 261000ba3e8STim J. Robbins { 262000ba3e8STim J. Robbins has_meta = 1; 263000ba3e8STim J. Robbins break; 264000ba3e8STim J. Robbins } 265000ba3e8STim J. Robbins } 266000ba3e8STim J. Robbins if (quote_all || (has_meta && strlen(meta_escape) == 0)) 267a5f0fb15SPaul Saab printf("%c%s%c", openquote, arg, closequote); 268a5f0fb15SPaul Saab else 269000ba3e8STim J. Robbins { 270000ba3e8STim J. Robbins for (s = arg; *s != '\0'; s++) 271000ba3e8STim J. Robbins { 27295270f73SXin LI if (is_metachar(*s)) 273000ba3e8STim J. Robbins printf("%s", meta_escape); 274000ba3e8STim J. Robbins printf("%c", *s); 275000ba3e8STim J. Robbins } 276000ba3e8STim J. Robbins } 277a5f0fb15SPaul Saab if (argc > 0) 278a5f0fb15SPaul Saab printf(" "); 279a5f0fb15SPaul Saab else 280a5f0fb15SPaul Saab printf("\n"); 281a5f0fb15SPaul Saab } 282a5f0fb15SPaul Saab return (0); 283a5f0fb15SPaul Saab } 284