[BACK]Return to args.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / bin / dd

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>