1 /* 2 * Copyright (C) 1984-2021 Mark Nudelman 3 * 4 * You may distribute under the terms of either the GNU General Public 5 * License or the Less License, as specified in the README file. 6 * 7 * For more information, see the README file. 8 */ 9 10 11 /* 12 * lessecho [-ox] [-cx] [-pn] [-dn] [-a] file ... 13 * Simply echos its filename arguments on standard output. 14 * But any argument containing spaces is enclosed in quotes. 15 * 16 * -ox Specifies "x" to be the open quote character. 17 * -cx Specifies "x" to be the close quote character. 18 * -pn Specifies "n" to be the open quote character, as an integer. 19 * -dn Specifies "n" to be the close quote character, as an integer. 20 * -mx Specifies "x" to be a metachar. 21 * -nn Specifies "n" to be a metachar, as an integer. 22 * -ex Specifies "x" to be the escape char for metachars. 23 * -fn Specifies "x" to be the escape char for metachars, as an integer. 24 * -a Specifies that all arguments are to be quoted. 25 * The default is that only arguments containing spaces are quoted. 26 */ 27 28 #include "less.h" 29 30 static char *version = "$Revision: 1.15 $"; 31 32 static int quote_all = 0; 33 static char openquote = '"'; 34 static char closequote = '"'; 35 static char *meta_escape = "\\"; 36 static char meta_escape_buf[2]; 37 static char metachars[64] = ""; 38 static int num_metachars = 0; 39 40 static void 41 pr_usage(VOID_PARAM) 42 { 43 fprintf(stderr, 44 "usage: lessecho [-ox] [-cx] [-pn] [-dn] [-mx] [-nn] [-ex] [-fn] [-a] file ...\n"); 45 } 46 47 static void 48 pr_version(VOID_PARAM) 49 { 50 char *p; 51 char buf[10]; 52 char *pbuf = buf; 53 54 for (p = version; *p != ' '; p++) 55 if (*p == '\0') 56 return; 57 for (p++; *p != '$' && *p != ' ' && *p != '\0'; p++) 58 *pbuf++ = *p; 59 *pbuf = '\0'; 60 printf("%s\n", buf); 61 } 62 63 static void 64 pr_error(s) 65 char *s; 66 { 67 fprintf(stderr, "%s\n", s); 68 exit(1); 69 } 70 71 static long 72 lstrtol(s, radix, pend) 73 char *s; 74 int radix; 75 char **pend; 76 { 77 int v; 78 int neg = 0; 79 long n = 0; 80 81 /* Skip leading white space. */ 82 while (*s == ' ' || *s == '\t') 83 s++; 84 85 /* Check for a leading + or -. */ 86 if (*s == '-') 87 { 88 neg = 1; 89 s++; 90 } else if (*s == '+') 91 { 92 s++; 93 } 94 95 /* Determine radix if caller does not specify. */ 96 if (radix == 0) 97 { 98 radix = 10; 99 if (*s == '0') 100 { 101 switch (*++s) 102 { 103 case 'x': 104 radix = 16; 105 s++; 106 break; 107 default: 108 radix = 8; 109 break; 110 } 111 } 112 } 113 114 /* Parse the digits of the number. */ 115 for (;;) 116 { 117 if (*s >= '0' && *s <= '9') 118 v = *s - '0'; 119 else if (*s >= 'a' && *s <= 'f') 120 v = *s - 'a' + 10; 121 else if (*s >= 'A' && *s <= 'F') 122 v = *s - 'A' + 10; 123 else 124 break; 125 if (v >= radix) 126 break; 127 n = n * radix + v; 128 s++; 129 } 130 131 if (pend != NULL) 132 { 133 /* Skip trailing white space. */ 134 while (*s == ' ' || *s == '\t') 135 s++; 136 *pend = s; 137 } 138 if (neg) 139 return (-n); 140 return (n); 141 } 142 143 144 #if !HAVE_STRCHR 145 char * 146 strchr(s, c) 147 char *s; 148 int c; 149 { 150 for ( ; *s != '\0'; s++) 151 if (*s == c) 152 return (s); 153 if (c == '\0') 154 return (s); 155 return (NULL); 156 } 157 #endif 158 159 int 160 main(argc, argv) 161 int argc; 162 char *argv[]; 163 { 164 char *arg; 165 char *s; 166 int no_more_options; 167 168 no_more_options = 0; 169 while (--argc > 0) 170 { 171 arg = *++argv; 172 if (*arg != '-' || no_more_options) 173 break; 174 switch (*++arg) 175 { 176 case 'a': 177 quote_all = 1; 178 break; 179 case 'c': 180 closequote = *++arg; 181 break; 182 case 'd': 183 closequote = lstrtol(++arg, 0, &s); 184 if (s == arg) 185 pr_error("Missing number after -d"); 186 break; 187 case 'e': 188 if (strcmp(++arg, "-") == 0) 189 meta_escape = ""; 190 else 191 meta_escape = arg; 192 break; 193 case 'f': 194 meta_escape_buf[0] = lstrtol(++arg, 0, &s); 195 meta_escape = meta_escape_buf; 196 if (s == arg) 197 pr_error("Missing number after -f"); 198 break; 199 case 'o': 200 openquote = *++arg; 201 break; 202 case 'p': 203 openquote = lstrtol(++arg, 0, &s); 204 if (s == arg) 205 pr_error("Missing number after -p"); 206 break; 207 case 'm': 208 metachars[num_metachars++] = *++arg; 209 metachars[num_metachars] = '\0'; 210 break; 211 case 'n': 212 metachars[num_metachars++] = lstrtol(++arg, 0, &s); 213 if (s == arg) 214 pr_error("Missing number after -n"); 215 metachars[num_metachars] = '\0'; 216 break; 217 case '?': 218 pr_usage(); 219 return (0); 220 case '-': 221 if (*++arg == '\0') 222 { 223 no_more_options = 1; 224 break; 225 } 226 if (strcmp(arg, "version") == 0) 227 { 228 pr_version(); 229 return (0); 230 } 231 if (strcmp(arg, "help") == 0) 232 { 233 pr_usage(); 234 return (0); 235 } 236 pr_error("Invalid option after --"); 237 default: 238 pr_error("Invalid option letter"); 239 } 240 } 241 242 while (argc-- > 0) 243 { 244 int has_meta = 0; 245 arg = *argv++; 246 for (s = arg; *s != '\0'; s++) 247 { 248 if (strchr(metachars, *s) != NULL) 249 { 250 has_meta = 1; 251 break; 252 } 253 } 254 if (quote_all || (has_meta && strlen(meta_escape) == 0)) 255 printf("%c%s%c", openquote, arg, closequote); 256 else 257 { 258 for (s = arg; *s != '\0'; s++) 259 { 260 if (strchr(metachars, *s) != NULL) 261 printf("%s", meta_escape); 262 printf("%c", *s); 263 } 264 } 265 if (argc > 0) 266 printf(" "); 267 else 268 printf("\n"); 269 } 270 return (0); 271 } 272