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