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