* Copyright (c) 1991, 1993, 1994
* The Regents of the University of California. All rights reserved.
* This code is derived from software contributed to Berkeley by
* Keith Muller of the University of California, San Diego and Lance
* Visser of Convex Computer Corporation.
* %sccs.include.redist.c%
static char sccsid
[] = "@(#)args.c 8.3 (Berkeley) %G%";
static int c_arg
__P((const void *, const void *));
static int c_conv
__P((const void *, const void *));
static void f_bs
__P((char *));
static void f_cbs
__P((char *));
static void f_conv
__P((char *));
static void f_count
__P((char *));
static void f_files
__P((char *));
static void f_ibs
__P((char *));
static void f_if
__P((char *));
static void f_obs
__P((char *));
static void f_of
__P((char *));
static void f_seek
__P((char *));
static void f_skip
__P((char *));
static u_long get_bsz
__P((char *));
{ "bs", f_bs
, C_BS
, C_BS
|C_IBS
|C_OBS
|C_OSYNC
},
{ "cbs", f_cbs
, C_CBS
, C_CBS
},
{ "conv", f_conv
, 0, 0 },
{ "count", f_count
, C_COUNT
, C_COUNT
},
{ "files", f_files
, C_FILES
, C_FILES
},
{ "ibs", f_ibs
, C_IBS
, C_BS
|C_IBS
},
{ "if", f_if
, C_IF
, C_IF
},
{ "obs", f_obs
, C_OBS
, C_BS
|C_OBS
},
{ "of", f_of
, C_OF
, C_OF
},
{ "seek", f_seek
, C_SEEK
, C_SEEK
},
{ "skip", f_skip
, C_SKIP
, C_SKIP
},
* args -- parse JCL syntax of dd.
in
.dbsz
= out
.dbsz
= 512;
if ((arg
= strchr(oper
, '=')) == NULL
)
errx(1, "unknown operand %s", oper
);
errx(1, "no value specified for %s", oper
);
if (!(ap
= (struct arg
*)bsearch(&tmp
, args
,
sizeof(args
)/sizeof(struct arg
), sizeof(struct arg
),
errx(1, "unknown operand %s", tmp
.name
);
errx(1, "%s: illegal argument combination or already set",
/* Final sanity checks. */
* Bs is turned off by any conversion -- we assume the user
* just wanted to set both the input and output block sizes
* and didn't want the bs semantics, so we don't warn.
if (ddflags
& (C_BLOCK
|C_LCASE
|C_SWAB
|C_UCASE
|C_UNBLOCK
))
/* Bs supersedes ibs and obs. */
if (ddflags
& C_BS
&& ddflags
& (C_IBS
|C_OBS
))
warnx("bs supersedes ibs and obs");
* Ascii/ebcdic and cbs implies block/unblock.
* Block/unblock requires cbs and vice-versa.
if (ddflags
& (C_BLOCK
|C_UNBLOCK
)) {
errx(1, "record operations require cbs");
errx(1, "cbs cannot be zero");
cfunc
= ddflags
& C_BLOCK
? block
: unblock
;
} else if (ddflags
& C_CBS
) {
if (ddflags
& (C_ASCII
|C_EBCDIC
)) {
errx(1, "cbs meaningless if not doing record operations");
errx(1, "cbs cannot be zero");
if (in
.dbsz
== 0 || out
.dbsz
== 0)
errx(1, "buffer sizes cannot be zero");
* Read, write and seek calls take ints as arguments. Seek sizes
* could be larger if we wanted to do it in stages or check only
* regular files, but it's probably not worth it.
if (in
.dbsz
> INT_MAX
|| out
.dbsz
> INT_MAX
)
errx(1, "buffer sizes cannot be greater than %d", INT_MAX
);
if (in
.offset
> INT_MAX
/ in
.dbsz
|| out
.offset
> INT_MAX
/ out
.dbsz
)
errx(1, "seek offsets cannot be larger than %d", INT_MAX
);
return (strcmp(((struct arg
*)a
)->name
, ((struct arg
*)b
)->name
));
in
.dbsz
= out
.dbsz
= (int)get_bsz(arg
);
cbsz
= (int)get_bsz(arg
);
cpy_cnt
= (u_int
)get_bsz(arg
);
files_cnt
= (int)get_bsz(arg
);
in
.dbsz
= (int)get_bsz(arg
);
out
.dbsz
= (int)get_bsz(arg
);
out
.offset
= (u_int
)get_bsz(arg
);
in
.offset
= (u_int
)get_bsz(arg
);
{ "ascii", C_ASCII
, C_EBCDIC
, e2a_POSIX
},
{ "block", C_BLOCK
, C_UNBLOCK
, NULL
},
{ "ebcdic", C_EBCDIC
, C_ASCII
, a2e_POSIX
},
{ "ibm", C_EBCDIC
, C_ASCII
, a2ibm_POSIX
},
{ "lcase", C_LCASE
, C_UCASE
, NULL
},
{ "noerror", C_NOERROR
, 0, NULL
},
{ "notrunc", C_NOTRUNC
, 0, NULL
},
{ "oldascii", C_ASCII
, C_EBCDIC
, e2a_32V
},
{ "oldebcdic", C_EBCDIC
, C_ASCII
, a2e_32V
},
{ "oldibm", C_EBCDIC
, C_ASCII
, a2ibm_32V
},
{ "osync", C_OSYNC
, C_BS
, NULL
},
{ "swab", C_SWAB
, 0, NULL
},
{ "sync", C_SYNC
, 0, NULL
},
{ "ucase", C_UCASE
, C_LCASE
, NULL
},
{ "unblock", C_UNBLOCK
, C_BLOCK
, NULL
},
tmp
.name
= strsep(&arg
, ",");
if (!(cp
= (struct conv
*)bsearch(&tmp
, clist
,
sizeof(clist
)/sizeof(struct conv
), sizeof(struct conv
),
errx(1, "unknown conversion %s", tmp
.name
);
errx(1, "%s: illegal conversion combination", tmp
.name
);
return (strcmp(((struct conv
*)a
)->name
, ((struct conv
*)b
)->name
));
* Convert an expression of the following forms to an unsigned long.
* 1) A positive decimal number.
* 2) A positive decimal number followed by a b (mult by 512).
* 3) A positive decimal number followed by a k (mult by 1024).
* 4) A positive decimal number followed by a m (mult by 512).
* 5) A positive decimal number followed by a w (mult by sizeof int)
* 6) Two or more positive decimal numbers (with/without k,b or w).
* seperated by x (also * for backwards compatibility), specifying
* the product of the indicated values.
num
= strtoul(val
, &expr
, 0);
if (num
== ULONG_MAX
) /* Overflow. */
if (expr
== val
) /* No digits. */
errx(1, "%s: illegal numeric value", oper
);
case '*': /* Backward compatible. */
num
*= get_bsz(expr
+ 1);
erange
: errx(1, "%s: %s", oper
, strerror(ERANGE
));
errx(1, "%s: illegal numeric value", oper
);