1*bce29b5cSbluhm /* $OpenBSD: args.c,v 1.31 2019/02/16 10:54:00 bluhm Exp $ */
27f82c603Sniklas /* $NetBSD: args.c,v 1.7 1996/03/01 01:18:58 jtc Exp $ */
3df930be7Sderaadt
4df930be7Sderaadt /*-
5df930be7Sderaadt * Copyright (c) 1991, 1993, 1994
6df930be7Sderaadt * The Regents of the University of California. All rights reserved.
7df930be7Sderaadt *
8df930be7Sderaadt * This code is derived from software contributed to Berkeley by
9df930be7Sderaadt * Keith Muller of the University of California, San Diego and Lance
10df930be7Sderaadt * Visser of Convex Computer Corporation.
11df930be7Sderaadt *
12df930be7Sderaadt * Redistribution and use in source and binary forms, with or without
13df930be7Sderaadt * modification, are permitted provided that the following conditions
14df930be7Sderaadt * are met:
15df930be7Sderaadt * 1. Redistributions of source code must retain the above copyright
16df930be7Sderaadt * notice, this list of conditions and the following disclaimer.
17df930be7Sderaadt * 2. Redistributions in binary form must reproduce the above copyright
18df930be7Sderaadt * notice, this list of conditions and the following disclaimer in the
19df930be7Sderaadt * documentation and/or other materials provided with the distribution.
2029295d1cSmillert * 3. Neither the name of the University nor the names of its contributors
21df930be7Sderaadt * may be used to endorse or promote products derived from this software
22df930be7Sderaadt * without specific prior written permission.
23df930be7Sderaadt *
24df930be7Sderaadt * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25df930be7Sderaadt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26df930be7Sderaadt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27df930be7Sderaadt * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28df930be7Sderaadt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29df930be7Sderaadt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30df930be7Sderaadt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31df930be7Sderaadt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32df930be7Sderaadt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33df930be7Sderaadt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34df930be7Sderaadt * SUCH DAMAGE.
35df930be7Sderaadt */
36df930be7Sderaadt
37df930be7Sderaadt #include <sys/types.h>
38e4cb6409Shugh #include <sys/time.h>
39df930be7Sderaadt
40df930be7Sderaadt #include <err.h>
41df930be7Sderaadt #include <errno.h>
42df930be7Sderaadt #include <limits.h>
43df930be7Sderaadt #include <stdio.h>
44df930be7Sderaadt #include <stdlib.h>
45df930be7Sderaadt #include <string.h>
46df930be7Sderaadt
47df930be7Sderaadt #include "dd.h"
48df930be7Sderaadt #include "extern.h"
49df930be7Sderaadt
50c72b5b24Smillert static int c_arg(const void *, const void *);
51c72b5b24Smillert static void f_bs(char *);
52c72b5b24Smillert static void f_cbs(char *);
53c72b5b24Smillert static void f_conv(char *);
54c72b5b24Smillert static void f_count(char *);
55c72b5b24Smillert static void f_files(char *);
56c72b5b24Smillert static void f_ibs(char *);
57c72b5b24Smillert static void f_if(char *);
58c72b5b24Smillert static void f_obs(char *);
59c72b5b24Smillert static void f_of(char *);
60c72b5b24Smillert static void f_seek(char *);
61c72b5b24Smillert static void f_skip(char *);
621f29dce2Sbluhm static void f_status(char *);
63c72b5b24Smillert static size_t get_bsz(char *);
64c72b5b24Smillert static off_t get_off(char *);
65df930be7Sderaadt
66f3959517Sderaadt static const struct arg {
67a7237831Sdhill const char *name;
68c72b5b24Smillert void (*f)(char *);
69df930be7Sderaadt u_int set, noset;
70df930be7Sderaadt } args[] = {
71df930be7Sderaadt { "bs", f_bs, C_BS, C_BS|C_IBS|C_OBS|C_OSYNC },
72df930be7Sderaadt { "cbs", f_cbs, C_CBS, C_CBS },
73df930be7Sderaadt { "conv", f_conv, 0, 0 },
74df930be7Sderaadt { "count", f_count, C_COUNT, C_COUNT },
75df930be7Sderaadt { "files", f_files, C_FILES, C_FILES },
76df930be7Sderaadt { "ibs", f_ibs, C_IBS, C_BS|C_IBS },
77df930be7Sderaadt { "if", f_if, C_IF, C_IF },
78df930be7Sderaadt { "obs", f_obs, C_OBS, C_BS|C_OBS },
79df930be7Sderaadt { "of", f_of, C_OF, C_OF },
80df930be7Sderaadt { "seek", f_seek, C_SEEK, C_SEEK },
81df930be7Sderaadt { "skip", f_skip, C_SKIP, C_SKIP },
821f29dce2Sbluhm { "status", f_status, C_STATUS,C_STATUS },
83df930be7Sderaadt };
84df930be7Sderaadt
85df930be7Sderaadt static char *oper;
86df930be7Sderaadt
87df930be7Sderaadt /*
88df930be7Sderaadt * args -- parse JCL syntax of dd.
89df930be7Sderaadt */
90df930be7Sderaadt void
jcl(char ** argv)9128416801Sderaadt jcl(char **argv)
92df930be7Sderaadt {
93df930be7Sderaadt struct arg *ap, tmp;
94df930be7Sderaadt char *arg;
95df930be7Sderaadt
96df930be7Sderaadt in.dbsz = out.dbsz = 512;
97df930be7Sderaadt
984b4540bbScheloha while (*++argv != NULL) {
994b4540bbScheloha if ((oper = strdup(*argv)) == NULL)
1004b4540bbScheloha err(1, NULL);
101df930be7Sderaadt if ((arg = strchr(oper, '=')) == NULL)
102df930be7Sderaadt errx(1, "unknown operand %s", oper);
103df930be7Sderaadt *arg++ = '\0';
104df930be7Sderaadt if (!*arg)
105df930be7Sderaadt errx(1, "no value specified for %s", oper);
106df930be7Sderaadt tmp.name = oper;
107df930be7Sderaadt if (!(ap = (struct arg *)bsearch(&tmp, args,
108df930be7Sderaadt sizeof(args)/sizeof(struct arg), sizeof(struct arg),
109df930be7Sderaadt c_arg)))
110df930be7Sderaadt errx(1, "unknown operand %s", tmp.name);
111df930be7Sderaadt if (ddflags & ap->noset)
112df930be7Sderaadt errx(1, "%s: illegal argument combination or already set",
113df930be7Sderaadt tmp.name);
114df930be7Sderaadt ddflags |= ap->set;
115df930be7Sderaadt ap->f(arg);
1164b4540bbScheloha free(oper);
117df930be7Sderaadt }
118df930be7Sderaadt
119df930be7Sderaadt /* Final sanity checks. */
120df930be7Sderaadt
121df930be7Sderaadt if (ddflags & C_BS) {
122df930be7Sderaadt /*
123df930be7Sderaadt * Bs is turned off by any conversion -- we assume the user
124df930be7Sderaadt * just wanted to set both the input and output block sizes
125df930be7Sderaadt * and didn't want the bs semantics, so we don't warn.
126df930be7Sderaadt */
127df930be7Sderaadt if (ddflags & (C_BLOCK|C_LCASE|C_SWAB|C_UCASE|C_UNBLOCK))
128df930be7Sderaadt ddflags &= ~C_BS;
129df930be7Sderaadt
130df930be7Sderaadt /* Bs supersedes ibs and obs. */
131df930be7Sderaadt if (ddflags & C_BS && ddflags & (C_IBS|C_OBS))
132df930be7Sderaadt warnx("bs supersedes ibs and obs");
133df930be7Sderaadt }
134df930be7Sderaadt
135df930be7Sderaadt /*
136df930be7Sderaadt * Ascii/ebcdic and cbs implies block/unblock.
137df930be7Sderaadt * Block/unblock requires cbs and vice-versa.
138df930be7Sderaadt */
139df930be7Sderaadt if (ddflags & (C_BLOCK|C_UNBLOCK)) {
140df930be7Sderaadt if (!(ddflags & C_CBS))
141df930be7Sderaadt errx(1, "record operations require cbs");
142df930be7Sderaadt if (cbsz == 0)
143df930be7Sderaadt errx(1, "cbs cannot be zero");
144df930be7Sderaadt cfunc = ddflags & C_BLOCK ? block : unblock;
145df930be7Sderaadt } else if (ddflags & C_CBS) {
146df930be7Sderaadt if (ddflags & (C_ASCII|C_EBCDIC)) {
147df930be7Sderaadt if (ddflags & C_ASCII) {
148df930be7Sderaadt ddflags |= C_UNBLOCK;
149df930be7Sderaadt cfunc = unblock;
150df930be7Sderaadt } else {
151df930be7Sderaadt ddflags |= C_BLOCK;
152df930be7Sderaadt cfunc = block;
153df930be7Sderaadt }
154df930be7Sderaadt } else
155df930be7Sderaadt errx(1, "cbs meaningless if not doing record operations");
156df930be7Sderaadt if (cbsz == 0)
157df930be7Sderaadt errx(1, "cbs cannot be zero");
158df930be7Sderaadt } else
159df930be7Sderaadt cfunc = def;
160df930be7Sderaadt
161df930be7Sderaadt if (in.dbsz == 0 || out.dbsz == 0)
162df930be7Sderaadt errx(1, "buffer sizes cannot be zero");
163df930be7Sderaadt
164df930be7Sderaadt /*
165f6ff413cSmillert * Read and write take size_t's as arguments. Lseek, however,
166a43a44b4Stedu * takes an off_t.
167df930be7Sderaadt */
1685d23a6e7Sray if (cbsz > SSIZE_MAX || in.dbsz > SSIZE_MAX || out.dbsz > SSIZE_MAX)
1695d23a6e7Sray errx(1, "buffer sizes cannot be greater than %zd",
1705d23a6e7Sray (ssize_t)SSIZE_MAX);
171a43a44b4Stedu if (in.offset > LLONG_MAX / in.dbsz || out.offset > LLONG_MAX / out.dbsz)
172a43a44b4Stedu errx(1, "seek offsets cannot be larger than %lld", LLONG_MAX);
173df930be7Sderaadt }
174df930be7Sderaadt
175df930be7Sderaadt static int
c_arg(const void * a,const void * b)17628416801Sderaadt c_arg(const void *a, const void *b)
177df930be7Sderaadt {
178df930be7Sderaadt
179df930be7Sderaadt return (strcmp(((struct arg *)a)->name, ((struct arg *)b)->name));
180df930be7Sderaadt }
181df930be7Sderaadt
182df930be7Sderaadt static void
f_bs(char * arg)18328416801Sderaadt f_bs(char *arg)
184df930be7Sderaadt {
185df930be7Sderaadt
186f6ff413cSmillert in.dbsz = out.dbsz = get_bsz(arg);
187df930be7Sderaadt }
188df930be7Sderaadt
189df930be7Sderaadt static void
f_cbs(char * arg)19028416801Sderaadt f_cbs(char *arg)
191df930be7Sderaadt {
192df930be7Sderaadt
193f6ff413cSmillert cbsz = get_bsz(arg);
194df930be7Sderaadt }
195df930be7Sderaadt
196df930be7Sderaadt static void
f_count(char * arg)19728416801Sderaadt f_count(char *arg)
198df930be7Sderaadt {
199df930be7Sderaadt
2009c9e0865Smillert if ((cpy_cnt = get_bsz(arg)) == 0)
2019c9e0865Smillert cpy_cnt = (size_t)-1;
202df930be7Sderaadt }
203df930be7Sderaadt
204df930be7Sderaadt static void
f_files(char * arg)20528416801Sderaadt f_files(char *arg)
206df930be7Sderaadt {
207df930be7Sderaadt
208f6ff413cSmillert files_cnt = get_bsz(arg);
209df930be7Sderaadt }
210df930be7Sderaadt
211df930be7Sderaadt static void
f_ibs(char * arg)21228416801Sderaadt f_ibs(char *arg)
213df930be7Sderaadt {
214df930be7Sderaadt
215df930be7Sderaadt if (!(ddflags & C_BS))
216f6ff413cSmillert in.dbsz = get_bsz(arg);
217df930be7Sderaadt }
218df930be7Sderaadt
219df930be7Sderaadt static void
f_if(char * arg)22028416801Sderaadt f_if(char *arg)
221df930be7Sderaadt {
2224b4540bbScheloha if ((in.name = strdup(arg)) == NULL)
2234b4540bbScheloha err(1, NULL);
224df930be7Sderaadt }
225df930be7Sderaadt
226df930be7Sderaadt static void
f_obs(char * arg)22728416801Sderaadt f_obs(char *arg)
228df930be7Sderaadt {
229df930be7Sderaadt
230df930be7Sderaadt if (!(ddflags & C_BS))
231f6ff413cSmillert out.dbsz = get_bsz(arg);
232df930be7Sderaadt }
233df930be7Sderaadt
234df930be7Sderaadt static void
f_of(char * arg)23528416801Sderaadt f_of(char *arg)
236df930be7Sderaadt {
2374b4540bbScheloha if ((out.name = strdup(arg)) == NULL)
2384b4540bbScheloha err(1, NULL);
239df930be7Sderaadt }
240df930be7Sderaadt
241df930be7Sderaadt static void
f_seek(char * arg)24228416801Sderaadt f_seek(char *arg)
243df930be7Sderaadt {
244df930be7Sderaadt
245f6ff413cSmillert out.offset = get_off(arg);
246df930be7Sderaadt }
247df930be7Sderaadt
248df930be7Sderaadt static void
f_skip(char * arg)24928416801Sderaadt f_skip(char *arg)
250df930be7Sderaadt {
251df930be7Sderaadt
252f6ff413cSmillert in.offset = get_off(arg);
253df930be7Sderaadt }
254df930be7Sderaadt
2551f29dce2Sbluhm static void
f_status(char * arg)2561f29dce2Sbluhm f_status(char *arg)
2571f29dce2Sbluhm {
2581f29dce2Sbluhm
2591f29dce2Sbluhm if (strcmp(arg, "none") == 0)
2601f29dce2Sbluhm ddflags |= C_NOINFO;
2611f29dce2Sbluhm else if (strcmp(arg, "noxfer") == 0)
2621f29dce2Sbluhm ddflags |= C_NOXFER;
2631f29dce2Sbluhm else
2641f29dce2Sbluhm errx(1, "unknown status %s", arg);
2651f29dce2Sbluhm }
2661f29dce2Sbluhm
267df930be7Sderaadt
268f3959517Sderaadt static const struct conv {
269a7237831Sdhill const char *name;
270df930be7Sderaadt u_int set, noset;
2717f82c603Sniklas const u_char *ctab;
272df930be7Sderaadt } clist[] = {
273dc3be576Stedu #ifndef NO_CONV
274df930be7Sderaadt { "ascii", C_ASCII, C_EBCDIC, e2a_POSIX },
275df930be7Sderaadt { "block", C_BLOCK, C_UNBLOCK, NULL },
276df930be7Sderaadt { "ebcdic", C_EBCDIC, C_ASCII, a2e_POSIX },
277*bce29b5cSbluhm { "fsync", C_FSYNC, 0, NULL },
278df930be7Sderaadt { "ibm", C_EBCDIC, C_ASCII, a2ibm_POSIX },
279df930be7Sderaadt { "lcase", C_LCASE, C_UCASE, NULL },
280df930be7Sderaadt { "osync", C_OSYNC, C_BS, NULL },
281df930be7Sderaadt { "swab", C_SWAB, 0, NULL },
282df930be7Sderaadt { "sync", C_SYNC, 0, NULL },
283df930be7Sderaadt { "ucase", C_UCASE, C_LCASE, NULL },
284df930be7Sderaadt { "unblock", C_UNBLOCK, C_BLOCK, NULL },
285dc3be576Stedu #endif
286dc3be576Stedu { "noerror", C_NOERROR, 0, NULL },
287dc3be576Stedu { "notrunc", C_NOTRUNC, 0, NULL },
288dc3be576Stedu { NULL, 0, 0, NULL }
289df930be7Sderaadt };
290df930be7Sderaadt
291df930be7Sderaadt static void
f_conv(char * arg)29228416801Sderaadt f_conv(char *arg)
293df930be7Sderaadt {
294dc3be576Stedu const struct conv *cp;
295dc3be576Stedu const char *name;
296df930be7Sderaadt
297df930be7Sderaadt while (arg != NULL) {
298dc3be576Stedu name = strsep(&arg, ",");
299dc3be576Stedu for (cp = &clist[0]; cp->name; cp++)
300dc3be576Stedu if (strcmp(name, cp->name) == 0)
301dc3be576Stedu break;
302dc3be576Stedu if (!cp->name)
303dc3be576Stedu errx(1, "unknown conversion %s", name);
304df930be7Sderaadt if (ddflags & cp->noset)
305dc3be576Stedu errx(1, "%s: illegal conversion combination", name);
306df930be7Sderaadt ddflags |= cp->set;
307df930be7Sderaadt if (cp->ctab)
308df930be7Sderaadt ctab = cp->ctab;
309df930be7Sderaadt }
310df930be7Sderaadt }
311df930be7Sderaadt
312df930be7Sderaadt /*
313f6ff413cSmillert * Convert an expression of the following forms to a size_t
3143058619eStedu * 1) A positive decimal number, optionally followed by
3153058619eStedu * b - multiply by 512.
3163058619eStedu * k, m or g - multiply by 1024 each.
3173058619eStedu * w - multiply by sizeof int
3183058619eStedu * 2) Two or more of the above, separated by x
3193058619eStedu * (or * for backwards compatibility), specifying
320df930be7Sderaadt * the product of the indicated values.
321df930be7Sderaadt */
322f6ff413cSmillert static size_t
get_bsz(char * val)32328416801Sderaadt get_bsz(char *val)
324df930be7Sderaadt {
325f6ff413cSmillert size_t num, t;
326df930be7Sderaadt char *expr;
327df930be7Sderaadt
32860e2b159Sschwarze if (strchr(val, '-'))
32960e2b159Sschwarze errx(1, "%s: illegal numeric value", oper);
33060e2b159Sschwarze
33160e2b159Sschwarze errno = 0;
332df930be7Sderaadt num = strtoul(val, &expr, 0);
33360e2b159Sschwarze if (num == ULONG_MAX && errno == ERANGE) /* Overflow. */
334df930be7Sderaadt err(1, "%s", oper);
335df930be7Sderaadt if (expr == val) /* No digits. */
336df930be7Sderaadt errx(1, "%s: illegal numeric value", oper);
337df930be7Sderaadt
338df930be7Sderaadt switch(*expr) {
339df930be7Sderaadt case 'b':
340df930be7Sderaadt t = num;
341df930be7Sderaadt num *= 512;
342df930be7Sderaadt if (t > num)
343df930be7Sderaadt goto erange;
344df930be7Sderaadt ++expr;
345df930be7Sderaadt break;
3463058619eStedu case 'g':
3473058619eStedu case 'G':
348df930be7Sderaadt t = num;
349df930be7Sderaadt num *= 1024;
350df930be7Sderaadt if (t > num)
351df930be7Sderaadt goto erange;
3523058619eStedu /* fallthrough */
353df930be7Sderaadt case 'm':
354e168cee8Snicm case 'M':
355df930be7Sderaadt t = num;
3563058619eStedu num *= 1024;
3573058619eStedu if (t > num)
3583058619eStedu goto erange;
3593058619eStedu /* fallthrough */
3603058619eStedu case 'k':
3613058619eStedu case 'K':
3623058619eStedu t = num;
3633058619eStedu num *= 1024;
364df930be7Sderaadt if (t > num)
365df930be7Sderaadt goto erange;
366df930be7Sderaadt ++expr;
367df930be7Sderaadt break;
368df930be7Sderaadt case 'w':
369df930be7Sderaadt t = num;
370df930be7Sderaadt num *= sizeof(int);
371df930be7Sderaadt if (t > num)
372df930be7Sderaadt goto erange;
373df930be7Sderaadt ++expr;
374df930be7Sderaadt break;
375df930be7Sderaadt }
376df930be7Sderaadt
377df930be7Sderaadt switch(*expr) {
378df930be7Sderaadt case '\0':
379df930be7Sderaadt break;
380df930be7Sderaadt case '*': /* Backward compatible. */
381df930be7Sderaadt case 'x':
382df930be7Sderaadt t = num;
383df930be7Sderaadt num *= get_bsz(expr + 1);
384df930be7Sderaadt if (t > num)
3853058619eStedu goto erange;
386df930be7Sderaadt break;
387df930be7Sderaadt default:
388df930be7Sderaadt errx(1, "%s: illegal numeric value", oper);
389df930be7Sderaadt }
390df930be7Sderaadt return (num);
3913058619eStedu erange:
392cd5cfea9Sguenther errc(1, ERANGE, "%s", oper);
393df930be7Sderaadt }
394f6ff413cSmillert
395f6ff413cSmillert /*
396f6ff413cSmillert * Convert an expression of the following forms to an off_t
3973058619eStedu * 1) A positive decimal number, optionally followed by
3983058619eStedu * b - multiply by 512.
3993058619eStedu * k, m or g - multiply by 1024 each.
4003058619eStedu * w - multiply by sizeof int
4013058619eStedu * 2) Two or more of the above, separated by x
4023058619eStedu * (or * for backwards compatibility), specifying
403f6ff413cSmillert * the product of the indicated values.
404f6ff413cSmillert */
405f6ff413cSmillert static off_t
get_off(char * val)40628416801Sderaadt get_off(char *val)
407f6ff413cSmillert {
408f6ff413cSmillert off_t num, t;
409f6ff413cSmillert char *expr;
410f6ff413cSmillert
411153396c3Sschwarze errno = 0;
412a43a44b4Stedu num = strtoll(val, &expr, 0);
413153396c3Sschwarze if (num == LLONG_MAX && errno == ERANGE) /* Overflow. */
414f6ff413cSmillert err(1, "%s", oper);
415f6ff413cSmillert if (expr == val) /* No digits. */
416f6ff413cSmillert errx(1, "%s: illegal numeric value", oper);
417f6ff413cSmillert
418f6ff413cSmillert switch(*expr) {
419f6ff413cSmillert case 'b':
420f6ff413cSmillert t = num;
421f6ff413cSmillert num *= 512;
422f6ff413cSmillert if (t > num)
423f6ff413cSmillert goto erange;
424f6ff413cSmillert ++expr;
425f6ff413cSmillert break;
4263058619eStedu case 'g':
4273058619eStedu case 'G':
428f6ff413cSmillert t = num;
429f6ff413cSmillert num *= 1024;
430f6ff413cSmillert if (t > num)
431f6ff413cSmillert goto erange;
4323058619eStedu /* fallthrough */
433f6ff413cSmillert case 'm':
434e168cee8Snicm case 'M':
435f6ff413cSmillert t = num;
4363058619eStedu num *= 1024;
4373058619eStedu if (t > num)
4383058619eStedu goto erange;
4393058619eStedu /* fallthrough */
4403058619eStedu case 'k':
4413058619eStedu case 'K':
4423058619eStedu t = num;
4433058619eStedu num *= 1024;
444f6ff413cSmillert if (t > num)
445f6ff413cSmillert goto erange;
446f6ff413cSmillert ++expr;
447f6ff413cSmillert break;
448f6ff413cSmillert case 'w':
449f6ff413cSmillert t = num;
450f6ff413cSmillert num *= sizeof(int);
451f6ff413cSmillert if (t > num)
452f6ff413cSmillert goto erange;
453f6ff413cSmillert ++expr;
454f6ff413cSmillert break;
455f6ff413cSmillert }
456f6ff413cSmillert
457f6ff413cSmillert switch(*expr) {
458f6ff413cSmillert case '\0':
459f6ff413cSmillert break;
460f6ff413cSmillert case '*': /* Backward compatible. */
461f6ff413cSmillert case 'x':
462f6ff413cSmillert t = num;
463f6ff413cSmillert num *= get_off(expr + 1);
464f6ff413cSmillert if (t > num)
4653058619eStedu goto erange;
466f6ff413cSmillert break;
467f6ff413cSmillert default:
468f6ff413cSmillert errx(1, "%s: illegal numeric value", oper);
469f6ff413cSmillert }
470f6ff413cSmillert return (num);
4713058619eStedu erange:
472cd5cfea9Sguenther errc(1, ERANGE, "%s", oper);
473f6ff413cSmillert }
474