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