Annotation of src/usr.bin/jot/jot.c, Revision 1.15
1.15 ! otto 1: /* $OpenBSD: jot.c,v 1.14 2003/12/15 23:24:20 jmc Exp $ */
1.1 deraadt 2: /* $NetBSD: jot.c,v 1.3 1994/12/02 20:29:43 pk Exp $ */
3:
4: /*-
5: * Copyright (c) 1993
6: * The Regents of the University of California. All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
1.12 millert 16: * 3. Neither the name of the University nor the names of its contributors
1.1 deraadt 17: * may be used to endorse or promote products derived from this software
18: * without specific prior written permission.
19: *
20: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30: * SUCH DAMAGE.
31: */
32:
33: #ifndef lint
1.15 ! otto 34: static const char copyright[] =
1.1 deraadt 35: "@(#) Copyright (c) 1993\n\
36: The Regents of the University of California. All rights reserved.\n";
37: #endif /* not lint */
38:
39: #ifndef lint
40: #if 0
41: static char sccsid[] = "@(#)jot.c 8.1 (Berkeley) 6/6/93";
42: #endif
1.15 ! otto 43: static const char rcsid[] = "$OpenBSD: jot.c,v 1.14 2003/12/15 23:24:20 jmc Exp $";
1.1 deraadt 44: #endif /* not lint */
45:
46: /*
47: * jot - print sequential or random data
48: *
49: * Author: John Kunze, Office of Comp. Affairs, UCB
50: */
51:
1.7 aaron 52: #include <err.h>
1.15 ! otto 53: #include <stdbool.h>
1.1 deraadt 54: #include <ctype.h>
55: #include <limits.h>
56: #include <stdio.h>
57: #include <stdlib.h>
58: #include <string.h>
59: #include <time.h>
60:
61: #define REPS_DEF 100
62: #define BEGIN_DEF 1
63: #define ENDER_DEF 100
64: #define STEP_DEF 1
65:
1.8 pjanzen 66: #define is_default(s) (strcmp((s), "-") == 0)
1.1 deraadt 67:
1.15 ! otto 68: static double begin;
! 69: static double ender;
! 70: static double s;
! 71: static long reps;
! 72: static bool randomize;
! 73: static bool infinity;
! 74: static bool boring;
! 75: static int prec = -1;
! 76: static bool dox;
! 77: static bool chardata;
! 78: static bool finalnl = true;
! 79: static char sepstring[BUFSIZ] = "\n";
! 80: static char format[BUFSIZ];
! 81:
! 82: static void getformat(void);
! 83: static int getprec(char *);
! 84: static void putdata(double, bool);
1.9 millert 85: static void usage(void);
1.1 deraadt 86:
87: int
1.13 deraadt 88: main(int argc, char *argv[])
1.1 deraadt 89: {
1.15 ! otto 90: double x;
! 91: double y;
! 92: long i;
1.8 pjanzen 93: unsigned int mask = 0;
1.15 ! otto 94: int n = 0;
! 95: int ch;
1.1 deraadt 96:
1.8 pjanzen 97: while ((ch = getopt(argc, argv, "rb:w:cs:np:")) != -1)
1.15 ! otto 98: switch (ch) {
1.1 deraadt 99: case 'r':
1.15 ! otto 100: randomize = true;
1.1 deraadt 101: break;
102: case 'c':
1.15 ! otto 103: chardata = true;
1.1 deraadt 104: break;
105: case 'n':
1.15 ! otto 106: finalnl = false;
1.1 deraadt 107: break;
108: case 'b':
1.15 ! otto 109: boring = true;
1.8 pjanzen 110: if (strlcpy(format, optarg, sizeof(format)) >=
111: sizeof(format))
112: errx(1, "-b word too long");
113: break;
1.1 deraadt 114: case 'w':
1.8 pjanzen 115: if (strlcpy(format, optarg, sizeof(format)) >=
116: sizeof(format))
117: errx(1, "-w word too long");
1.1 deraadt 118: break;
119: case 's':
1.8 pjanzen 120: if (strlcpy(sepstring, optarg, sizeof(sepstring)) >=
121: sizeof(sepstring))
122: errx(1, "-s word too long");
1.1 deraadt 123: break;
124: case 'p':
1.8 pjanzen 125: prec = atoi(optarg);
1.15 ! otto 126: if (prec < 0)
1.8 pjanzen 127: errx(1, "bad precision value");
1.1 deraadt 128: break;
129: default:
1.7 aaron 130: usage();
1.1 deraadt 131: }
1.8 pjanzen 132: argc -= optind;
133: argv += optind;
1.1 deraadt 134:
1.8 pjanzen 135: switch (argc) { /* examine args right to left, falling thru cases */
1.1 deraadt 136: case 4:
1.8 pjanzen 137: if (!is_default(argv[3])) {
138: if (!sscanf(argv[3], "%lf", &s))
139: errx(1, "Bad s value: %s", argv[3]);
1.1 deraadt 140: mask |= 01;
141: }
142: case 3:
1.8 pjanzen 143: if (!is_default(argv[2])) {
144: if (!sscanf(argv[2], "%lf", &ender))
145: ender = argv[2][strlen(argv[2])-1];
1.1 deraadt 146: mask |= 02;
1.15 ! otto 147: if (prec == -1)
1.8 pjanzen 148: n = getprec(argv[2]);
1.1 deraadt 149: }
150: case 2:
1.8 pjanzen 151: if (!is_default(argv[1])) {
152: if (!sscanf(argv[1], "%lf", &begin))
153: begin = argv[1][strlen(argv[1])-1];
1.1 deraadt 154: mask |= 04;
1.15 ! otto 155: if (prec == -1)
1.8 pjanzen 156: prec = getprec(argv[1]);
1.1 deraadt 157: if (n > prec) /* maximum precision */
158: prec = n;
159: }
160: case 1:
1.8 pjanzen 161: if (!is_default(argv[0])) {
162: if (!sscanf(argv[0], "%ld", &reps))
163: errx(1, "Bad reps value: %s", argv[0]);
1.1 deraadt 164: mask |= 010;
1.15 ! otto 165: if (prec == -1)
! 166: prec = 0;
1.1 deraadt 167: }
168: break;
169: case 0:
1.8 pjanzen 170: usage();
171: break;
1.1 deraadt 172: default:
1.15 ! otto 173: errx(1, "Too many arguments. What do you mean by %s?",
! 174: argv[4]);
1.1 deraadt 175: }
176: getformat();
177: while (mask) /* 4 bit mask has 1's where last 4 args were given */
178: switch (mask) { /* fill in the 0's by default or computation */
179: case 001:
180: reps = REPS_DEF;
181: mask = 011;
182: break;
183: case 002:
184: reps = REPS_DEF;
185: mask = 012;
186: break;
187: case 003:
188: reps = REPS_DEF;
189: mask = 013;
190: break;
191: case 004:
192: reps = REPS_DEF;
193: mask = 014;
194: break;
195: case 005:
196: reps = REPS_DEF;
197: mask = 015;
198: break;
199: case 006:
200: reps = REPS_DEF;
201: mask = 016;
202: break;
203: case 007:
204: if (randomize) {
205: reps = REPS_DEF;
206: mask = 0;
207: break;
208: }
209: if (s == 0.0) {
210: reps = 0;
211: mask = 0;
212: break;
213: }
214: reps = (ender - begin + s) / s;
215: if (reps <= 0)
1.7 aaron 216: errx(1, "Impossible stepsize");
1.1 deraadt 217: mask = 0;
218: break;
219: case 010:
220: begin = BEGIN_DEF;
221: mask = 014;
222: break;
223: case 011:
224: begin = BEGIN_DEF;
225: mask = 015;
226: break;
227: case 012:
1.6 aaron 228: s = (randomize ? time(NULL) : STEP_DEF);
1.1 deraadt 229: mask = 013;
230: break;
231: case 013:
232: if (randomize)
233: begin = BEGIN_DEF;
234: else if (reps == 0)
1.7 aaron 235: errx(1, "Must specify begin if reps == 0");
1.1 deraadt 236: begin = ender - reps * s + s;
237: mask = 0;
238: break;
239: case 014:
1.6 aaron 240: s = (randomize ? time(NULL) : STEP_DEF);
1.1 deraadt 241: mask = 015;
242: break;
243: case 015:
244: if (randomize)
245: ender = ENDER_DEF;
246: else
247: ender = begin + reps * s - s;
248: mask = 0;
249: break;
250: case 016:
251: if (randomize)
1.6 aaron 252: s = time(NULL);
1.1 deraadt 253: else if (reps == 0)
1.7 aaron 254: errx(1, "Infinite sequences cannot be bounded");
1.1 deraadt 255: else if (reps == 1)
256: s = 0.0;
257: else
258: s = (ender - begin) / (reps - 1);
259: mask = 0;
260: break;
261: case 017: /* if reps given and implied, */
262: if (!randomize && s != 0.0) {
263: long t = (ender - begin + s) / s;
264: if (t <= 0)
1.7 aaron 265: errx(1, "Impossible stepsize");
1.1 deraadt 266: if (t < reps) /* take lesser */
267: reps = t;
268: }
269: mask = 0;
270: break;
271: default:
1.8 pjanzen 272: errx(1, "bad mask");
1.1 deraadt 273: }
274: if (reps == 0)
1.15 ! otto 275: infinity = true;
1.8 pjanzen 276: if (randomize) {
1.15 ! otto 277: x = (ender - begin) * (ender > begin ? 1 : -1);
! 278: for (i = 1; i <= reps || infinity; i++) {
! 279: y = (double) arc4random() / UINT_MAX;
! 280: putdata(y * x + begin, reps - i == 0 && !infinity);
1.8 pjanzen 281: }
282: }
283: else
1.15 ! otto 284: for (i = 1, x = begin; i <= reps || infinity; i++, x += s)
! 285: putdata(x, reps - i == 0 && !infinity);
! 286: if (finalnl)
1.8 pjanzen 287: putchar('\n');
288: exit(0);
1.1 deraadt 289: }
290:
1.15 ! otto 291: static void
! 292: putdata(double x, bool last)
1.1 deraadt 293: {
294: if (boring) /* repeated word */
295: printf("%s", format);
296: else if (dox) /* scalar */
1.15 ! otto 297: printf(format, (long)x);
1.1 deraadt 298: else /* real */
299: printf(format, x);
1.15 ! otto 300: if (!last)
1.1 deraadt 301: fputs(sepstring, stdout);
302: }
303:
1.7 aaron 304: static void
305: usage(void)
1.1 deraadt 306: {
1.14 jmc 307: (void)fprintf(stderr, "usage: jot [-cnr] [-b word] [-p precision] "
308: "[-s string] [-w word]\n"
309: " [reps [begin [end [s]]]]\n");
1.1 deraadt 310: exit(1);
311: }
312:
1.15 ! otto 313: static int
1.13 deraadt 314: getprec(char *s)
1.1 deraadt 315: {
1.8 pjanzen 316: char *p;
317: char *q;
1.1 deraadt 318:
1.15 ! otto 319: for (p = s; *p != '\0'; p++)
1.1 deraadt 320: if (*p == '.')
321: break;
1.15 ! otto 322: if (*p == '\0')
1.1 deraadt 323: return (0);
1.15 ! otto 324: for (q = ++p; *p != '\0'; p++)
1.1 deraadt 325: if (!isdigit(*p))
326: break;
327: return (p - q);
328: }
329:
1.15 ! otto 330: static void
1.13 deraadt 331: getformat(void)
1.1 deraadt 332: {
1.8 pjanzen 333: char *p;
334: size_t sz;
1.1 deraadt 335:
336: if (boring) /* no need to bother */
337: return;
1.15 ! otto 338: for (p = format; *p != '\0'; p++) /* look for '%' */
1.8 pjanzen 339: if (*p == '%') {
340: if (*(p+1) != '%')
341: break;
342: p++; /* leave %% alone */
343: }
344: sz = sizeof(format) - strlen(format) - 1;
1.15 ! otto 345: if (*p == '\0' && !chardata) {
1.8 pjanzen 346: if (snprintf(p, sz, "%%.%df", prec) >= (int)sz)
347: errx(1, "-w word too long");
1.15 ! otto 348: } else if (*p == '\0' && chardata) {
1.8 pjanzen 349: if (strlcpy(p, "%c", sz) >= sz)
350: errx(1, "-w word too long");
1.15 ! otto 351: dox = true;
! 352: } else if (*(p+1) == '\0') {
1.8 pjanzen 353: if (sz <= 0)
354: errx(1, "-w word too long");
1.15 ! otto 355: /* cannot end in single '%' */
! 356: strlcat(format, "%", sizeof format);
1.8 pjanzen 357: } else {
1.15 ! otto 358: for (; *p != '\0' && !isalpha(*p); p++)
1.8 pjanzen 359: /* Certain nonalphanumerics we can't allow */
360: if (*p == '$' || *p == '*')
361: break;
362: /* Allow 'l' prefix, but no other. */
363: if (*p == 'l')
1.1 deraadt 364: p++;
365: switch (*p) {
366: case 'f': case 'e': case 'g': case '%':
1.8 pjanzen 367: case 'E': case 'G':
1.1 deraadt 368: break;
369: case 's':
1.8 pjanzen 370: errx(1, "cannot convert numeric data to strings");
1.1 deraadt 371: break;
1.8 pjanzen 372: case 'd': case 'o': case 'x': case 'u':
373: case 'D': case 'O': case 'X': case 'U':
374: case 'c': case 'i':
1.15 ! otto 375: dox = true;
1.1 deraadt 376: break;
1.8 pjanzen 377: default:
378: errx(1, "unknown or invalid format `%s'", format);
1.1 deraadt 379: }
1.8 pjanzen 380: /* Need to check for trailing stuff to print */
1.15 ! otto 381: for (; *p != '\0'; p++) /* look for '%' */
1.8 pjanzen 382: if (*p == '%') {
383: if (*(p+1) != '%')
384: break;
385: p++; /* leave %% alone */
386: }
1.15 ! otto 387: if (*p != '\0')
1.8 pjanzen 388: errx(1, "unknown or invalid format `%s'", format);
1.1 deraadt 389: }
390: }