Annotation of src/bin/dd/args.c, Revision 1.11
1.11 ! enami 1: /* $NetBSD: args.c,v 1.10 1998/02/28 04:20:02 enami Exp $ */
1.4 cgd 2:
1.1 glass 3: /*-
1.3 mycroft 4: * Copyright (c) 1991, 1993, 1994
5: * The Regents of the University of California. All rights reserved.
1.1 glass 6: *
7: * This code is derived from software contributed to Berkeley by
8: * Keith Muller of the University of California, San Diego and Lance
9: * Visser of Convex Computer Corporation.
10: *
11: * Redistribution and use in source and binary forms, with or without
12: * modification, are permitted provided that the following conditions
13: * are met:
14: * 1. Redistributions of source code must retain the above copyright
15: * notice, this list of conditions and the following disclaimer.
16: * 2. Redistributions in binary form must reproduce the above copyright
17: * notice, this list of conditions and the following disclaimer in the
18: * documentation and/or other materials provided with the distribution.
19: * 3. All advertising materials mentioning features or use of this software
20: * must display the following acknowledgement:
21: * This product includes software developed by the University of
22: * California, Berkeley and its contributors.
23: * 4. Neither the name of the University nor the names of its contributors
24: * may be used to endorse or promote products derived from this software
25: * without specific prior written permission.
26: *
27: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37: * SUCH DAMAGE.
38: */
39:
1.8 christos 40: #include <sys/cdefs.h>
1.1 glass 41: #ifndef lint
1.4 cgd 42: #if 0
43: static char sccsid[] = "@(#)args.c 8.3 (Berkeley) 4/2/94";
44: #else
1.11 ! enami 45: __RCSID("$NetBSD: args.c,v 1.10 1998/02/28 04:20:02 enami Exp $");
1.4 cgd 46: #endif
1.1 glass 47: #endif /* not lint */
48:
49: #include <sys/types.h>
1.3 mycroft 50:
51: #include <err.h>
52: #include <errno.h>
1.1 glass 53: #include <limits.h>
54: #include <stdio.h>
55: #include <stdlib.h>
56: #include <string.h>
1.3 mycroft 57:
1.1 glass 58: #include "dd.h"
59: #include "extern.h"
60:
1.3 mycroft 61: static int c_arg __P((const void *, const void *));
62: static int c_conv __P((const void *, const void *));
63: static void f_bs __P((char *));
64: static void f_cbs __P((char *));
65: static void f_conv __P((char *));
66: static void f_count __P((char *));
67: static void f_files __P((char *));
68: static void f_ibs __P((char *));
69: static void f_if __P((char *));
70: static void f_obs __P((char *));
71: static void f_of __P((char *));
72: static void f_seek __P((char *));
73: static void f_skip __P((char *));
74: static u_long get_bsz __P((char *));
1.1 glass 75:
1.7 jtc 76: const static struct arg {
1.1 glass 77: char *name;
78: void (*f) __P((char *));
79: u_int set, noset;
80: } args[] = {
1.3 mycroft 81: { "bs", f_bs, C_BS, C_BS|C_IBS|C_OBS|C_OSYNC },
82: { "cbs", f_cbs, C_CBS, C_CBS },
83: { "conv", f_conv, 0, 0 },
84: { "count", f_count, C_COUNT, C_COUNT },
85: { "files", f_files, C_FILES, C_FILES },
86: { "ibs", f_ibs, C_IBS, C_BS|C_IBS },
87: { "if", f_if, C_IF, C_IF },
88: { "obs", f_obs, C_OBS, C_BS|C_OBS },
89: { "of", f_of, C_OF, C_OF },
90: { "seek", f_seek, C_SEEK, C_SEEK },
91: { "skip", f_skip, C_SKIP, C_SKIP },
1.1 glass 92: };
93:
94: static char *oper;
95:
96: /*
97: * args -- parse JCL syntax of dd.
98: */
99: void
100: jcl(argv)
1.3 mycroft 101: char **argv;
1.1 glass 102: {
1.3 mycroft 103: struct arg *ap, tmp;
1.1 glass 104: char *arg;
105:
106: in.dbsz = out.dbsz = 512;
107:
1.8 christos 108: while ((oper = *++argv) != NULL) {
1.3 mycroft 109: if ((arg = strchr(oper, '=')) == NULL)
110: errx(1, "unknown operand %s", oper);
1.1 glass 111: *arg++ = '\0';
112: if (!*arg)
1.3 mycroft 113: errx(1, "no value specified for %s", oper);
1.1 glass 114: tmp.name = oper;
115: if (!(ap = (struct arg *)bsearch(&tmp, args,
116: sizeof(args)/sizeof(struct arg), sizeof(struct arg),
117: c_arg)))
1.3 mycroft 118: errx(1, "unknown operand %s", tmp.name);
1.1 glass 119: if (ddflags & ap->noset)
1.3 mycroft 120: errx(1, "%s: illegal argument combination or already set",
1.1 glass 121: tmp.name);
122: ddflags |= ap->set;
123: ap->f(arg);
124: }
125:
126: /* Final sanity checks. */
127:
128: if (ddflags & C_BS) {
129: /*
130: * Bs is turned off by any conversion -- we assume the user
131: * just wanted to set both the input and output block sizes
132: * and didn't want the bs semantics, so we don't warn.
133: */
134: if (ddflags & (C_BLOCK|C_LCASE|C_SWAB|C_UCASE|C_UNBLOCK))
135: ddflags &= ~C_BS;
136:
137: /* Bs supersedes ibs and obs. */
138: if (ddflags & C_BS && ddflags & (C_IBS|C_OBS))
1.3 mycroft 139: warnx("bs supersedes ibs and obs");
1.1 glass 140: }
141:
142: /*
143: * Ascii/ebcdic and cbs implies block/unblock.
144: * Block/unblock requires cbs and vice-versa.
145: */
146: if (ddflags & (C_BLOCK|C_UNBLOCK)) {
147: if (!(ddflags & C_CBS))
1.3 mycroft 148: errx(1, "record operations require cbs");
1.1 glass 149: if (cbsz == 0)
1.3 mycroft 150: errx(1, "cbs cannot be zero");
1.1 glass 151: cfunc = ddflags & C_BLOCK ? block : unblock;
152: } else if (ddflags & C_CBS) {
153: if (ddflags & (C_ASCII|C_EBCDIC)) {
154: if (ddflags & C_ASCII) {
155: ddflags |= C_UNBLOCK;
156: cfunc = unblock;
157: } else {
158: ddflags |= C_BLOCK;
159: cfunc = block;
160: }
161: } else
1.3 mycroft 162: errx(1, "cbs meaningless if not doing record operations");
1.1 glass 163: if (cbsz == 0)
1.3 mycroft 164: errx(1, "cbs cannot be zero");
1.1 glass 165: } else
166: cfunc = def;
167:
168: if (in.dbsz == 0 || out.dbsz == 0)
1.3 mycroft 169: errx(1, "buffer sizes cannot be zero");
1.1 glass 170:
171: /*
1.9 phil 172: * Check to make sure that the buffers are not too large.
1.1 glass 173: */
174: if (in.dbsz > INT_MAX || out.dbsz > INT_MAX)
1.3 mycroft 175: errx(1, "buffer sizes cannot be greater than %d", INT_MAX);
1.9 phil 176:
177: /* Read, write and seek calls take off_t as arguments.
178: *
179: * The following check is not done because an off_t is a quad
180: * for current NetBSD implementations.
181: *
182: * if (in.offset > INT_MAX/in.dbsz || out.offset > INT_MAX/out.dbsz)
183: * errx(1, "seek offsets cannot be larger than %d", INT_MAX);
184: */
1.1 glass 185: }
186:
187: static int
188: c_arg(a, b)
189: const void *a, *b;
190: {
1.3 mycroft 191:
1.1 glass 192: return (strcmp(((struct arg *)a)->name, ((struct arg *)b)->name));
193: }
194:
195: static void
196: f_bs(arg)
197: char *arg;
198: {
1.3 mycroft 199:
1.1 glass 200: in.dbsz = out.dbsz = (int)get_bsz(arg);
201: }
202:
203: static void
204: f_cbs(arg)
205: char *arg;
206: {
1.3 mycroft 207:
1.1 glass 208: cbsz = (int)get_bsz(arg);
209: }
210:
211: static void
212: f_count(arg)
213: char *arg;
214: {
1.3 mycroft 215:
1.1 glass 216: cpy_cnt = (u_int)get_bsz(arg);
217: if (!cpy_cnt)
218: terminate(0);
219: }
220:
221: static void
222: f_files(arg)
223: char *arg;
224: {
1.3 mycroft 225:
1.1 glass 226: files_cnt = (int)get_bsz(arg);
227: }
228:
229: static void
230: f_ibs(arg)
231: char *arg;
232: {
1.3 mycroft 233:
1.1 glass 234: if (!(ddflags & C_BS))
235: in.dbsz = (int)get_bsz(arg);
236: }
237:
238: static void
239: f_if(arg)
240: char *arg;
241: {
1.3 mycroft 242:
1.1 glass 243: in.name = arg;
244: }
245:
246: static void
247: f_obs(arg)
248: char *arg;
249: {
1.3 mycroft 250:
1.1 glass 251: if (!(ddflags & C_BS))
252: out.dbsz = (int)get_bsz(arg);
253: }
254:
255: static void
256: f_of(arg)
257: char *arg;
258: {
1.3 mycroft 259:
1.1 glass 260: out.name = arg;
261: }
262:
263: static void
264: f_seek(arg)
265: char *arg;
266: {
1.3 mycroft 267:
1.1 glass 268: out.offset = (u_int)get_bsz(arg);
269: }
270:
271: static void
272: f_skip(arg)
273: char *arg;
274: {
1.3 mycroft 275:
1.1 glass 276: in.offset = (u_int)get_bsz(arg);
277: }
278:
1.5 gwr 279: #ifdef NO_CONV
280: /* Build a small version (i.e. for a ramdisk root) */
281: static void
282: f_conv(arg)
283: char *arg;
284: {
285: errx(1, "conv option disabled");
286: }
287: #else /* NO_CONV */
288:
1.7 jtc 289: const static struct conv {
1.1 glass 290: char *name;
291: u_int set, noset;
1.6 jtc 292: const u_char *ctab;
1.1 glass 293: } clist[] = {
1.3 mycroft 294: { "ascii", C_ASCII, C_EBCDIC, e2a_POSIX },
295: { "block", C_BLOCK, C_UNBLOCK, NULL },
296: { "ebcdic", C_EBCDIC, C_ASCII, a2e_POSIX },
297: { "ibm", C_EBCDIC, C_ASCII, a2ibm_POSIX },
298: { "lcase", C_LCASE, C_UCASE, NULL },
299: { "noerror", C_NOERROR, 0, NULL },
300: { "notrunc", C_NOTRUNC, 0, NULL },
301: { "oldascii", C_ASCII, C_EBCDIC, e2a_32V },
302: { "oldebcdic", C_EBCDIC, C_ASCII, a2e_32V },
303: { "oldibm", C_EBCDIC, C_ASCII, a2ibm_32V },
304: { "osync", C_OSYNC, C_BS, NULL },
305: { "swab", C_SWAB, 0, NULL },
306: { "sync", C_SYNC, 0, NULL },
307: { "ucase", C_UCASE, C_LCASE, NULL },
308: { "unblock", C_UNBLOCK, C_BLOCK, NULL },
1.1 glass 309: };
310:
311: static void
312: f_conv(arg)
313: char *arg;
314: {
1.3 mycroft 315: struct conv *cp, tmp;
1.1 glass 316:
317: while (arg != NULL) {
318: tmp.name = strsep(&arg, ",");
319: if (!(cp = (struct conv *)bsearch(&tmp, clist,
320: sizeof(clist)/sizeof(struct conv), sizeof(struct conv),
321: c_conv)))
1.3 mycroft 322: errx(1, "unknown conversion %s", tmp.name);
1.1 glass 323: if (ddflags & cp->noset)
1.3 mycroft 324: errx(1, "%s: illegal conversion combination", tmp.name);
1.1 glass 325: ddflags |= cp->set;
326: if (cp->ctab)
327: ctab = cp->ctab;
328: }
329: }
330:
331: static int
332: c_conv(a, b)
333: const void *a, *b;
334: {
1.3 mycroft 335:
1.1 glass 336: return (strcmp(((struct conv *)a)->name, ((struct conv *)b)->name));
337: }
1.5 gwr 338:
339: #endif /* NO_CONV */
1.1 glass 340:
341: /*
342: * Convert an expression of the following forms to an unsigned long.
343: * 1) A positive decimal number.
344: * 2) A positive decimal number followed by a b (mult by 512).
345: * 3) A positive decimal number followed by a k (mult by 1024).
346: * 4) A positive decimal number followed by a m (mult by 512).
347: * 5) A positive decimal number followed by a w (mult by sizeof int)
348: * 6) Two or more positive decimal numbers (with/without k,b or w).
349: * seperated by x (also * for backwards compatibility), specifying
350: * the product of the indicated values.
351: */
352: static u_long
353: get_bsz(val)
354: char *val;
355: {
1.3 mycroft 356: u_long num, t;
1.1 glass 357: char *expr;
358:
359: num = strtoul(val, &expr, 0);
360: if (num == ULONG_MAX) /* Overflow. */
1.3 mycroft 361: err(1, "%s", oper);
1.1 glass 362: if (expr == val) /* No digits. */
1.3 mycroft 363: errx(1, "%s: illegal numeric value", oper);
1.1 glass 364:
1.10 enami 365: switch (*expr) {
1.1 glass 366: case 'b':
367: t = num;
368: num *= 512;
369: if (t > num)
370: goto erange;
371: ++expr;
372: break;
373: case 'k':
374: t = num;
375: num *= 1024;
376: if (t > num)
377: goto erange;
378: ++expr;
379: break;
380: case 'm':
381: t = num;
382: num *= 1048576;
383: if (t > num)
384: goto erange;
385: ++expr;
386: break;
387: case 'w':
388: t = num;
389: num *= sizeof(int);
390: if (t > num)
391: goto erange;
392: ++expr;
393: break;
394: }
395:
1.10 enami 396: switch (*expr) {
1.11 ! enami 397: case '\0':
! 398: break;
! 399: case '*': /* Backward compatible. */
! 400: case 'x':
! 401: t = num;
! 402: num *= get_bsz(expr + 1);
! 403: if (t > num)
! 404: erange: errx(1, "%s: %s", oper, strerror(ERANGE));
! 405: break;
! 406: default:
! 407: errx(1, "%s: illegal numeric value", oper);
1.1 glass 408: }
1.3 mycroft 409: return (num);
1.1 glass 410: }
CVSweb <webmaster@jp.NetBSD.org>