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