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