1 /* 2 * Copyright (C) 1984-2015 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) 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) 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(char *s) 65 { 66 fprintf(stderr, "%s\n", s); 67 exit(1); 68 } 69 70 static long 71 lstrtol(char *s, int radix, char **pend) 72 { 73 int v; 74 int neg = 0; 75 long n = 0; 76 77 /* Skip leading white space. */ 78 while (*s == ' ' || *s == '\t') 79 s++; 80 81 /* Check for a leading + or -. */ 82 if (*s == '-') 83 { 84 neg = 1; 85 s++; 86 } else if (*s == '+') 87 { 88 s++; 89 } 90 91 /* Determine radix if caller does not specify. */ 92 if (radix == 0) 93 { 94 radix = 10; 95 if (*s == '0') 96 { 97 switch (*++s) 98 { 99 case 'x': 100 radix = 16; 101 s++; 102 break; 103 default: 104 radix = 8; 105 break; 106 } 107 } 108 } 109 110 /* Parse the digits of the number. */ 111 for (;;) 112 { 113 if (*s >= '0' && *s <= '9') 114 v = *s - '0'; 115 else if (*s >= 'a' && *s <= 'f') 116 v = *s - 'a' + 10; 117 else if (*s >= 'A' && *s <= 'F') 118 v = *s - 'A' + 10; 119 else 120 break; 121 if (v >= radix) 122 break; 123 n = n * radix + v; 124 s++; 125 } 126 127 if (pend != NULL) 128 { 129 /* Skip trailing white space. */ 130 while (*s == ' ' || *s == '\t') 131 s++; 132 *pend = s; 133 } 134 if (neg) 135 return (-n); 136 return (n); 137 } 138 139 140 #if !HAVE_STRCHR 141 char * 142 strchr(s, c) 143 char *s; 144 int c; 145 { 146 for ( ; *s != '\0'; s++) 147 if (*s == c) 148 return (s); 149 if (c == '\0') 150 return (s); 151 return (NULL); 152 } 153 #endif 154 155 int 156 main(argc, argv) 157 int argc; 158 char *argv[]; 159 { 160 char *arg; 161 char *s; 162 int no_more_options; 163 164 no_more_options = 0; 165 while (--argc > 0) 166 { 167 arg = *++argv; 168 if (*arg != '-' || no_more_options) 169 break; 170 switch (*++arg) 171 { 172 case 'a': 173 quote_all = 1; 174 break; 175 case 'c': 176 closequote = *++arg; 177 break; 178 case 'd': 179 closequote = lstrtol(++arg, 0, &s); 180 if (s == arg) 181 pr_error("Missing number after -d"); 182 break; 183 case 'e': 184 if (strcmp(++arg, "-") == 0) 185 meta_escape = ""; 186 else 187 meta_escape = arg; 188 break; 189 case 'f': 190 meta_escape_buf[0] = lstrtol(++arg, 0, &s); 191 meta_escape = meta_escape_buf; 192 if (s == arg) 193 pr_error("Missing number after -f"); 194 break; 195 case 'o': 196 openquote = *++arg; 197 break; 198 case 'p': 199 openquote = lstrtol(++arg, 0, &s); 200 if (s == arg) 201 pr_error("Missing number after -p"); 202 break; 203 case 'm': 204 metachars[num_metachars++] = *++arg; 205 metachars[num_metachars] = '\0'; 206 break; 207 case 'n': 208 metachars[num_metachars++] = lstrtol(++arg, 0, &s); 209 if (s == arg) 210 pr_error("Missing number after -n"); 211 metachars[num_metachars] = '\0'; 212 break; 213 case '?': 214 pr_usage(); 215 return (0); 216 case '-': 217 if (*++arg == '\0') 218 { 219 no_more_options = 1; 220 break; 221 } 222 if (strcmp(arg, "version") == 0) 223 { 224 pr_version(); 225 return (0); 226 } 227 if (strcmp(arg, "help") == 0) 228 { 229 pr_usage(); 230 return (0); 231 } 232 pr_error("Invalid option after --"); 233 default: 234 pr_error("Invalid option letter"); 235 } 236 } 237 238 while (argc-- > 0) 239 { 240 int has_meta = 0; 241 arg = *argv++; 242 for (s = arg; *s != '\0'; s++) 243 { 244 if (strchr(metachars, *s) != NULL) 245 { 246 has_meta = 1; 247 break; 248 } 249 } 250 if (quote_all || (has_meta && strlen(meta_escape) == 0)) 251 printf("%c%s%c", openquote, arg, closequote); 252 else 253 { 254 for (s = arg; *s != '\0'; s++) 255 { 256 if (strchr(metachars, *s) != NULL) 257 printf("%s", meta_escape); 258 printf("%c", *s); 259 } 260 } 261 if (argc > 0) 262 printf(" "); 263 else 264 printf("\n"); 265 } 266 return (0); 267 } 268