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