[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.3

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

CVSweb <webmaster@jp.NetBSD.org>