Annotation of src/bin/dd/args.c, Revision 1.22
1.22 ! jschauma 1: /* $NetBSD: args.c,v 1.21 2002/11/29 13:11:10 lukem 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.22 ! jschauma 45: __RCSID("$NetBSD: args.c,v 1.21 2002/11/29 13:11:10 lukem Exp $");
1.4 cgd 46: #endif
1.1 glass 47: #endif /* not lint */
48:
49: #include <sys/types.h>
1.15 ross 50: #include <sys/time.h>
1.3 mycroft 51:
52: #include <err.h>
53: #include <errno.h>
1.1 glass 54: #include <limits.h>
55: #include <stdio.h>
56: #include <stdlib.h>
57: #include <string.h>
1.3 mycroft 58:
1.1 glass 59: #include "dd.h"
60: #include "extern.h"
61:
1.17 lukem 62: static int c_arg(const void *, const void *);
1.18 lukem 63: #ifndef NO_CONV
1.17 lukem 64: static int c_conv(const void *, const void *);
1.18 lukem 65: #endif
1.17 lukem 66: static void f_bs(char *);
67: static void f_cbs(char *);
68: static void f_conv(char *);
69: static void f_count(char *);
70: static void f_files(char *);
71: static void f_ibs(char *);
72: static void f_if(char *);
73: static void f_obs(char *);
74: static void f_of(char *);
75: static void f_seek(char *);
76: static void f_skip(char *);
77: static void f_progress(char *);
1.1 glass 78:
1.12 msaitoh 79: static const struct arg {
1.17 lukem 80: const char *name;
81: void (*f)(char *);
1.1 glass 82: u_int set, noset;
83: } args[] = {
1.14 hubertf 84: /* the array needs to be sorted by the first column so
1.20 enami 85: bsearch() can be used to find commands quickly */
1.3 mycroft 86: { "bs", f_bs, C_BS, C_BS|C_IBS|C_OBS|C_OSYNC },
87: { "cbs", f_cbs, C_CBS, C_CBS },
88: { "conv", f_conv, 0, 0 },
89: { "count", f_count, C_COUNT, C_COUNT },
90: { "files", f_files, C_FILES, C_FILES },
91: { "ibs", f_ibs, C_IBS, C_BS|C_IBS },
92: { "if", f_if, C_IF, C_IF },
93: { "obs", f_obs, C_OBS, C_BS|C_OBS },
94: { "of", f_of, C_OF, C_OF },
1.14 hubertf 95: { "progress", f_progress, 0, 0 },
1.3 mycroft 96: { "seek", f_seek, C_SEEK, C_SEEK },
97: { "skip", f_skip, C_SKIP, C_SKIP },
1.1 glass 98: };
99:
100: /*
101: * args -- parse JCL syntax of dd.
102: */
103: void
1.17 lukem 104: jcl(char **argv)
1.1 glass 105: {
1.3 mycroft 106: struct arg *ap, tmp;
1.19 lukem 107: char *oper, *arg;
1.1 glass 108:
109: in.dbsz = out.dbsz = 512;
110:
1.8 christos 111: while ((oper = *++argv) != NULL) {
1.22 ! jschauma 112: if ((arg = strchr(oper, '=')) == NULL) {
! 113: errx(EXIT_FAILURE, "unknown operand %s", oper);
! 114: /* NOTREACHED */
! 115: }
1.1 glass 116: *arg++ = '\0';
1.22 ! jschauma 117: if (!*arg) {
! 118: errx(EXIT_FAILURE, "no value specified for %s", oper);
! 119: /* NOTREACHED */
! 120: }
1.1 glass 121: tmp.name = oper;
122: if (!(ap = (struct arg *)bsearch(&tmp, args,
123: sizeof(args)/sizeof(struct arg), sizeof(struct arg),
1.22 ! jschauma 124: c_arg))) {
! 125: errx(EXIT_FAILURE, "unknown operand %s", tmp.name);
! 126: /* NOTREACHED */
! 127: }
! 128: if (ddflags & ap->noset) {
! 129: errx(EXIT_FAILURE,
1.17 lukem 130: "%s: illegal argument combination or already set",
1.1 glass 131: tmp.name);
1.22 ! jschauma 132: /* NOTREACHED */
! 133: }
1.1 glass 134: ddflags |= ap->set;
135: ap->f(arg);
136: }
137:
138: /* Final sanity checks. */
139:
140: if (ddflags & C_BS) {
141: /*
142: * Bs is turned off by any conversion -- we assume the user
143: * just wanted to set both the input and output block sizes
144: * and didn't want the bs semantics, so we don't warn.
145: */
146: if (ddflags & (C_BLOCK|C_LCASE|C_SWAB|C_UCASE|C_UNBLOCK))
147: ddflags &= ~C_BS;
148:
149: /* Bs supersedes ibs and obs. */
150: if (ddflags & C_BS && ddflags & (C_IBS|C_OBS))
1.3 mycroft 151: warnx("bs supersedes ibs and obs");
1.1 glass 152: }
153:
154: /*
155: * Ascii/ebcdic and cbs implies block/unblock.
156: * Block/unblock requires cbs and vice-versa.
157: */
158: if (ddflags & (C_BLOCK|C_UNBLOCK)) {
1.22 ! jschauma 159: if (!(ddflags & C_CBS)) {
! 160: errx(EXIT_FAILURE, "record operations require cbs");
! 161: /* NOTREACHED */
! 162: }
1.1 glass 163: cfunc = ddflags & C_BLOCK ? block : unblock;
164: } else if (ddflags & C_CBS) {
165: if (ddflags & (C_ASCII|C_EBCDIC)) {
166: if (ddflags & C_ASCII) {
167: ddflags |= C_UNBLOCK;
168: cfunc = unblock;
169: } else {
170: ddflags |= C_BLOCK;
171: cfunc = block;
172: }
1.22 ! jschauma 173: } else {
! 174: errx(EXIT_FAILURE,
1.17 lukem 175: "cbs meaningless if not doing record operations");
1.22 ! jschauma 176: /* NOTREACHED */
! 177: }
1.1 glass 178: } else
179: cfunc = def;
180:
1.20 enami 181: /* Read, write and seek calls take off_t as arguments.
1.9 phil 182: *
183: * The following check is not done because an off_t is a quad
1.20 enami 184: * for current NetBSD implementations.
1.9 phil 185: *
186: * if (in.offset > INT_MAX/in.dbsz || out.offset > INT_MAX/out.dbsz)
187: * errx(1, "seek offsets cannot be larger than %d", INT_MAX);
188: */
1.1 glass 189: }
190:
191: static int
1.17 lukem 192: c_arg(const void *a, const void *b)
1.1 glass 193: {
1.17 lukem 194:
1.13 mycroft 195: return (strcmp(((const struct arg *)a)->name,
196: ((const struct arg *)b)->name));
1.1 glass 197: }
198:
199: static void
1.17 lukem 200: f_bs(char *arg)
1.1 glass 201: {
1.17 lukem 202:
1.21 lukem 203: in.dbsz = out.dbsz = strsuftoll("block size", arg, 1, UINT_MAX);
1.1 glass 204: }
205:
206: static void
1.17 lukem 207: f_cbs(char *arg)
1.1 glass 208: {
1.17 lukem 209:
1.21 lukem 210: cbsz = strsuftoll("conversion record size", arg, 1, UINT_MAX);
1.1 glass 211: }
212:
213: static void
1.17 lukem 214: f_count(char *arg)
1.1 glass 215: {
1.17 lukem 216:
1.21 lukem 217: cpy_cnt = strsuftoll("block count", arg, 0, LLONG_MAX);
1.1 glass 218: if (!cpy_cnt)
219: terminate(0);
220: }
221:
222: static void
1.17 lukem 223: f_files(char *arg)
1.1 glass 224: {
1.17 lukem 225:
1.21 lukem 226: files_cnt = (u_int)strsuftoll("file count", arg, 0, UINT_MAX);
1.19 lukem 227: if (!files_cnt)
228: terminate(0);
1.1 glass 229: }
230:
231: static void
1.17 lukem 232: f_ibs(char *arg)
1.1 glass 233: {
1.17 lukem 234:
1.1 glass 235: if (!(ddflags & C_BS))
1.21 lukem 236: in.dbsz = strsuftoll("input block size", arg, 1, UINT_MAX);
1.1 glass 237: }
238:
239: static void
1.17 lukem 240: f_if(char *arg)
1.1 glass 241: {
1.17 lukem 242:
1.1 glass 243: in.name = arg;
244: }
245:
246: static void
1.17 lukem 247: f_obs(char *arg)
1.1 glass 248: {
1.17 lukem 249:
1.1 glass 250: if (!(ddflags & C_BS))
1.21 lukem 251: out.dbsz = strsuftoll("output block size", arg, 1, UINT_MAX);
1.1 glass 252: }
253:
254: static void
1.17 lukem 255: f_of(char *arg)
1.1 glass 256: {
1.17 lukem 257:
1.1 glass 258: out.name = arg;
259: }
260:
261: static void
1.17 lukem 262: f_seek(char *arg)
1.1 glass 263: {
1.17 lukem 264:
1.21 lukem 265: out.offset = strsuftoll("seek blocks", arg, 0, LLONG_MAX);
1.1 glass 266: }
267:
268: static void
1.17 lukem 269: f_skip(char *arg)
1.1 glass 270: {
1.17 lukem 271:
1.21 lukem 272: in.offset = strsuftoll("skip blocks", arg, 0, LLONG_MAX);
1.14 hubertf 273: }
1.3 mycroft 274:
1.14 hubertf 275: static void
1.17 lukem 276: f_progress(char *arg)
1.14 hubertf 277: {
1.17 lukem 278:
1.14 hubertf 279: if (*arg != '0')
280: progress = 1;
1.1 glass 281: }
282:
1.5 gwr 283: #ifdef NO_CONV
284: /* Build a small version (i.e. for a ramdisk root) */
285: static void
1.17 lukem 286: f_conv(char *arg)
1.5 gwr 287: {
1.17 lukem 288:
1.22 ! jschauma 289: errx(EXIT_FAILURE, "conv option disabled");
! 290: /* NOTREACHED */
1.5 gwr 291: }
292: #else /* NO_CONV */
293:
1.12 msaitoh 294: static const struct conv {
1.17 lukem 295: const char *name;
1.1 glass 296: u_int set, noset;
1.6 jtc 297: const u_char *ctab;
1.1 glass 298: } clist[] = {
1.3 mycroft 299: { "ascii", C_ASCII, C_EBCDIC, e2a_POSIX },
300: { "block", C_BLOCK, C_UNBLOCK, NULL },
301: { "ebcdic", C_EBCDIC, C_ASCII, a2e_POSIX },
302: { "ibm", C_EBCDIC, C_ASCII, a2ibm_POSIX },
303: { "lcase", C_LCASE, C_UCASE, NULL },
304: { "noerror", C_NOERROR, 0, NULL },
305: { "notrunc", C_NOTRUNC, 0, NULL },
306: { "oldascii", C_ASCII, C_EBCDIC, e2a_32V },
307: { "oldebcdic", C_EBCDIC, C_ASCII, a2e_32V },
308: { "oldibm", C_EBCDIC, C_ASCII, a2ibm_32V },
309: { "osync", C_OSYNC, C_BS, NULL },
310: { "swab", C_SWAB, 0, NULL },
311: { "sync", C_SYNC, 0, NULL },
312: { "ucase", C_UCASE, C_LCASE, NULL },
313: { "unblock", C_UNBLOCK, C_BLOCK, NULL },
1.1 glass 314: };
315:
316: static void
1.17 lukem 317: f_conv(char *arg)
1.1 glass 318: {
1.3 mycroft 319: struct conv *cp, tmp;
1.1 glass 320:
321: while (arg != NULL) {
322: tmp.name = strsep(&arg, ",");
323: if (!(cp = (struct conv *)bsearch(&tmp, clist,
324: sizeof(clist)/sizeof(struct conv), sizeof(struct conv),
1.22 ! jschauma 325: c_conv))) {
! 326: errx(EXIT_FAILURE, "unknown conversion %s", tmp.name);
! 327: /* NOTREACHED */
! 328: }
! 329: if (ddflags & cp->noset) {
! 330: errx(EXIT_FAILURE, "%s: illegal conversion combination", tmp.name);
! 331: /* NOTREACHED */
! 332: }
1.1 glass 333: ddflags |= cp->set;
334: if (cp->ctab)
335: ctab = cp->ctab;
336: }
337: }
338:
339: static int
1.17 lukem 340: c_conv(const void *a, const void *b)
1.1 glass 341: {
1.3 mycroft 342:
1.13 mycroft 343: return (strcmp(((const struct conv *)a)->name,
344: ((const struct conv *)b)->name));
1.1 glass 345: }
1.5 gwr 346:
347: #endif /* NO_CONV */
CVSweb <webmaster@jp.NetBSD.org>