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