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