1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License, Version 1.0 only
   6  * (the "License").  You may not use this file except in compliance
   7  * with the License.
   8  *
   9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  10  * or http://www.opensolaris.org/os/licensing.
  11  * See the License for the specific language governing permissions
  12  * and limitations under the License.
  13  *
  14  * When distributing Covered Code, include this CDDL HEADER in each
  15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16  * If applicable, add the following below this CDDL HEADER, with the
  17  * fields enclosed by brackets "[]" replaced with your own identifying
  18  * information: Portions Copyright [yyyy] [name of copyright owner]
  19  *
  20  * CDDL HEADER END
  21  */
  22 
  23 /*
  24  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
  25  * Use is subject to license terms.
  26  * Copyright 2012, Josef 'Jeff' Sipek <jeffpc@31bits.net>. All rights reserved.
  27  */
  28 
  29 /*      Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T     */
  30 /*        All Rights Reserved   */
  31 
  32 #pragma ident   "%Z%%M% %I%     %E% SMI"
  33 
  34 /*
  35  *      convert and copy
  36  */
  37 
  38 #include        <stdio.h>
  39 #include        <signal.h>
  40 #include        <fcntl.h>
  41 #include        <sys/param.h>
  42 #include        <sys/types.h>
  43 #include        <sys/sysmacros.h>
  44 #include        <sys/stat.h>
  45 #include        <unistd.h>
  46 #include        <stdlib.h>
  47 #include        <locale.h>
  48 #include        <string.h>
  49 
  50 /* The BIG parameter is machine dependent.  It should be a long integer */
  51 /* constant that can be used by the number parser to check the validity */
  52 /* of numeric parameters.  On 16-bit machines, it should probably be    */
  53 /* the maximum unsigned integer, 0177777L.  On 32-bit machines where    */
  54 /* longs are the same size as ints, the maximum signed integer is more  */
  55 /* appropriate.  This value is 017777777777L. In 64 bit environments,   */
  56 /* the maximum signed integer value is 0777777777777777777777LL         */
  57 
  58 #define BIG     0777777777777777777777LL
  59 
  60 #define BSIZE   512
  61 
  62 /* Option parameters */
  63 
  64 #define COPY            0       /* file copy, preserve input block size */
  65 #define REBLOCK         1       /* file copy, change block size */
  66 #define LCREBLOCK       2       /* file copy, convert to lower case */
  67 #define UCREBLOCK       3       /* file copy, convert to upper case */
  68 #define NBASCII         4       /* file copy, convert from EBCDIC to ASCII */
  69 #define LCNBASCII       5       /* file copy, EBCDIC to lower case ASCII */
  70 #define UCNBASCII       6       /* file copy, EBCDIC to upper case ASCII */
  71 #define NBEBCDIC        7       /* file copy, convert from ASCII to EBCDIC */
  72 #define LCNBEBCDIC      8       /* file copy, ASCII to lower case EBCDIC */
  73 #define UCNBEBCDIC      9       /* file copy, ASCII to upper case EBCDIC */
  74 #define NBIBM           10      /* file copy, convert from ASCII to IBM */
  75 #define LCNBIBM         11      /* file copy, ASCII to lower case IBM */
  76 #define UCNBIBM         12      /* file copy, ASCII to upper case IBM */
  77 #define UNBLOCK         13      /* convert blocked ASCII to ASCII */
  78 #define LCUNBLOCK       14      /* convert blocked ASCII to lower case ASCII */
  79 #define UCUNBLOCK       15      /* convert blocked ASCII to upper case ASCII */
  80 #define ASCII           16      /* convert blocked EBCDIC to ASCII */
  81 #define LCASCII         17      /* convert blocked EBCDIC to lower case ASCII */
  82 #define UCASCII         18      /* convert blocked EBCDIC to upper case ASCII */
  83 #define BLOCK           19      /* convert ASCII to blocked ASCII */
  84 #define LCBLOCK         20      /* convert ASCII to lower case blocked ASCII */
  85 #define UCBLOCK         21      /* convert ASCII to upper case blocked ASCII */
  86 #define EBCDIC          22      /* convert ASCII to blocked EBCDIC */
  87 #define LCEBCDIC        23      /* convert ASCII to lower case blocked EBCDIC */
  88 #define UCEBCDIC        24      /* convert ASCII to upper case blocked EBCDIC */
  89 #define IBM             25      /* convert ASCII to blocked IBM */
  90 #define LCIBM           26      /* convert ASCII to lower case blocked IBM */
  91 #define UCIBM           27      /* convert ASCII to upper case blocked IBM */
  92 #define LCASE           01      /* flag - convert to lower case */
  93 #define UCASE           02      /* flag - convert to upper case */
  94 #define SWAB            04      /* flag - swap bytes before conversion */
  95 #define NERR            010     /* flag - proceed on input errors */
  96 #define SYNC            020     /* flag - pad short input blocks with nulls */
  97 #define BADLIMIT        5       /* give up if no progress after BADLIMIT trys */
  98 #define SVR4XLATE       0       /* use default EBCDIC translation */
  99 #define BSDXLATE        1       /* use BSD-compatible EBCDIC translation */
 100 
 101 #define USAGE\
 102         "usage: dd [if=file] [of=file] [ibs=n|nk|nb|nxm] [obs=n|nk|nb|nxm]\n"\
 103         "          [bs=n|nk|nb|nxm] [cbs=n|nk|nb|nxm] [files=n] [skip=n]\n"\
 104         "          [iseek=n] [oseek=n] [seek=n] [count=n] [conv=[ascii]\n"\
 105         "          [,ebcdic][,ibm][,asciib][,ebcdicb][,ibmb]\n"\
 106         "          [,block|unblock][,lcase|ucase][,swab]\n"\
 107         "          [,noerror][,notrunc][,sync]]\n"
 108 
 109 /* Global references */
 110 
 111 /* Local routine declarations */
 112 
 113 static int      match(char *);
 114 static void             term();
 115 static unsigned long long       number();
 116 static unsigned char    *flsh();
 117 static void             stats();
 118 
 119 /* Local data definitions */
 120 
 121 static unsigned ibs;    /* input buffer size */
 122 static unsigned obs;    /* output buffer size */
 123 static unsigned bs;     /* buffer size, overrules ibs and obs */
 124 static unsigned cbs;    /* conversion buffer size, used for block conversions */
 125 static unsigned ibc;    /* number of bytes still in the input buffer */
 126 static unsigned obc;    /* number of bytes in the output buffer */
 127 static unsigned cbc;    /* number of bytes in the conversion buffer */
 128 
 129 static int      ibf;    /* input file descriptor */
 130 static int      obf;    /* output file descriptor */
 131 static int      cflag;  /* conversion option flags */
 132 static int      skipf;  /* if skipf == 1, skip rest of input line */
 133 static unsigned long long       nifr;   /* count of full input records */
 134 static unsigned long long       nipr;   /* count of partial input records */
 135 static unsigned long long       nofr;   /* count of full output records */
 136 static unsigned long long       nopr;   /* count of partial output records */
 137 static unsigned long long       ntrunc; /* count of truncated input lines */
 138 static unsigned long long       nbad;   /* count of bad records since last */
 139                                         /* good one */
 140 static int      files;  /* number of input files to concatenate (tape only) */
 141 static off_t    skip;   /* number of input records to skip */
 142 static off_t    iseekn; /* number of input records to seek past */
 143 static off_t    oseekn; /* number of output records to seek past */
 144 static unsigned long long       count;  /* number of input records to copy */
 145                         /* (0 = all) */
 146 static int      trantype; /* BSD or SVr4 compatible EBCDIC */
 147 
 148 static char             *string;        /* command arg pointer */
 149 static char             *ifile;         /* input file name pointer */
 150 static char             *ofile;         /* output file name pointer */
 151 static unsigned char    *ibuf;          /* input buffer pointer */
 152 static unsigned char    *obuf;          /* output buffer pointer */
 153 
 154 /* This is an EBCDIC to ASCII conversion table  */
 155 /* from a proposed BTL standard April 16, 1979  */
 156 
 157 static unsigned char svr4_etoa [] =
 158 {
 159         0000, 0001, 0002, 0003, 0234, 0011, 0206, 0177,
 160         0227, 0215, 0216, 0013, 0014, 0015, 0016, 0017,
 161         0020, 0021, 0022, 0023, 0235, 0205, 0010, 0207,
 162         0030, 0031, 0222, 0217, 0034, 0035, 0036, 0037,
 163         0200, 0201, 0202, 0203, 0204, 0012, 0027, 0033,
 164         0210, 0211, 0212, 0213, 0214, 0005, 0006, 0007,
 165         0220, 0221, 0026, 0223, 0224, 0225, 0226, 0004,
 166         0230, 0231, 0232, 0233, 0024, 0025, 0236, 0032,
 167         0040, 0240, 0241, 0242, 0243, 0244, 0245, 0246,
 168         0247, 0250, 0325, 0056, 0074, 0050, 0053, 0174,
 169         0046, 0251, 0252, 0253, 0254, 0255, 0256, 0257,
 170         0260, 0261, 0041, 0044, 0052, 0051, 0073, 0176,
 171         0055, 0057, 0262, 0263, 0264, 0265, 0266, 0267,
 172         0270, 0271, 0313, 0054, 0045, 0137, 0076, 0077,
 173         0272, 0273, 0274, 0275, 0276, 0277, 0300, 0301,
 174         0302, 0140, 0072, 0043, 0100, 0047, 0075, 0042,
 175         0303, 0141, 0142, 0143, 0144, 0145, 0146, 0147,
 176         0150, 0151, 0304, 0305, 0306, 0307, 0310, 0311,
 177         0312, 0152, 0153, 0154, 0155, 0156, 0157, 0160,
 178         0161, 0162, 0136, 0314, 0315, 0316, 0317, 0320,
 179         0321, 0345, 0163, 0164, 0165, 0166, 0167, 0170,
 180         0171, 0172, 0322, 0323, 0324, 0133, 0326, 0327,
 181         0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337,
 182         0340, 0341, 0342, 0343, 0344, 0135, 0346, 0347,
 183         0173, 0101, 0102, 0103, 0104, 0105, 0106, 0107,
 184         0110, 0111, 0350, 0351, 0352, 0353, 0354, 0355,
 185         0175, 0112, 0113, 0114, 0115, 0116, 0117, 0120,
 186         0121, 0122, 0356, 0357, 0360, 0361, 0362, 0363,
 187         0134, 0237, 0123, 0124, 0125, 0126, 0127, 0130,
 188         0131, 0132, 0364, 0365, 0366, 0367, 0370, 0371,
 189         0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067,
 190         0070, 0071, 0372, 0373, 0374, 0375, 0376, 0377,
 191 };
 192 
 193 /* This is an ASCII to EBCDIC conversion table  */
 194 /* from a proposed BTL standard April 16, 1979  */
 195 
 196 static unsigned char svr4_atoe [] =
 197 {
 198         0000, 0001, 0002, 0003, 0067, 0055, 0056, 0057,
 199         0026, 0005, 0045, 0013, 0014, 0015, 0016, 0017,
 200         0020, 0021, 0022, 0023, 0074, 0075, 0062, 0046,
 201         0030, 0031, 0077, 0047, 0034, 0035, 0036, 0037,
 202         0100, 0132, 0177, 0173, 0133, 0154, 0120, 0175,
 203         0115, 0135, 0134, 0116, 0153, 0140, 0113, 0141,
 204         0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367,
 205         0370, 0371, 0172, 0136, 0114, 0176, 0156, 0157,
 206         0174, 0301, 0302, 0303, 0304, 0305, 0306, 0307,
 207         0310, 0311, 0321, 0322, 0323, 0324, 0325, 0326,
 208         0327, 0330, 0331, 0342, 0343, 0344, 0345, 0346,
 209         0347, 0350, 0351, 0255, 0340, 0275, 0232, 0155,
 210         0171, 0201, 0202, 0203, 0204, 0205, 0206, 0207,
 211         0210, 0211, 0221, 0222, 0223, 0224, 0225, 0226,
 212         0227, 0230, 0231, 0242, 0243, 0244, 0245, 0246,
 213         0247, 0250, 0251, 0300, 0117, 0320, 0137, 0007,
 214         0040, 0041, 0042, 0043, 0044, 0025, 0006, 0027,
 215         0050, 0051, 0052, 0053, 0054, 0011, 0012, 0033,
 216         0060, 0061, 0032, 0063, 0064, 0065, 0066, 0010,
 217         0070, 0071, 0072, 0073, 0004, 0024, 0076, 0341,
 218         0101, 0102, 0103, 0104, 0105, 0106, 0107, 0110,
 219         0111, 0121, 0122, 0123, 0124, 0125, 0126, 0127,
 220         0130, 0131, 0142, 0143, 0144, 0145, 0146, 0147,
 221         0150, 0151, 0160, 0161, 0162, 0163, 0164, 0165,
 222         0166, 0167, 0170, 0200, 0212, 0213, 0214, 0215,
 223         0216, 0217, 0220, 0152, 0233, 0234, 0235, 0236,
 224         0237, 0240, 0252, 0253, 0254, 0112, 0256, 0257,
 225         0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267,
 226         0270, 0271, 0272, 0273, 0274, 0241, 0276, 0277,
 227         0312, 0313, 0314, 0315, 0316, 0317, 0332, 0333,
 228         0334, 0335, 0336, 0337, 0352, 0353, 0354, 0355,
 229         0356, 0357, 0372, 0373, 0374, 0375, 0376, 0377,
 230 };
 231 
 232 /* Table for ASCII to IBM (alternate EBCDIC) code conversion    */
 233 
 234 static unsigned char svr4_atoibm[] =
 235 {
 236         0000, 0001, 0002, 0003, 0067, 0055, 0056, 0057,
 237         0026, 0005, 0045, 0013, 0014, 0015, 0016, 0017,
 238         0020, 0021, 0022, 0023, 0074, 0075, 0062, 0046,
 239         0030, 0031, 0077, 0047, 0034, 0035, 0036, 0037,
 240         0100, 0132, 0177, 0173, 0133, 0154, 0120, 0175,
 241         0115, 0135, 0134, 0116, 0153, 0140, 0113, 0141,
 242         0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367,
 243         0370, 0371, 0172, 0136, 0114, 0176, 0156, 0157,
 244         0174, 0301, 0302, 0303, 0304, 0305, 0306, 0307,
 245         0310, 0311, 0321, 0322, 0323, 0324, 0325, 0326,
 246         0327, 0330, 0331, 0342, 0343, 0344, 0345, 0346,
 247         0347, 0350, 0351, 0255, 0340, 0275, 0137, 0155,
 248         0171, 0201, 0202, 0203, 0204, 0205, 0206, 0207,
 249         0210, 0211, 0221, 0222, 0223, 0224, 0225, 0226,
 250         0227, 0230, 0231, 0242, 0243, 0244, 0245, 0246,
 251         0247, 0250, 0251, 0300, 0117, 0320, 0241, 0007,
 252         0040, 0041, 0042, 0043, 0044, 0025, 0006, 0027,
 253         0050, 0051, 0052, 0053, 0054, 0011, 0012, 0033,
 254         0060, 0061, 0032, 0063, 0064, 0065, 0066, 0010,
 255         0070, 0071, 0072, 0073, 0004, 0024, 0076, 0341,
 256         0101, 0102, 0103, 0104, 0105, 0106, 0107, 0110,
 257         0111, 0121, 0122, 0123, 0124, 0125, 0126, 0127,
 258         0130, 0131, 0142, 0143, 0144, 0145, 0146, 0147,
 259         0150, 0151, 0160, 0161, 0162, 0163, 0164, 0165,
 260         0166, 0167, 0170, 0200, 0212, 0213, 0214, 0215,
 261         0216, 0217, 0220, 0232, 0233, 0234, 0235, 0236,
 262         0237, 0240, 0252, 0253, 0254, 0255, 0256, 0257,
 263         0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267,
 264         0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277,
 265         0312, 0313, 0314, 0315, 0316, 0317, 0332, 0333,
 266         0334, 0335, 0336, 0337, 0352, 0353, 0354, 0355,
 267         0356, 0357, 0372, 0373, 0374, 0375, 0376, 0377,
 268 };
 269 
 270 /* Table for conversion of ASCII to lower case ASCII    */
 271 
 272 static unsigned char utol[] =
 273 {
 274         0000, 0001, 0002, 0003, 0004, 0005, 0006, 0007,
 275         0010, 0011, 0012, 0013, 0014, 0015, 0016, 0017,
 276         0020, 0021, 0022, 0023, 0024, 0025, 0026, 0027,
 277         0030, 0031, 0032, 0033, 0034, 0035, 0036, 0037,
 278         0040, 0041, 0042, 0043, 0044, 0045, 0046, 0047,
 279         0050, 0051, 0052, 0053, 0054, 0055, 0056, 0057,
 280         0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067,
 281         0070, 0071, 0072, 0073, 0074, 0075, 0076, 0077,
 282         0100, 0141, 0142, 0143, 0144, 0145, 0146, 0147,
 283         0150, 0151, 0152, 0153, 0154, 0155, 0156, 0157,
 284         0160, 0161, 0162, 0163, 0164, 0165, 0166, 0167,
 285         0170, 0171, 0172, 0133, 0134, 0135, 0136, 0137,
 286         0140, 0141, 0142, 0143, 0144, 0145, 0146, 0147,
 287         0150, 0151, 0152, 0153, 0154, 0155, 0156, 0157,
 288         0160, 0161, 0162, 0163, 0164, 0165, 0166, 0167,
 289         0170, 0171, 0172, 0173, 0174, 0175, 0176, 0177,
 290         0200, 0201, 0202, 0203, 0204, 0205, 0206, 0207,
 291         0210, 0211, 0212, 0213, 0214, 0215, 0216, 0217,
 292         0220, 0221, 0222, 0223, 0224, 0225, 0226, 0227,
 293         0230, 0231, 0232, 0233, 0234, 0235, 0236, 0237,
 294         0240, 0241, 0242, 0243, 0244, 0245, 0246, 0247,
 295         0250, 0251, 0252, 0253, 0254, 0255, 0256, 0257,
 296         0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267,
 297         0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277,
 298         0300, 0301, 0302, 0303, 0304, 0305, 0306, 0307,
 299         0310, 0311, 0312, 0313, 0314, 0315, 0316, 0317,
 300         0320, 0321, 0322, 0323, 0324, 0325, 0326, 0327,
 301         0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337,
 302         0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347,
 303         0350, 0351, 0352, 0353, 0354, 0355, 0356, 0357,
 304         0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367,
 305         0370, 0371, 0372, 0373, 0374, 0375, 0376, 0377,
 306 };
 307 
 308 /* Table for conversion of ASCII to upper case ASCII    */
 309 
 310 static unsigned char ltou[] =
 311 {
 312         0000, 0001, 0002, 0003, 0004, 0005, 0006, 0007,
 313         0010, 0011, 0012, 0013, 0014, 0015, 0016, 0017,
 314         0020, 0021, 0022, 0023, 0024, 0025, 0026, 0027,
 315         0030, 0031, 0032, 0033, 0034, 0035, 0036, 0037,
 316         0040, 0041, 0042, 0043, 0044, 0045, 0046, 0047,
 317         0050, 0051, 0052, 0053, 0054, 0055, 0056, 0057,
 318         0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067,
 319         0070, 0071, 0072, 0073, 0074, 0075, 0076, 0077,
 320         0100, 0101, 0102, 0103, 0104, 0105, 0106, 0107,
 321         0110, 0111, 0112, 0113, 0114, 0115, 0116, 0117,
 322         0120, 0121, 0122, 0123, 0124, 0125, 0126, 0127,
 323         0130, 0131, 0132, 0133, 0134, 0135, 0136, 0137,
 324         0140, 0101, 0102, 0103, 0104, 0105, 0106, 0107,
 325         0110, 0111, 0112, 0113, 0114, 0115, 0116, 0117,
 326         0120, 0121, 0122, 0123, 0124, 0125, 0126, 0127,
 327         0130, 0131, 0132, 0173, 0174, 0175, 0176, 0177,
 328         0200, 0201, 0202, 0203, 0204, 0205, 0206, 0207,
 329         0210, 0211, 0212, 0213, 0214, 0215, 0216, 0217,
 330         0220, 0221, 0222, 0223, 0224, 0225, 0226, 0227,
 331         0230, 0231, 0232, 0233, 0234, 0235, 0236, 0237,
 332         0240, 0241, 0242, 0243, 0244, 0245, 0246, 0247,
 333         0250, 0251, 0252, 0253, 0254, 0255, 0256, 0257,
 334         0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267,
 335         0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277,
 336         0300, 0301, 0302, 0303, 0304, 0305, 0306, 0307,
 337         0310, 0311, 0312, 0313, 0314, 0315, 0316, 0317,
 338         0320, 0321, 0322, 0323, 0324, 0325, 0326, 0327,
 339         0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337,
 340         0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347,
 341         0350, 0351, 0352, 0353, 0354, 0355, 0356, 0357,
 342         0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367,
 343         0370, 0371, 0372, 0373, 0374, 0375, 0376, 0377,
 344 };
 345 
 346 /* BSD-compatible EBCDIC to ASCII translate table */
 347 
 348 static unsigned char    bsd_etoa[] =
 349 {
 350         0000, 0001, 0002, 0003, 0234, 0011, 0206, 0177,
 351         0227, 0215, 0216, 0013, 0014, 0015, 0016, 0017,
 352         0020, 0021, 0022, 0023, 0235, 0205, 0010, 0207,
 353         0030, 0031, 0222, 0217, 0034, 0035, 0036, 0037,
 354         0200, 0201, 0202, 0203, 0204, 0012, 0027, 0033,
 355         0210, 0211, 0212, 0213, 0214, 0005, 0006, 0007,
 356         0220, 0221, 0026, 0223, 0224, 0225, 0226, 0004,
 357         0230, 0231, 0232, 0233, 0024, 0025, 0236, 0032,
 358         0040, 0240, 0241, 0242, 0243, 0244, 0245, 0246,
 359         0247, 0250, 0133, 0056, 0074, 0050, 0053, 0041,
 360         0046, 0251, 0252, 0253, 0254, 0255, 0256, 0257,
 361         0260, 0261, 0135, 0044, 0052, 0051, 0073, 0136,
 362         0055, 0057, 0262, 0263, 0264, 0265, 0266, 0267,
 363         0270, 0271, 0174, 0054, 0045, 0137, 0076, 0077,
 364         0272, 0273, 0274, 0275, 0276, 0277, 0300, 0301,
 365         0302, 0140, 0072, 0043, 0100, 0047, 0075, 0042,
 366         0303, 0141, 0142, 0143, 0144, 0145, 0146, 0147,
 367         0150, 0151, 0304, 0305, 0306, 0307, 0310, 0311,
 368         0312, 0152, 0153, 0154, 0155, 0156, 0157, 0160,
 369         0161, 0162, 0313, 0314, 0315, 0316, 0317, 0320,
 370         0321, 0176, 0163, 0164, 0165, 0166, 0167, 0170,
 371         0171, 0172, 0322, 0323, 0324, 0325, 0326, 0327,
 372         0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337,
 373         0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347,
 374         0173, 0101, 0102, 0103, 0104, 0105, 0106, 0107,
 375         0110, 0111, 0350, 0351, 0352, 0353, 0354, 0355,
 376         0175, 0112, 0113, 0114, 0115, 0116, 0117, 0120,
 377         0121, 0122, 0356, 0357, 0360, 0361, 0362, 0363,
 378         0134, 0237, 0123, 0124, 0125, 0126, 0127, 0130,
 379         0131, 0132, 0364, 0365, 0366, 0367, 0370, 0371,
 380         0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067,
 381         0070, 0071, 0372, 0373, 0374, 0375, 0376, 0377,
 382 };
 383 
 384 /* BSD-compatible ASCII to EBCDIC translate table */
 385 
 386 static unsigned char    bsd_atoe[] =
 387 {
 388         0000, 0001, 0002, 0003, 0067, 0055, 0056, 0057,
 389         0026, 0005, 0045, 0013, 0014, 0015, 0016, 0017,
 390         0020, 0021, 0022, 0023, 0074, 0075, 0062, 0046,
 391         0030, 0031, 0077, 0047, 0034, 0035, 0036, 0037,
 392         0100, 0117, 0177, 0173, 0133, 0154, 0120, 0175,
 393         0115, 0135, 0134, 0116, 0153, 0140, 0113, 0141,
 394         0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367,
 395         0370, 0371, 0172, 0136, 0114, 0176, 0156, 0157,
 396         0174, 0301, 0302, 0303, 0304, 0305, 0306, 0307,
 397         0310, 0311, 0321, 0322, 0323, 0324, 0325, 0326,
 398         0327, 0330, 0331, 0342, 0343, 0344, 0345, 0346,
 399         0347, 0350, 0351, 0112, 0340, 0132, 0137, 0155,
 400         0171, 0201, 0202, 0203, 0204, 0205, 0206, 0207,
 401         0210, 0211, 0221, 0222, 0223, 0224, 0225, 0226,
 402         0227, 0230, 0231, 0242, 0243, 0244, 0245, 0246,
 403         0247, 0250, 0251, 0300, 0152, 0320, 0241, 0007,
 404         0040, 0041, 0042, 0043, 0044, 0025, 0006, 0027,
 405         0050, 0051, 0052, 0053, 0054, 0011, 0012, 0033,
 406         0060, 0061, 0032, 0063, 0064, 0065, 0066, 0010,
 407         0070, 0071, 0072, 0073, 0004, 0024, 0076, 0341,
 408         0101, 0102, 0103, 0104, 0105, 0106, 0107, 0110,
 409         0111, 0121, 0122, 0123, 0124, 0125, 0126, 0127,
 410         0130, 0131, 0142, 0143, 0144, 0145, 0146, 0147,
 411         0150, 0151, 0160, 0161, 0162, 0163, 0164, 0165,
 412         0166, 0167, 0170, 0200, 0212, 0213, 0214, 0215,
 413         0216, 0217, 0220, 0232, 0233, 0234, 0235, 0236,
 414         0237, 0240, 0252, 0253, 0254, 0255, 0256, 0257,
 415         0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267,
 416         0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277,
 417         0312, 0313, 0314, 0315, 0316, 0317, 0332, 0333,
 418         0334, 0335, 0336, 0337, 0352, 0353, 0354, 0355,
 419         0356, 0357, 0372, 0373, 0374, 0375, 0376, 0377,
 420 };
 421 
 422 /* BSD-compatible ASCII to IBM translate table */
 423 
 424 static unsigned char    bsd_atoibm[] =
 425 {
 426         0000, 0001, 0002, 0003, 0067, 0055, 0056, 0057,
 427         0026, 0005, 0045, 0013, 0014, 0015, 0016, 0017,
 428         0020, 0021, 0022, 0023, 0074, 0075, 0062, 0046,
 429         0030, 0031, 0077, 0047, 0034, 0035, 0036, 0037,
 430         0100, 0132, 0177, 0173, 0133, 0154, 0120, 0175,
 431         0115, 0135, 0134, 0116, 0153, 0140, 0113, 0141,
 432         0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367,
 433         0370, 0371, 0172, 0136, 0114, 0176, 0156, 0157,
 434         0174, 0301, 0302, 0303, 0304, 0305, 0306, 0307,
 435         0310, 0311, 0321, 0322, 0323, 0324, 0325, 0326,
 436         0327, 0330, 0331, 0342, 0343, 0344, 0345, 0346,
 437         0347, 0350, 0351, 0255, 0340, 0275, 0137, 0155,
 438         0171, 0201, 0202, 0203, 0204, 0205, 0206, 0207,
 439         0210, 0211, 0221, 0222, 0223, 0224, 0225, 0226,
 440         0227, 0230, 0231, 0242, 0243, 0244, 0245, 0246,
 441         0247, 0250, 0251, 0300, 0117, 0320, 0241, 0007,
 442         0040, 0041, 0042, 0043, 0044, 0025, 0006, 0027,
 443         0050, 0051, 0052, 0053, 0054, 0011, 0012, 0033,
 444         0060, 0061, 0032, 0063, 0064, 0065, 0066, 0010,
 445         0070, 0071, 0072, 0073, 0004, 0024, 0076, 0341,
 446         0101, 0102, 0103, 0104, 0105, 0106, 0107, 0110,
 447         0111, 0121, 0122, 0123, 0124, 0125, 0126, 0127,
 448         0130, 0131, 0142, 0143, 0144, 0145, 0146, 0147,
 449         0150, 0151, 0160, 0161, 0162, 0163, 0164, 0165,
 450         0166, 0167, 0170, 0200, 0212, 0213, 0214, 0215,
 451         0216, 0217, 0220, 0232, 0233, 0234, 0235, 0236,
 452         0237, 0240, 0252, 0253, 0254, 0255, 0256, 0257,
 453         0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267,
 454         0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277,
 455         0312, 0313, 0314, 0315, 0316, 0317, 0332, 0333,
 456         0334, 0335, 0336, 0337, 0352, 0353, 0354, 0355,
 457         0356, 0357, 0372, 0373, 0374, 0375, 0376, 0377,
 458 };
 459 
 460 /* set up to use SVr4 ascii-ebcdic translation by default */
 461 
 462 static unsigned char *atoe = svr4_atoe;
 463 static unsigned char *etoa = svr4_etoa;
 464 static unsigned char *atoibm = svr4_atoibm;
 465 
 466 
 467 int
 468 main(int argc, char **argv)
 469 {
 470         unsigned char *ip, *op; /* input and output buffer pointers */
 471         int c;          /* character counter */
 472         int ic;         /* input character */
 473         int conv;               /* conversion option code */
 474         int trunc;              /* whether output file is truncated */
 475         struct stat file_stat;
 476 
 477         /* Set option defaults */
 478 
 479         ibs = BSIZE;
 480         obs = BSIZE;
 481         files = 1;
 482         conv = COPY;
 483         trunc = 1;                      /* default: truncate output file */
 484         trantype = SVR4XLATE;  /* use SVR4 EBCDIC by default */
 485 
 486         /* Parse command options */
 487 
 488         (void) setlocale(LC_ALL, "");
 489 #if !defined(TEXT_DOMAIN)       /* Should be defined by cc -D */
 490 #define TEXT_DOMAIN "SYS_TEST"  /* Use this only if it weren't */
 491 #endif
 492         (void) textdomain(TEXT_DOMAIN);
 493 
 494         while ((c = getopt(argc, argv, "")) != EOF)
 495                 switch (c) {
 496                         case '?':
 497                         (void) fprintf(stderr, USAGE);
 498                         exit(2);
 499                 }
 500 
 501         /* not getopt()'ed because dd has no options but only operand(s) */
 502 
 503         for (c = optind; c < argc; c++)
 504         {
 505                 string = argv[c];
 506                 if (match("ibs="))
 507                 {
 508                         ibs = (unsigned)number(BIG);
 509                         continue;
 510                 }
 511                 if (match("obs="))
 512                 {
 513                         obs = (unsigned)number(BIG);
 514                         continue;
 515                 }
 516                 if (match("cbs="))
 517                 {
 518                         cbs = (unsigned)number(BIG);
 519                         continue;
 520                 }
 521                 if (match("bs="))
 522                 {
 523                         bs = (unsigned)number(BIG);
 524                         continue;
 525                 }
 526                 if (match("if="))
 527                 {
 528                         ifile = string;
 529                         continue;
 530                 }
 531                 if (match("of="))
 532                 {
 533                         ofile = string;
 534                         continue;
 535                 }
 536                 if (match("skip="))
 537                 {
 538                         skip = number(BIG);
 539                         continue;
 540                 }
 541                 if (match("iseek="))
 542                 {
 543                         iseekn = number(BIG);
 544                         continue;
 545                 }
 546                 if (match("oseek="))
 547                 {
 548                         oseekn = number(BIG);
 549                         continue;
 550                 }
 551                 if (match("seek="))             /* retained for compatibility */
 552                 {
 553                         oseekn = number(BIG);
 554                         continue;
 555                 }
 556                 if (match("count="))
 557                 {
 558                         count = number(BIG);
 559                         continue;
 560                 }
 561                 if (match("files="))
 562                 {
 563                         files = (int)number(BIG);
 564                         continue;
 565                 }
 566                 if (match("conv="))
 567                 {
 568                         for (;;)
 569                         {
 570                                 if (match(","))
 571                                 {
 572                                         continue;
 573                                 }
 574                                 if (*string == '\0')
 575                                 {
 576                                         break;
 577                                 }
 578                                 if (match("block"))
 579                                 {
 580                                         conv = BLOCK;
 581                                         continue;
 582                                 }
 583                                 if (match("unblock"))
 584                                 {
 585                                         conv = UNBLOCK;
 586                                         continue;
 587                                 }
 588 
 589                                 /* ebcdicb, ibmb, and asciib must precede */
 590                                 /* ebcdic, ibm, and ascii in this test */
 591 
 592                                 if (match("ebcdicb"))
 593                                 {
 594                                         conv = EBCDIC;
 595                                         trantype = BSDXLATE;
 596                                         continue;
 597                                 }
 598                                 if (match("ibmb"))
 599                                 {
 600                                         conv = IBM;
 601                                         trantype = BSDXLATE;
 602                                         continue;
 603                                 }
 604                                 if (match("asciib"))
 605                                 {
 606                                         conv = ASCII;
 607                                         trantype = BSDXLATE;
 608                                         continue;
 609                                 }
 610                                 if (match("ebcdic"))
 611                                 {
 612                                         conv = EBCDIC;
 613                                         trantype = SVR4XLATE;
 614                                         continue;
 615                                 }
 616                                 if (match("ibm"))
 617                                 {
 618                                         conv = IBM;
 619                                         trantype = SVR4XLATE;
 620                                         continue;
 621                                 }
 622                                 if (match("ascii"))
 623                                 {
 624                                         conv = ASCII;
 625                                         trantype = SVR4XLATE;
 626                                         continue;
 627                                 }
 628                                 if (match("lcase"))
 629                                 {
 630                                         cflag |= LCASE;
 631                                         continue;
 632                                 }
 633                                 if (match("ucase"))
 634                                 {
 635                                         cflag |= UCASE;
 636                                         continue;
 637                                 }
 638                                 if (match("swab"))
 639                                 {
 640                                         cflag |= SWAB;
 641                                         continue;
 642                                 }
 643                                 if (match("noerror"))
 644                                 {
 645                                         cflag |= NERR;
 646                                         continue;
 647                                 }
 648                                 if (match("notrunc"))
 649                                 {
 650                                         trunc = 0;
 651                                         continue;
 652                                 }
 653                                 if (match("sync"))
 654                                 {
 655                                         cflag |= SYNC;
 656                                         continue;
 657                                 }
 658                                 goto badarg;
 659                         }
 660                         continue;
 661                 }
 662                 badarg:
 663                 (void) fprintf(stderr, "dd: %s \"%s\"\n",
 664                         gettext("bad argument:"), string);
 665                 exit(2);
 666         }
 667 
 668         /* Perform consistency checks on options, decode strange conventions */
 669 
 670         if (bs)
 671         {
 672                 ibs = obs = bs;
 673         }
 674         if ((ibs == 0) || (obs == 0))
 675         {
 676                 (void) fprintf(stderr, "dd: %s\n",
 677                         gettext("buffer sizes cannot be zero"));
 678                 exit(2);
 679         }
 680         if (conv == COPY)
 681         {
 682                 if ((bs == 0) || (cflag&(LCASE|UCASE)))
 683                 {
 684                         conv = REBLOCK;
 685                 }
 686         }
 687         if (cbs == 0)
 688         {
 689                 switch (conv)
 690                 {
 691                 case BLOCK:
 692                 case UNBLOCK:
 693                         conv = REBLOCK;
 694                         break;
 695 
 696                 case ASCII:
 697                         conv = NBASCII;
 698                         break;
 699 
 700                 case EBCDIC:
 701                         conv = NBEBCDIC;
 702                         break;
 703 
 704                 case IBM:
 705                         conv = NBIBM;
 706                         break;
 707                 }
 708         }
 709 
 710         /* Expand options into lower and upper case versions if necessary */
 711 
 712         switch (conv)
 713         {
 714         case REBLOCK:
 715                 if (cflag&LCASE)
 716                         conv = LCREBLOCK;
 717                 else if (cflag&UCASE)
 718                         conv = UCREBLOCK;
 719                 break;
 720 
 721         case UNBLOCK:
 722                 if (cflag&LCASE)
 723                         conv = LCUNBLOCK;
 724                 else if (cflag&UCASE)
 725                         conv = UCUNBLOCK;
 726                 break;
 727 
 728         case BLOCK:
 729                 if (cflag&LCASE)
 730                         conv = LCBLOCK;
 731                 else if (cflag&UCASE)
 732                         conv = UCBLOCK;
 733                 break;
 734 
 735         case ASCII:
 736                 if (cflag&LCASE)
 737                         conv = LCASCII;
 738                 else if (cflag&UCASE)
 739                         conv = UCASCII;
 740                 break;
 741 
 742         case NBASCII:
 743                 if (cflag&LCASE)
 744                         conv = LCNBASCII;
 745                 else if (cflag&UCASE)
 746                         conv = UCNBASCII;
 747                 break;
 748 
 749         case EBCDIC:
 750                 if (cflag&LCASE)
 751                         conv = LCEBCDIC;
 752                 else if (cflag&UCASE)
 753                         conv = UCEBCDIC;
 754                 break;
 755 
 756         case NBEBCDIC:
 757                 if (cflag&LCASE)
 758                         conv = LCNBEBCDIC;
 759                 else if (cflag&UCASE)
 760                         conv = UCNBEBCDIC;
 761                 break;
 762 
 763         case IBM:
 764                 if (cflag&LCASE)
 765                         conv = LCIBM;
 766                 else if (cflag&UCASE)
 767                         conv = UCIBM;
 768                 break;
 769 
 770         case NBIBM:
 771                 if (cflag&LCASE)
 772                         conv = LCNBIBM;
 773                 else if (cflag&UCASE)
 774                         conv = UCNBIBM;
 775                 break;
 776         }
 777 
 778         /* If BSD-compatible translation is selected, change the tables */
 779 
 780         if (trantype == BSDXLATE) {
 781                 atoe = bsd_atoe;
 782                 atoibm = bsd_atoibm;
 783                 etoa = bsd_etoa;
 784         }
 785         /* Open the input file, or duplicate standard input */
 786 
 787         ibf = -1;
 788         if (ifile)
 789         {
 790                 ibf = open(ifile, 0);
 791         }
 792 #ifndef STANDALONE
 793         else
 794         {
 795                 ifile = "";
 796                 ibf = dup(0);
 797         }
 798 #endif
 799         if (ibf == -1)
 800         {
 801                 (void) fprintf(stderr, "dd: %s: ", ifile);
 802                 perror("open");
 803                 exit(2);
 804         }
 805 
 806         /* Open the output file, or duplicate standard output */
 807 
 808         obf = -1;
 809         if (ofile)
 810         {
 811                 if (trunc == 0) /* do not truncate output file */
 812                         obf = open(ofile, (O_WRONLY|O_CREAT),
 813                         (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH));
 814                 else if (oseekn && (trunc == 1))
 815                 {
 816                         obf = open(ofile, O_WRONLY|O_CREAT,
 817                         (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH));
 818                         if (obf == -1)
 819                         {
 820                                 (void) fprintf(stderr, "dd: %s: ", ofile);
 821                                 perror("open");
 822                                 exit(2);
 823                         }
 824                         (void) fstat(obf, &file_stat);
 825                         if (((file_stat.st_mode & S_IFMT) == S_IFREG) &&
 826                             (ftruncate(obf, (((off_t)oseekn) * ((off_t)obs)))
 827                                 == -1))
 828                         {
 829                                 perror("ftruncate");
 830                                 exit(2);
 831                         }
 832                 }
 833                 else
 834                         obf = creat(ofile,
 835                         (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH));
 836         }
 837 #ifndef STANDALONE
 838         else
 839         {
 840                 ofile = "";
 841                 obf = dup(1);
 842         }
 843 #endif
 844         if (obf == -1)
 845         {
 846                 (void) fprintf(stderr, "dd: %s: ", ofile);
 847                 perror("open");
 848                 exit(2);
 849         }
 850 
 851         /* Expand memory to get an input buffer */
 852 
 853         ibuf = (unsigned char *)valloc(ibs + 10);
 854 
 855         /* If no conversions, the input buffer is the output buffer */
 856 
 857         if (conv == COPY)
 858         {
 859                 obuf = ibuf;
 860         }
 861 
 862         /* Expand memory to get an output buffer. Leave enough room at the */
 863         /* end to convert a logical record when doing block conversions. */
 864 
 865         else
 866         {
 867                 obuf = (unsigned char *)valloc(obs + cbs + 10);
 868         }
 869         if ((ibuf == (unsigned char *)NULL) || (obuf == (unsigned char *)NULL))
 870         {
 871                 (void) fprintf(stderr,
 872                         "dd: %s\n", gettext("not enough memory"));
 873                 exit(2);
 874         }
 875 
 876         /* Enable a statistics message on SIGINT */
 877 
 878 #ifndef STANDALONE
 879         if (signal(SIGINT, SIG_IGN) != SIG_IGN)
 880         {
 881                 (void) signal(SIGINT, term);
 882         }
 883 #endif
 884         /* Skip input blocks */
 885 
 886         while (skip)
 887         {
 888                 ibc = read(ibf, (char *)ibuf, ibs);
 889                 if (ibc == (unsigned)-1)
 890                 {
 891                         if (++nbad > BADLIMIT)
 892                         {
 893                                 (void) fprintf(stderr, "dd: %s\n",
 894                                         gettext("skip failed"));
 895                                 exit(2);
 896                         }
 897                         else
 898                         {
 899                                 perror("read");
 900                         }
 901                 }
 902                 else
 903                 {
 904                         if (ibc == 0)
 905                         {
 906                                 (void) fprintf(stderr, "dd: %s\n",
 907                                 gettext("cannot skip past end-of-file"));
 908                                 exit(3);
 909                         }
 910                         else
 911                         {
 912                                 nbad = 0;
 913                         }
 914                 }
 915                 skip--;
 916         }
 917 
 918         /* Seek past input blocks */
 919 
 920         if (iseekn && lseek(ibf, (((off_t)iseekn) * ((off_t)ibs)), 1) == -1)
 921         {
 922                 perror("lseek");
 923                 exit(2);
 924         }
 925 
 926         /* Seek past output blocks */
 927 
 928         if (oseekn && lseek(obf, (((off_t)oseekn) * ((off_t)obs)), 1) == -1)
 929         {
 930                 perror("lseek");
 931                 exit(2);
 932         }
 933 
 934         /* Initialize all buffer pointers */
 935 
 936         skipf = 0;      /* not skipping an input line */
 937         ibc = 0;        /* no input characters yet */
 938         obc = 0;        /* no output characters yet */
 939         cbc = 0;        /* the conversion buffer is empty */
 940         op = obuf;      /* point to the output buffer */
 941 
 942         /* Read and convert input blocks until end of file(s) */
 943 
 944         for (;;)
 945         {
 946                 if ((count == 0) || (nifr+nipr < count))
 947                 {
 948                 /* If proceed on error is enabled, zero the input buffer */
 949 
 950                         if (cflag&NERR)
 951                         {
 952                                 ip = ibuf + ibs;
 953                                 c = ibs;
 954                                 if (c & 1)  /* if the size is odd, */
 955                                 {
 956                                         *--ip = 0;      /* clear the odd byte */
 957                                 }
 958                                 if (c >>= 1)              /* divide by two */
 959                                 {
 960                                         do {    /* clear two at a time */
 961                                                 *--ip = 0;
 962                                                 *--ip = 0;
 963                                         } while (--c);
 964                                 }
 965                         }
 966 
 967                         /* Read the next input block */
 968 
 969                         ibc = read(ibf, (char *)ibuf, ibs);
 970 
 971                         /* Process input errors */
 972 
 973                         if (ibc == (unsigned)-1)
 974                         {
 975                                 perror("read");
 976                                 if (((cflag&NERR) == 0) || (++nbad > BADLIMIT))
 977                                 {
 978                                         while (obc)
 979                                         {
 980                                                 (void) flsh();
 981                                         }
 982                                         term(2);
 983                                 }
 984                                 else
 985                                 {
 986                                         stats();
 987                                         ibc = ibs; /* assume a full block */
 988                                 }
 989                         }
 990                         else
 991                         {
 992                                 nbad = 0;
 993                         }
 994                 }
 995 
 996                 /* Record count satisfied, simulate end of file */
 997 
 998                 else
 999                 {
1000                         ibc = 0;
1001                         files = 1;
1002                 }
1003 
1004                 /* Process end of file */
1005 
1006                 if (ibc == 0)
1007                 {
1008                         switch (conv)
1009                         {
1010                         case UNBLOCK:
1011                         case LCUNBLOCK:
1012                         case UCUNBLOCK:
1013                         case ASCII:
1014                         case LCASCII:
1015                         case UCASCII:
1016 
1017                                 /* Trim trailing blanks from the last line */
1018 
1019                                 if ((c = cbc) != 0)
1020                                 {
1021                                         do {
1022                                                 if ((*--op) != ' ')
1023                                                 {
1024                                                         op++;
1025                                                         break;
1026                                                 }
1027                                         } while (--c);
1028                                         *op++ = '\n';
1029                                         obc -= cbc - c - 1;
1030                                         cbc = 0;
1031 
1032                                         /* Flush the output buffer if full */
1033 
1034                                         while (obc >= obs)
1035                                         {
1036                                                 op = flsh();
1037                                         }
1038                                 }
1039                                 break;
1040 
1041                         case BLOCK:
1042                         case LCBLOCK:
1043                         case UCBLOCK:
1044                         case EBCDIC:
1045                         case LCEBCDIC:
1046                         case UCEBCDIC:
1047                         case IBM:
1048                         case LCIBM:
1049                         case UCIBM:
1050 
1051                         /* Pad trailing blanks if the last line is short */
1052 
1053                                 if (cbc)
1054                                 {
1055                                         obc += c = cbs - cbc;
1056                                         cbc = 0;
1057                                         if (c > 0)
1058                                         {
1059                                         /* Use the right kind of blank */
1060 
1061                                                 switch (conv)
1062                                                 {
1063                                                 case BLOCK:
1064                                                 case LCBLOCK:
1065                                                 case UCBLOCK:
1066                                                         ic = ' ';
1067                                                         break;
1068 
1069                                                 case EBCDIC:
1070                                                 case LCEBCDIC:
1071                                                 case UCEBCDIC:
1072                                                         ic = atoe[' '];
1073                                                         break;
1074 
1075                                                 case IBM:
1076                                                 case LCIBM:
1077                                                 case UCIBM:
1078                                                         ic = atoibm[' '];
1079                                                         break;
1080                                                 }
1081 
1082                                                 /* Pad with trailing blanks */
1083 
1084                                                 do {
1085                                                         *op++ = ic;
1086                                                 } while (--c);
1087                                         }
1088                                 }
1089 
1090 
1091                                 /* Flush the output buffer if full */
1092 
1093                                 while (obc >= obs)
1094                                 {
1095                                         op = flsh();
1096                                 }
1097                                 break;
1098                         }
1099 
1100                         /* If no more files to read, flush the output buffer */
1101 
1102                         if (--files <= 0)
1103                         {
1104                                 (void) flsh();
1105                                 if ((close(obf) != 0) || (fclose(stdout) != 0))
1106                                 {
1107                                         perror(gettext("dd: close error"));
1108                                         exit(2);
1109                                 }
1110                                 term(0);        /* successful exit */
1111                         }
1112                         else
1113                         {
1114                                 continue;       /* read the next file */
1115                         }
1116                 }
1117 
1118                 /* Normal read, check for special cases */
1119 
1120                 else if (ibc == ibs)
1121                 {
1122                         nifr++;         /* count another full input record */
1123                 }
1124                 else
1125                 {
1126                         nipr++;         /* count a partial input record */
1127 
1128                         /* If `sync' enabled, pad nulls */
1129 
1130                         if ((cflag&SYNC) && ((cflag&NERR) == 0))
1131                         {
1132                                 c = ibs - ibc;
1133                                 ip = ibuf + ibs;
1134                                 do {
1135                                 if ((conv == BLOCK) || (conv == UNBLOCK))
1136                                         *--ip = ' ';
1137                                 else
1138                                         *--ip = '\0';
1139                                 } while (--c);
1140                                 ibc = ibs;
1141                         }
1142                 }
1143 
1144                 /* Swap the bytes in the input buffer if necessary */
1145 
1146                 if (cflag&SWAB)
1147                 {
1148                         ip = ibuf;
1149                         if (ibc & 1)        /* if the byte count is odd, */
1150                         {
1151                                 ip[ibc] = 0;  /* make it even, pad with zero */
1152                         }
1153                         c = ibc >> 1;     /* compute the pair count */
1154                         do {
1155                                 ic = *ip++;
1156                                 ip[-1] = *ip;
1157                                 *ip++ = ic;
1158                         } while (--c);          /* do two bytes at a time */
1159                 }
1160 
1161                 /* Select the appropriate conversion loop */
1162 
1163                 ip = ibuf;
1164                 switch (conv)
1165                 {
1166 
1167                 /* Simple copy: no conversion, preserve the input block size */
1168 
1169                 case COPY:
1170                         obc = ibc;
1171                         (void) flsh();
1172                         break;
1173 
1174                 /* Simple copy: pack all output into equal sized blocks */
1175 
1176                 case REBLOCK:
1177                 case LCREBLOCK:
1178                 case UCREBLOCK:
1179                 case NBASCII:
1180                 case LCNBASCII:
1181                 case UCNBASCII:
1182                 case NBEBCDIC:
1183                 case LCNBEBCDIC:
1184                 case UCNBEBCDIC:
1185                 case NBIBM:
1186                 case LCNBIBM:
1187                 case UCNBIBM:
1188                         while ((c = ibc) != 0)
1189                         {
1190                                 if (c > (obs - obc))
1191                                 {
1192                                         c = obs - obc;
1193                                 }
1194                                 ibc -= c;
1195                                 obc += c;
1196                                 switch (conv)
1197                                 {
1198                                 case REBLOCK:
1199                                         do {
1200                                                 *op++ = *ip++;
1201                                         } while (--c);
1202                                         break;
1203 
1204                                 case LCREBLOCK:
1205                                         do {
1206                                                 *op++ = utol[*ip++];
1207                                         } while (--c);
1208                                         break;
1209 
1210                                 case UCREBLOCK:
1211                                         do {
1212                                                 *op++ = ltou[*ip++];
1213                                         } while (--c);
1214                                         break;
1215 
1216                                 case NBASCII:
1217                                         do {
1218                                                 *op++ = etoa[*ip++];
1219                                         } while (--c);
1220                                         break;
1221 
1222                                 case LCNBASCII:
1223                                         do {
1224                                                 *op++ = utol[etoa[*ip++]];
1225                                         } while (--c);
1226                                         break;
1227 
1228                                 case UCNBASCII:
1229                                         do {
1230                                                 *op++ = ltou[etoa[*ip++]];
1231                                         } while (--c);
1232                                         break;
1233 
1234                                 case NBEBCDIC:
1235                                         do {
1236                                                 *op++ = atoe[*ip++];
1237                                         } while (--c);
1238                                         break;
1239 
1240                                 case LCNBEBCDIC:
1241                                         do {
1242                                                 *op++ = atoe[utol[*ip++]];
1243                                         } while (--c);
1244                                         break;
1245 
1246                                 case UCNBEBCDIC:
1247                                         do {
1248                                                 *op++ = atoe[ltou[*ip++]];
1249                                         } while (--c);
1250                                         break;
1251 
1252                                 case NBIBM:
1253                                         do {
1254                                                 *op++ = atoibm[*ip++];
1255                                         } while (--c);
1256                                         break;
1257 
1258                                 case LCNBIBM:
1259                                         do {
1260                                                 *op++ = atoibm[utol[*ip++]];
1261                                         } while (--c);
1262                                         break;
1263 
1264                                 case UCNBIBM:
1265                                         do {
1266                                                 *op++ = atoibm[ltou[*ip++]];
1267                                         } while (--c);
1268                                         break;
1269                                 }
1270                                 if (obc >= obs)
1271                                 {
1272                                         op = flsh();
1273                                 }
1274                         }
1275                         break;
1276 
1277         /* Convert from blocked records to lines terminated by newline */
1278 
1279                 case UNBLOCK:
1280                 case LCUNBLOCK:
1281                 case UCUNBLOCK:
1282                 case ASCII:
1283                 case LCASCII:
1284                 case UCASCII:
1285                         while ((c = ibc) != 0)
1286                         {
1287                                 if (c > (cbs - cbc))
1288                                                 /* if more than one record, */
1289                                 {
1290                                         c = cbs - cbc;
1291                                                 /* only copy one record */
1292                                 }
1293                                 ibc -= c;
1294                                 cbc += c;
1295                                 obc += c;
1296                                 switch (conv)
1297                                 {
1298                                 case UNBLOCK:
1299                                         do {
1300                                                 *op++ = *ip++;
1301                                         } while (--c);
1302                                         break;
1303 
1304                                 case LCUNBLOCK:
1305                                         do {
1306                                                 *op++ = utol[*ip++];
1307                                         } while (--c);
1308                                         break;
1309 
1310                                 case UCUNBLOCK:
1311                                         do {
1312                                                 *op++ = ltou[*ip++];
1313                                         } while (--c);
1314                                         break;
1315 
1316                                 case ASCII:
1317                                         do {
1318                                                 *op++ = etoa[*ip++];
1319                                         } while (--c);
1320                                         break;
1321 
1322                                 case LCASCII:
1323                                         do {
1324                                                 *op++ = utol[etoa[*ip++]];
1325                                         } while (--c);
1326                                         break;
1327 
1328                                 case UCASCII:
1329                                         do {
1330                                                 *op++ = ltou[etoa[*ip++]];
1331                                         } while (--c);
1332                                         break;
1333                                 }
1334 
1335                                 /* Trim trailing blanks if the line is full */
1336 
1337                                 if (cbc == cbs)
1338                                 {
1339                                         c = cbs; /* `do - while' is usually */
1340                                         do {            /* faster than `for' */
1341                                                 if ((*--op) != ' ')
1342                                                 {
1343                                                         op++;
1344                                                         break;
1345                                                 }
1346                                         } while (--c);
1347                                         *op++ = '\n';
1348                                         obc -= cbs - c - 1;
1349                                         cbc = 0;
1350 
1351                                         /* Flush the output buffer if full */
1352 
1353                                         while (obc >= obs)
1354                                         {
1355                                                 op = flsh();
1356                                         }
1357                                 }
1358                         }
1359                         break;
1360 
1361                 /* Convert to blocked records */
1362 
1363                 case BLOCK:
1364                 case LCBLOCK:
1365                 case UCBLOCK:
1366                 case EBCDIC:
1367                 case LCEBCDIC:
1368                 case UCEBCDIC:
1369                 case IBM:
1370                 case LCIBM:
1371                 case UCIBM:
1372                         while ((c = ibc) != 0)
1373                         {
1374                                 int nlflag = 0;
1375 
1376                         /* We may have to skip to the end of a long line */
1377 
1378                                 if (skipf)
1379                                 {
1380                                         do {
1381                                                 if ((ic = *ip++) == '\n')
1382                                                 {
1383                                                         skipf = 0;
1384                                                         c--;
1385                                                         break;
1386                                                 }
1387                                         } while (--c);
1388                                         if ((ibc = c) == 0)
1389                                         {
1390                                                 continue;
1391                                                         /* read another block */
1392                                         }
1393                                 }
1394 
1395                                 /* If anything left, copy until newline */
1396 
1397                                 if (c > (cbs - cbc + 1))
1398                                 {
1399                                         c = cbs - cbc + 1;
1400                                 }
1401                                 ibc -= c;
1402                                 cbc += c;
1403                                 obc += c;
1404 
1405                                 switch (conv)
1406                                 {
1407                                 case BLOCK:
1408                                         do {
1409                                                 if ((ic = *ip++) != '\n')
1410                                                 {
1411                                                         *op++ = ic;
1412                                                 }
1413                                                 else
1414                                                 {
1415                                                         nlflag = 1;
1416                                                         break;
1417                                                 }
1418                                         } while (--c);
1419                                         break;
1420 
1421                                 case LCBLOCK:
1422                                         do {
1423                                                 if ((ic = *ip++) != '\n')
1424                                                 {
1425                                                         *op++ = utol[ic];
1426                                                 }
1427                                                 else
1428                                                 {
1429                                                         nlflag = 1;
1430                                                         break;
1431                                                 }
1432                                         } while (--c);
1433                                         break;
1434 
1435                                 case UCBLOCK:
1436                                         do {
1437                                                 if ((ic = *ip++) != '\n')
1438                                                 {
1439                                                         *op++ = ltou[ic];
1440                                                 }
1441                                                 else
1442                                                 {
1443                                                         nlflag = 1;
1444                                                         break;
1445                                                 }
1446                                         } while (--c);
1447                                         break;
1448 
1449                                 case EBCDIC:
1450                                         do {
1451                                                 if ((ic = *ip++) != '\n')
1452                                                 {
1453                                                         *op++ = atoe[ic];
1454                                                 }
1455                                                 else
1456                                                 {
1457                                                         nlflag = 1;
1458                                                         break;
1459                                                 }
1460                                         } while (--c);
1461                                         break;
1462 
1463                                 case LCEBCDIC:
1464                                         do {
1465                                                 if ((ic = *ip++) != '\n')
1466                                                 {
1467                                                         *op++ = atoe[utol[ic]];
1468                                                 }
1469                                                 else
1470                                                 {
1471                                                         nlflag = 1;
1472                                                         break;
1473                                                 }
1474                                         } while (--c);
1475                                         break;
1476 
1477                                 case UCEBCDIC:
1478                                         do {
1479                                                 if ((ic = *ip++) != '\n')
1480                                                 {
1481                                                         *op++ = atoe[ltou[ic]];
1482                                                 }
1483                                                 else
1484                                                 {
1485                                                         nlflag = 1;
1486                                                         break;
1487                                                 }
1488                                         } while (--c);
1489                                         break;
1490 
1491                                 case IBM:
1492                                         do {
1493                                                 if ((ic = *ip++) != '\n')
1494                                                 {
1495                                                         *op++ = atoibm[ic];
1496                                                 }
1497                                                 else
1498                                                 {
1499                                                         nlflag = 1;
1500                                                         break;
1501                                                 }
1502                                         } while (--c);
1503                                         break;
1504 
1505                                 case LCIBM:
1506                                         do {
1507                                                 if ((ic = *ip++) != '\n')
1508                                                 {
1509                                                 *op++ = atoibm[utol[ic]];
1510                                                 }
1511                                                 else
1512                                                 {
1513                                                         nlflag = 1;
1514                                                         break;
1515                                                 }
1516                                         } while (--c);
1517                                         break;
1518 
1519                                 case UCIBM:
1520                                         do {
1521                                                 if ((ic = *ip++) != '\n')
1522                                                 {
1523                                                 *op++ = atoibm[ltou[ic]];
1524                                                 }
1525                                                 else
1526                                                 {
1527                                                         nlflag = 1;
1528                                                         break;
1529                                                 }
1530                                         } while (--c);
1531                                         break;
1532                                 }
1533 
1534                         /* If newline found, update all the counters and */
1535                         /* pointers, pad with trailing blanks if necessary */
1536 
1537                                 if (nlflag)
1538                                 {
1539                                         ibc += c - 1;
1540                                         obc += cbs - cbc;
1541                                         c += cbs - cbc;
1542                                         cbc = 0;
1543                                         if (c > 0)
1544                                         {
1545                                         /* Use the right kind of blank */
1546 
1547                                                 switch (conv)
1548                                                 {
1549                                                 case BLOCK:
1550                                                 case LCBLOCK:
1551                                                 case UCBLOCK:
1552                                                         ic = ' ';
1553                                                         break;
1554 
1555                                                 case EBCDIC:
1556                                                 case LCEBCDIC:
1557                                                 case UCEBCDIC:
1558                                                         ic = atoe[' '];
1559                                                         break;
1560 
1561                                                 case IBM:
1562                                                 case LCIBM:
1563                                                 case UCIBM:
1564                                                         ic = atoibm[' '];
1565                                                         break;
1566                                                 }
1567 
1568                                                 /* Pad with trailing blanks */
1569 
1570                                                 do {
1571                                                         *op++ = ic;
1572                                                 } while (--c);
1573                                         }
1574                                 }
1575 
1576                         /* If not end of line, this line may be too long */
1577 
1578                                 else if (cbc > cbs)
1579                                 {
1580                                         skipf = 1; /* note skip in progress */
1581                                         obc--;
1582                                         op--;
1583                                         cbc = 0;
1584                                         ntrunc++;  /* count another long line */
1585                                 }
1586 
1587                                 /* Flush the output buffer if full */
1588 
1589                                 while (obc >= obs)
1590                                 {
1591                                         op = flsh();
1592                                 }
1593                         }
1594                         break;
1595                 }
1596         }
1597         /* NOTREACHED */
1598         return (0);
1599 }
1600 
1601 /* match ************************************************************** */
1602 /*                                                                      */
1603 /* Compare two text strings for equality                                */
1604 /*                                                                      */
1605 /* Arg:         s - pointer to string to match with a command arg       */
1606 /* Global arg:  string - pointer to command arg                         */
1607 /*                                                                      */
1608 /* Return:      1 if match, 0 if no match                               */
1609 /*              If match, also reset `string' to point to the text      */
1610 /*              that follows the matching text.                         */
1611 /*                                                                      */
1612 /* ******************************************************************** */
1613 
1614 static int
1615 match(s)
1616 char *s;
1617 {
1618         char *cs;
1619 
1620         cs = string;
1621         while (*cs++ == *s)
1622         {
1623                 if (*s++ == '\0')
1624                 {
1625                         goto true;
1626                 }
1627         }
1628         if (*s != '\0')
1629         {
1630                 return (0);
1631         }
1632 
1633 true:
1634         cs--;
1635         string = cs;
1636         return (1);
1637 }
1638 
1639 /* number ************************************************************* */
1640 /*                                                                      */
1641 /* Convert a numeric arg to binary                                      */
1642 /*                                                                      */
1643 /* Arg:         big - maximum valid input number                        */
1644 /* Global arg:  string - pointer to command arg                         */
1645 /*                                                                      */
1646 /* Valid forms: 123 | 123k | 123M | 123G | 123T | 123P | 123E | 123Z |  */
1647 /*              123w | 123b | 123*123 | 123x123                         */
1648 /*              plus combinations such as 2b*3kw*4w                     */
1649 /*                                                                      */
1650 /* Return:      converted number                                        */
1651 /*                                                                      */
1652 /* ******************************************************************** */
1653 
1654 static unsigned long long
1655 number(big)
1656 long long big;
1657 {
1658         char *cs;
1659         long long n;
1660         long long cut = BIG / 10;       /* limit to avoid overflow */
1661 
1662         cs = string;
1663         n = 0;
1664         while ((*cs >= '0') && (*cs <= '9') && (n <= cut))
1665         {
1666                 n = n*10 + *cs++ - '0';
1667         }
1668         for (;;)
1669         {
1670                 switch (*cs++)
1671                 {
1672 
1673                 case 'Z':
1674                         n *= 1024;
1675                         /* FALLTHROUGH */
1676 
1677                 case 'E':
1678                         n *= 1024;
1679                         /* FALLTHROUGH */
1680 
1681                 case 'P':
1682                         n *= 1024;
1683                         /* FALLTHROUGH */
1684 
1685                 case 'T':
1686                         n *= 1024;
1687                         /* FALLTHROUGH */
1688 
1689                 case 'G':
1690                         n *= 1024;
1691                         /* FALLTHROUGH */
1692 
1693                 case 'M':
1694                         n *= 1024;
1695                         /* FALLTHROUGH */
1696 
1697                 case 'k':
1698                         n *= 1024;
1699                         continue;
1700 
1701                 case 'w':
1702                         n *= 2;
1703                         continue;
1704 
1705                 case 'b':
1706                         n *= BSIZE;
1707                         continue;
1708 
1709                 case '*':
1710                 case 'x':
1711                         string = cs;
1712                         n *= number(BIG);
1713 
1714                 /* FALLTHROUGH */
1715                 /* Fall into exit test, recursion has read rest of string */
1716                 /* End of string, check for a valid number */
1717 
1718                 case '\0':
1719                         if ((n > big) || (n < 0))
1720                         {
1721                                 (void) fprintf(stderr, "dd: %s \"%llu\"\n",
1722                                         gettext("argument out of range:"), n);
1723                                 exit(2);
1724                         }
1725                         return (n);
1726 
1727                 default:
1728                         (void) fprintf(stderr, "dd: %s \"%s\"\n",
1729                                 gettext("bad numeric argument:"), string);
1730                         exit(2);
1731                 }
1732         } /* never gets here */
1733 }
1734 
1735 /* flsh *************************************************************** */
1736 /*                                                                      */
1737 /* Flush the output buffer, move any excess bytes down to the beginning */
1738 /*                                                                      */
1739 /* Arg:         none                                                    */
1740 /* Global args: obuf, obc, obs, nofr, nopr                              */
1741 /*                                                                      */
1742 /* Return:      Pointer to the first free byte in the output buffer.    */
1743 /*              Also reset `obc' to account for moved bytes.            */
1744 /*                                                                      */
1745 /* ******************************************************************** */
1746 
1747 static unsigned char
1748 *flsh()
1749 {
1750         unsigned char *op, *cp;
1751         int bc;
1752         unsigned int oc;
1753 
1754         if (obc)                        /* don't flush if the buffer is empty */
1755         {
1756                 if (obc >= obs) {
1757                         oc = obs;
1758                         nofr++;         /* count a full output buffer */
1759                 }
1760                 else
1761                 {
1762                         oc = obc;
1763                         nopr++;         /* count a partial output buffer */
1764                 }
1765                 bc = write(obf, (char *)obuf, oc);
1766                 if (bc != oc) {
1767                         if (bc < 0)
1768                                 perror("write");
1769                         else
1770                         (void) fprintf(stderr,
1771                                 gettext("dd: unexpected short write, "
1772                                 "wrote %d bytes, expected %d\n"), bc, oc);
1773                         term(2);
1774                 }
1775                 obc -= oc;
1776                 op = obuf;
1777 
1778                 /* If any data in the conversion buffer, move it into */
1779                 /* the output buffer */
1780 
1781                 if (obc) {
1782                         cp = obuf + obs;
1783                         bc = obc;
1784                         do {
1785                                 *op++ = *cp++;
1786                         } while (--bc);
1787                 }
1788                 return (op);
1789         }
1790         return (obuf);
1791 }
1792 
1793 /* term *************************************************************** */
1794 /*                                                                      */
1795 /* Write record statistics, then exit                                   */
1796 /*                                                                      */
1797 /* Arg:         c - exit status code                                    */
1798 /*                                                                      */
1799 /* Return:      no return, calls exit                                   */
1800 /*                                                                      */
1801 /* ******************************************************************** */
1802 
1803 static void
1804 term(c)
1805 int c;
1806 {
1807         stats();
1808         exit(c);
1809 }
1810 
1811 /* stats ************************************************************** */
1812 /*                                                                      */
1813 /* Write record statistics onto standard error                          */
1814 /*                                                                      */
1815 /* Args:        none                                                    */
1816 /* Global args: nifr, nipr, nofr, nopr, ntrunc                          */
1817 /*                                                                      */
1818 /* Return:      void                                                    */
1819 /*                                                                      */
1820 /* ******************************************************************** */
1821 
1822 static void
1823 stats()
1824 {
1825         (void) fprintf(stderr, gettext("%llu+%llu records in\n"), nifr, nipr);
1826         (void) fprintf(stderr, gettext("%llu+%llu records out\n"), nofr, nopr);
1827         if (ntrunc) {
1828                 (void) fprintf(stderr,
1829                         gettext("%llu truncated record(s)\n"), ntrunc);
1830         }
1831 }