home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / bin / dd / args.c next >
Encoding:
C/C++ Source or Header  |  1993-04-28  |  8.9 KB  |  374 lines

  1. /*-
  2.  * Copyright (c) 1991 The Regents of the University of California.
  3.  * All rights reserved.
  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
  39. static char sccsid[] = "@(#)args.c    5.5 (Berkeley) 7/29/91";
  40. #endif /* not lint */
  41.  
  42. #include <sys/types.h>
  43. #include <limits.h>
  44. #include <errno.h>
  45. #include <stdio.h>
  46. #include <stdlib.h>
  47. #include <string.h>
  48. #include "dd.h"
  49. #include "extern.h"
  50.  
  51. static u_long get_bsz __P((char *));
  52.  
  53. static void f_bs __P((char *));
  54. static void f_cbs __P((char *));
  55. static void f_conv __P((char *));
  56. static void f_count __P((char *));
  57. static void f_files __P((char *));
  58. static void f_ibs __P((char *));
  59. static void f_if __P((char *));
  60. static void f_obs __P((char *));
  61. static void f_of __P((char *));
  62. static void f_seek __P((char *));
  63. static void f_skip __P((char *));
  64.  
  65. static struct arg {
  66.     char *name;
  67.     void (*f) __P((char *));
  68.     u_int set, noset;
  69. } args[] = {
  70.     "bs",        f_bs,        C_BS,        C_BS|C_IBS|C_OBS,
  71.     "cbs",        f_cbs,        C_CBS,        C_CBS,
  72.     "conv",        f_conv,        0,        0,
  73.     "count",    f_count,    C_COUNT,    C_COUNT,
  74.     "files",    f_files,    C_FILES,    C_FILES,
  75.     "ibs",        f_ibs,        C_IBS,        C_BS|C_IBS,
  76.     "if",        f_if,        C_IF,        C_IF,
  77.     "obs",        f_obs,        C_OBS,        C_BS|C_OBS,
  78.     "of",        f_of,        C_OF,        C_OF,
  79.     "seek",        f_seek,        C_SEEK,        C_SEEK,
  80.     "skip",        f_skip,        C_SKIP,        C_SKIP,
  81. };
  82.  
  83. static char *oper;
  84.  
  85. /*
  86.  * args -- parse JCL syntax of dd.
  87.  */
  88. void
  89. jcl(argv)
  90.     register char **argv;
  91. {
  92.     register struct arg *ap;
  93.     struct arg tmp;
  94.     char *arg;
  95.     static int c_arg __P((const void *, const void *));
  96.  
  97.     in.dbsz = out.dbsz = 512;
  98.  
  99.     while (oper = *++argv) {
  100.         if ((arg = index(oper, '=')) == NULL)
  101.             err("unknown operand %s", oper);
  102.         *arg++ = '\0';
  103.         if (!*arg)
  104.             err("no value specified for %s", oper);
  105.         tmp.name = oper;
  106.         if (!(ap = (struct arg *)bsearch(&tmp, args,
  107.             sizeof(args)/sizeof(struct arg), sizeof(struct arg),
  108.             c_arg)))
  109.             err("unknown operand %s", tmp.name);
  110.         if (ddflags & ap->noset)
  111.             err("%s: illegal argument combination or already set",
  112.                 tmp.name);
  113.         ddflags |= ap->set;
  114.         ap->f(arg);
  115.     }
  116.  
  117.     /* Final sanity checks. */
  118.  
  119.     if (ddflags & C_BS) {
  120.         /*
  121.          * Bs is turned off by any conversion -- we assume the user
  122.          * just wanted to set both the input and output block sizes
  123.          * and didn't want the bs semantics, so we don't warn.
  124.          */
  125.         if (ddflags & (C_BLOCK|C_LCASE|C_SWAB|C_UCASE|C_UNBLOCK))
  126.             ddflags &= ~C_BS;
  127.  
  128.         /* Bs supersedes ibs and obs. */
  129.         if (ddflags & C_BS && ddflags & (C_IBS|C_OBS))
  130.             warn("bs supersedes ibs and obs");
  131.     }
  132.  
  133.     /*
  134.      * Ascii/ebcdic and cbs implies block/unblock.
  135.      * Block/unblock requires cbs and vice-versa.
  136.      */
  137.     if (ddflags & (C_BLOCK|C_UNBLOCK)) {
  138.         if (!(ddflags & C_CBS))
  139.             err("record operations require cbs");
  140.         if (cbsz == 0)
  141.             err("cbs cannot be zero");
  142.         cfunc = ddflags & C_BLOCK ? block : unblock;
  143.     } else if (ddflags & C_CBS) {
  144.         if (ddflags & (C_ASCII|C_EBCDIC)) {
  145.             if (ddflags & C_ASCII) {
  146.                 ddflags |= C_UNBLOCK;
  147.                 cfunc = unblock;
  148.             } else {
  149.                 ddflags |= C_BLOCK;
  150.                 cfunc = block;
  151.             }
  152.         } else
  153.             err("cbs meaningless if not doing record operations");
  154.         if (cbsz == 0)
  155.             err("cbs cannot be zero");
  156.     } else
  157.         cfunc = def;
  158.  
  159.     if (in.dbsz == 0 || out.dbsz == 0)
  160.         err("buffer sizes cannot be zero");
  161.  
  162.     /*
  163.      * Read, write and seek calls take ints as arguments.  Seek sizes
  164.      * could be larger if we wanted to do it in stages or check only
  165.      * regular files, but it's probably not worth it.
  166.      */
  167.     if (in.dbsz > INT_MAX || out.dbsz > INT_MAX)
  168.         err("buffer sizes cannot be greater than %d", INT_MAX);
  169.     if (in.offset > INT_MAX / in.dbsz || out.offset > INT_MAX / out.dbsz)
  170.         err("seek offsets cannot be larger than %d", INT_MAX);
  171. }
  172.  
  173. static int
  174. c_arg(a, b)
  175.     const void *a, *b;
  176. {
  177.     return (strcmp(((struct arg *)a)->name, ((struct arg *)b)->name));
  178. }
  179.  
  180. static void
  181. f_bs(arg)
  182.     char *arg;
  183. {
  184.     in.dbsz = out.dbsz = (int)get_bsz(arg);
  185. }
  186.  
  187. static void
  188. f_cbs(arg)
  189.     char *arg;
  190. {
  191.     cbsz = (int)get_bsz(arg);
  192. }
  193.  
  194. static void
  195. f_count(arg)
  196.     char *arg;
  197. {
  198.     cpy_cnt = (u_int)get_bsz(arg);
  199.     if (!cpy_cnt)
  200.         terminate(0);
  201. }
  202.  
  203. static void
  204. f_files(arg)
  205.     char *arg;
  206. {
  207.     files_cnt = (int)get_bsz(arg);
  208. }
  209.  
  210. static void
  211. f_ibs(arg)
  212.     char *arg;
  213. {
  214.     if (!(ddflags & C_BS))
  215.         in.dbsz = (int)get_bsz(arg);
  216. }
  217.  
  218. static void
  219. f_if(arg)
  220.     char *arg;
  221. {
  222.     in.name = arg;
  223. }
  224.  
  225. static void
  226. f_obs(arg)
  227.     char *arg;
  228. {
  229.     if (!(ddflags & C_BS))
  230.         out.dbsz = (int)get_bsz(arg);
  231. }
  232.  
  233. static void
  234. f_of(arg)
  235.     char *arg;
  236. {
  237.     out.name = arg;
  238. }
  239.  
  240. static void
  241. f_seek(arg)
  242.     char *arg;
  243. {
  244.     out.offset = (u_int)get_bsz(arg);
  245. }
  246.  
  247. static void
  248. f_skip(arg)
  249.     char *arg;
  250. {
  251.     in.offset = (u_int)get_bsz(arg);
  252. }
  253.  
  254. static struct conv {
  255.     char *name;
  256.     u_int set, noset;
  257.     u_char *ctab;
  258. } clist[] = {
  259.     "ascii",    C_ASCII,    C_EBCDIC,    e2a_POSIX,
  260.     "block",    C_BLOCK,    C_UNBLOCK,    NULL,
  261.     "ebcdic",    C_EBCDIC,    C_ASCII,    a2e_POSIX,
  262.     "ibm",        C_EBCDIC,    C_ASCII,    a2ibm_POSIX,
  263.     "lcase",    C_LCASE,    C_UCASE,    NULL,
  264.     "noerror",    C_NOERROR,    0,        NULL,
  265.     "notrunc",    C_NOTRUNC,    0,        NULL,
  266.     "oldascii",    C_ASCII,    C_EBCDIC,    e2a_32V,
  267.     "oldebcdic",    C_EBCDIC,    C_ASCII,    a2e_32V,
  268.     "oldibm",    C_EBCDIC,    C_ASCII,    a2ibm_32V,
  269.     "swab",        C_SWAB,        0,        NULL,
  270.     "sync",        C_SYNC,        0,        NULL,
  271.     "ucase",    C_UCASE,    C_LCASE,    NULL,
  272.     "unblock",    C_UNBLOCK,    C_BLOCK,    NULL,
  273. };
  274.  
  275. static void
  276. f_conv(arg)
  277.     char *arg;
  278. {
  279.     register struct conv *cp;
  280.     struct conv tmp;
  281.     static int c_conv __P((const void *, const void *));
  282.  
  283.     while (arg != NULL) {
  284.         tmp.name = strsep(&arg, ",");
  285.         if (!(cp = (struct conv *)bsearch(&tmp, clist,
  286.             sizeof(clist)/sizeof(struct conv), sizeof(struct conv),
  287.             c_conv)))
  288.             err("unknown conversion %s", tmp.name);
  289.         if (ddflags & cp->noset)
  290.             err("%s: illegal conversion combination", tmp.name);
  291.         ddflags |= cp->set;
  292.         if (cp->ctab)
  293.             ctab = cp->ctab;
  294.     }
  295. }
  296.  
  297. static int
  298. c_conv(a, b)
  299.     const void *a, *b;
  300. {
  301.     return (strcmp(((struct conv *)a)->name, ((struct conv *)b)->name));
  302. }
  303.  
  304. /*
  305.  * Convert an expression of the following forms to an unsigned long.
  306.  *     1) A positive decimal number.
  307.  *    2) A positive decimal number followed by a b (mult by 512).
  308.  *    3) A positive decimal number followed by a k (mult by 1024).
  309.  *    4) A positive decimal number followed by a m (mult by 512).
  310.  *    5) A positive decimal number followed by a w (mult by sizeof int)
  311.  *    6) Two or more positive decimal numbers (with/without k,b or w).
  312.  *       seperated by x (also * for backwards compatibility), specifying
  313.  *       the product of the indicated values.
  314.  */
  315. static u_long
  316. get_bsz(val)
  317.     char *val;
  318. {
  319.     char *expr;
  320.     u_long num, t;
  321.  
  322.     num = strtoul(val, &expr, 0);
  323.     if (num == ULONG_MAX)            /* Overflow. */
  324.         err("%s: %s", oper, strerror(errno));
  325.     if (expr == val)            /* No digits. */
  326.         err("%s: illegal numeric value", oper);
  327.  
  328.     switch(*expr) {
  329.     case 'b':
  330.         t = num;
  331.         num *= 512;
  332.         if (t > num)
  333.             goto erange;
  334.         ++expr;
  335.         break;
  336.     case 'k':
  337.         t = num;
  338.         num *= 1024;
  339.         if (t > num)
  340.             goto erange;
  341.         ++expr;
  342.         break;
  343.     case 'm':
  344.         t = num;
  345.         num *= 1048576;
  346.         if (t > num)
  347.             goto erange;
  348.         ++expr;
  349.         break;
  350.     case 'w':
  351.         t = num;
  352.         num *= sizeof(int);
  353.         if (t > num)
  354.             goto erange;
  355.         ++expr;
  356.         break;
  357.     }
  358.  
  359.     switch(*expr) {
  360.         case '\0':
  361.             break;
  362.         case '*':            /* Backward compatible. */
  363.         case 'x':
  364.             t = num;
  365.             num *= get_bsz(expr + 1);
  366.             if (t > num)
  367. erange:                err("%s: %s", oper, strerror(ERANGE));
  368.             break;
  369.         default:
  370.             err("%s: illegal numeric value", oper);
  371.     }
  372.     return(num);
  373. }
  374.