xref: /illumos-gate/usr/src/cmd/sunpc/other/unix2dos.c (revision 8b80e8cb6855118d46f605e91b5ed4ce83417395)
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  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 
30 /*
31  *	Converts files from one char set to another
32  *
33  *	Written 11/09/87	Eddy Bell
34  *
35  */
36 
37 
38 /*
39  *  INCLUDED and DEFINES
40  */
41 #include	<stdio.h>
42 #include	<fcntl.h>
43 #include	<sys/systeminfo.h>
44 #include	<stdlib.h>
45 #include	<string.h>
46 #include	<errno.h>
47 /* #include	<io.h>			for microsoft c 4.0 */
48 
49 
50 #define		CONTENTS_ASCII	0
51 #define		CONTENTS_ASCII8 1
52 #define		CONTENTS_ISO	2
53 #define		CONTENTS_DOS	3
54 #ifdef _F_BIN
55 #define	DOS_BUILD 1
56 #else
57 #define	UNIX_BUILD 1
58 #endif
59 
60 
61 /*
62  * INCLUDES AND DEFINES
63  *
64  */
65 #ifdef UNIX_BUILD
66 #include <sys/types.h>
67 #include	<sys/kbio.h>
68 #include	<sys/time.h>
69 #include	<fcntl.h>
70 #include "../sys/dos_iso.h"
71 #endif
72 
73 #ifdef DOS_BUILD
74 #include <dos.h>
75 #include "..\sys\dos_iso.h"
76 #endif
77 
78 
79 #define		GLOBAL
80 #define		LOCAL	static
81 #define		BOOL	int
82 
83 #define		FALSE	0
84 #define		TRUE	~FALSE
85 
86 #define		CR	0x0D
87 #define		LF	0x0A
88 #define		DOS_EOF 0x1A
89 
90 #define		MAXLEN	1024
91 
92 /*
93  * FUNCTION AND VARIABLE DECLARATIONS
94  */
95 static	void	error();
96 static	void	usage();
97 static	int	tmpfd = -1;
98 /*
99  * ENTRY POINTS
100  */
101 
102 int
103 main(int argc, char **argv)
104 {
105 	FILE *in_stream = NULL;
106 	FILE *out_stream = NULL;
107 	unsigned char tmp_buff[512];
108 
109 	unsigned char *src_str, *dest_str;
110 	char	 *in_file_name, *out_file_name;
111 	int num_read, numchar, i, j, out_len, translate_mode;
112 	int same_name;
113 	/* char count for fread() */
114 
115 	int	type;
116 	int	code_page_overide; /* over ride of default codepage */
117 
118 	unsigned char * dos_to_iso;
119 	unsigned char iso_to_dos[256];
120 #ifdef UNIX_BUILD
121 	int	kbdfd;
122 #endif
123 	char	sysinfo_str[MAXLEN];
124 
125 	same_name = FALSE;
126 	out_file_name = (char *)0;
127 
128 	/*
129 	 * The filename parameter is positionally dependent - in that
130 	 * the dest file name must follow the source filename
131 	 */
132 	argv++;
133 	in_stream = stdin;
134 	out_stream = stdout;
135 	j = 0;  /* count for file names 0 -> source 1-> dest */
136 	translate_mode = CONTENTS_ISO; /* default trans mode */
137 	code_page_overide = 0;
138 	for (i = 1; i < argc; i++) {
139 		if (*argv[0] == '-') {
140 			if (argc > 1 && !strncmp(*argv, "-iso", 4)) {
141 				translate_mode = CONTENTS_ISO;
142 				argv++;
143 			} else if (argc > 1 && !strncmp(*argv, "-7", 2)) {
144 				translate_mode = CONTENTS_ASCII;
145 				argv++;
146 			} else if (argc > 1 && !strncmp(*argv, "-ascii", 6)) {
147 				translate_mode = CONTENTS_DOS;
148 				argv++;
149 			} else if (argc > 1 && !strncmp(*argv, "-437", 4)) {
150 				code_page_overide = CODE_PAGE_US;
151 				argv++;
152 			} else if (argc > 1 && !strncmp(*argv, "-850", 4)) {
153 				code_page_overide = CODE_PAGE_MULTILINGUAL;
154 				argv++;
155 			} else if (argc > 1 && !strncmp(*argv, "-860", 4)) {
156 				code_page_overide = CODE_PAGE_PORTUGAL;
157 				argv++;
158 			} else if (argc > 1 && !strncmp(*argv, "-863", 4)) {
159 				code_page_overide = CODE_PAGE_CANADA_FRENCH;
160 				argv++;
161 			} else if (argc > 1 && !strncmp(*argv, "-865", 4)) {
162 				code_page_overide = CODE_PAGE_NORWAY;
163 				argv++;
164 			} else
165 				argv++;
166 			continue;
167 		} else {  /* not a command so must be filename */
168 			switch (j) {
169 				case IN_FILE:	/* open in file from cmdline */
170 					in_file_name = *argv;
171 					j++;  /* next file name is outfile */
172 					break;
173 
174 				case OUT_FILE:	/* open out file from cmdline */
175 					out_file_name = *argv;
176 					j++;
177 					break;
178 
179 				default:
180 					usage();
181 			}
182 		}
183 	argv++;
184 	}
185 
186 	/* input file is specified */
187 	if (j > 0) {
188 		in_stream = fopen(in_file_name, "r");
189 		if (in_stream == NULL)
190 			error("Couldn't open input file %s.", in_file_name);
191 	}
192 
193 	/* output file is specified */
194 	if (j > 1) {
195 		if (!strcmp(in_file_name, out_file_name)) {
196 			/* input and output have same name */
197 			if (access(out_file_name, 2))
198 				error("%s not writable.", out_file_name);
199 			strcpy(out_file_name, "/tmp/udXXXXXX");
200 			tmpfd = mkstemp(out_file_name);
201 			if (tmpfd == -1) {
202 				error("Couldn't create output file %s.",
203 				    out_file_name);
204 			}
205 			(void) close(tmpfd);
206 			same_name = TRUE;
207 		} else
208 			same_name = FALSE;
209 		out_stream = fopen(out_file_name, "w");
210 		if (out_stream == NULL) {
211 			(void) unlink(out_file_name);
212 			error("Couldn't open output file %s.", out_file_name);
213 		}
214 
215 	}
216 #ifdef _F_BIN
217 	setmode(fileno(in_stream), O_BINARY);
218 	setmode(fileno(out_stream), O_BINARY);
219 #endif
220 
221 
222 #ifdef UNIX_BUILD
223 	if (!code_page_overide) {
224 		if (sysinfo(SI_ARCHITECTURE, sysinfo_str, MAXLEN)  < 0) {
225 			fprintf(stderr,
226 			    "could not obtain system information\n");
227 			(void) unlink(out_file_name);
228 			exit(1);
229 
230 		}
231 		if (strcmp(sysinfo_str, "i386")) {
232 			if ((kbdfd = open("/dev/kbd", O_WRONLY)) < 0) {
233 				fprintf(stderr,
234 				    "could not open /dev/kbd to get "
235 				    "keyboard type US keyboard assumed\n");
236 			}
237 			if (ioctl(kbdfd, KIOCLAYOUT, &type) < 0) {
238 				fprintf(stderr,
239 	"could not get keyboard type US keyboard assumed\n");
240 			}
241 		} else {
242 			type = 0;
243 		}
244 		switch (type) {
245 			case	0:
246 			case	1:	/* United States */
247 				dos_to_iso = &dos_to_iso_cp_437[0];
248 			break;
249 
250 			case	2:	/* Belgian French */
251 				dos_to_iso = &dos_to_iso_cp_437[0];
252 			break;
253 
254 			case	3:	/* Canadian French */
255 				dos_to_iso = &dos_to_iso_cp_863[0];
256 			break;
257 
258 			case	4:	/* Danish */
259 				dos_to_iso = &dos_to_iso_cp_865[0];
260 			break;
261 
262 			case	5:	/* German */
263 				dos_to_iso = &dos_to_iso_cp_437[0];
264 			break;
265 
266 			case	6:	/* Italian */
267 				dos_to_iso = &dos_to_iso_cp_437[0];
268 			break;
269 
270 			case	7:	/* Netherlands Dutch */
271 				dos_to_iso = &dos_to_iso_cp_437[0];
272 			break;
273 
274 			case	8:	/* Norwegian */
275 				dos_to_iso = &dos_to_iso_cp_865[0];
276 			break;
277 
278 			case	9:	/* Portuguese */
279 				dos_to_iso = &dos_to_iso_cp_860[0];
280 			break;
281 
282 			case	10:	/* Spanish */
283 				dos_to_iso = &dos_to_iso_cp_437[0];
284 			break;
285 
286 			case	11:	/* Swedish Finnish */
287 				dos_to_iso = &dos_to_iso_cp_437[0];
288 			break;
289 
290 			case	12:	/* Swiss French */
291 				dos_to_iso = &dos_to_iso_cp_437[0];
292 			break;
293 
294 			case	13:	/* Swiss German */
295 				dos_to_iso = &dos_to_iso_cp_437[0];
296 			break;
297 
298 			case	14:	/* United Kingdom */
299 				dos_to_iso = &dos_to_iso_cp_437[0];
300 
301 			break;
302 
303 			default:
304 				dos_to_iso = &dos_to_iso_cp_437[0];
305 			break;
306 		}
307 	} else {
308 		switch (code_page_overide) {
309 			case CODE_PAGE_US:
310 				dos_to_iso = &dos_to_iso_cp_437[0];
311 			break;
312 
313 			case CODE_PAGE_MULTILINGUAL:
314 				dos_to_iso = &dos_to_iso_cp_850[0];
315 			break;
316 
317 			case CODE_PAGE_PORTUGAL:
318 				dos_to_iso = &dos_to_iso_cp_860[0];
319 			break;
320 
321 			case CODE_PAGE_CANADA_FRENCH:
322 				dos_to_iso = &dos_to_iso_cp_863[0];
323 			break;
324 
325 			case CODE_PAGE_NORWAY:
326 				dos_to_iso = &dos_to_iso_cp_865[0];
327 			break;
328 		}
329 	}
330 #endif
331 #ifdef DOS_BUILD
332 	if (!code_page_overide) {
333 		{
334 		union REGS regs;
335 		regs.h.ah = 0x66;	/* get/set global code page */
336 		regs.h.al = 0x01;		/* get */
337 		intdos(&regs, &regs);
338 		type = regs.x.bx;
339 		}
340 		switch (type) {
341 			case	437:	/* United States */
342 				dos_to_iso = &dos_to_iso_cp_437[0];
343 			break;
344 
345 			case	850:	/* Multilingual */
346 				dos_to_iso = &dos_to_iso_cp_850[0];
347 			break;
348 
349 			case	860:	/* Portuguese */
350 				dos_to_iso = &dos_to_iso_cp_860[0];
351 			break;
352 
353 			case	863:	/* Canadian French */
354 				dos_to_iso = &dos_to_iso_cp_863[0];
355 			break;
356 
357 			case	865:	/* Danish */
358 				dos_to_iso = &dos_to_iso_cp_865[0];
359 			break;
360 
361 			default:
362 				dos_to_iso = &dos_to_iso_cp_437[0];
363 			break;
364 		}
365 	} else {
366 		switch (code_page_overide) {
367 			case CODE_PAGE_US:
368 				dos_to_iso = &dos_to_iso_cp_437[0];
369 			break;
370 
371 			case CODE_PAGE_MULTILINGUAL:
372 				dos_to_iso = &dos_to_iso_cp_850[0];
373 			break;
374 
375 			case CODE_PAGE_PORTUGAL:
376 				dos_to_iso = &dos_to_iso_cp_860[0];
377 			break;
378 
379 			case CODE_PAGE_CANADA_FRENCH:
380 				dos_to_iso = &dos_to_iso_cp_863[0];
381 			break;
382 
383 			case CODE_PAGE_NORWAY:
384 				dos_to_iso = &dos_to_iso_cp_865[0];
385 			break;
386 		}
387 	}
388 
389 #endif
390 	for (i = 0; i <= 255; i++) {
391 		iso_to_dos[dos_to_iso[i]] = i;
392 	}
393 
394 	/*
395 	 * While not EOF, read in chars and send them to out_stream
396 	 * if current char is not a CR.
397 	 */
398 
399     do {
400 		num_read = fread(&tmp_buff[100], 1, 100, in_stream);
401 		i = 0;
402 		out_len = 0;
403 		src_str = &tmp_buff[100];
404 		dest_str = &tmp_buff[0];
405 		switch (translate_mode) {
406 			case CONTENTS_ISO:
407 				{
408 				while (i++ != num_read) {
409 					if (*src_str == '\n') {
410 						*dest_str++ = '\r';
411 						out_len++;
412 						}
413 					out_len++;
414 					*dest_str++ = iso_to_dos[*src_str++];
415 					}
416 				}
417 				break;
418 
419 			case CONTENTS_ASCII:
420 				while (i++ != num_read) {
421 					if (*src_str > 127) {
422 						*dest_str++ =
423 						    (unsigned char) ' ';
424 						src_str++;
425 						out_len++;
426 					} else {
427 						if (*src_str == '\n') {
428 							*dest_str++ = '\r';
429 							out_len++;
430 						}
431 						*dest_str++ = *src_str++;
432 						out_len++;
433 					}
434 				}
435 				break;
436 
437 			case CONTENTS_DOS:
438 				{
439 				while (i++ != num_read) {
440 					if (*src_str == '\n') {
441 						*dest_str++ = '\r';
442 						out_len++;
443 						}
444 					*dest_str++ =	*src_str++;
445 					out_len++;
446 					}
447 				}
448 				break;
449 			}
450 		if (out_len && out_len != fwrite(&tmp_buff[0], 1, out_len,
451 		    out_stream))
452 			error("Error writing to %s.", out_file_name);
453 
454 		} while (!feof(in_stream));
455 
456 #ifdef CTRL_Z_ON_EOF
457 	tmp_buff[0] = 26;
458 	fwrite(&tmp_buff[0], 1, 1, out_stream);
459 #endif
460 	fclose(out_stream);
461 	fclose(in_stream);
462 	if (same_name) {
463 		unlink(in_file_name);
464 		in_stream = fopen(out_file_name, "r");
465 		out_stream = fopen(in_file_name, "w");
466 #ifdef _F_BIN
467 		setmode(fileno(in_stream), O_BINARY);
468 		setmode(fileno(out_stream), O_BINARY);
469 #endif
470 		while ((num_read = fread(tmp_buff, 1, sizeof (tmp_buff),
471 		    in_stream)) != 0) {
472 			if (num_read != fwrite(tmp_buff, 1, num_read,
473 			    out_stream))
474 				error("Error writing to %s.", in_file_name);
475 		}
476 		fclose(out_stream);
477 		fclose(in_stream);
478 		unlink(out_file_name);
479 	}
480 	return (0);
481 }
482 
483 void
484 error(format, args)
485 	char	*format;
486 	char	*args;
487 {
488 	fprintf(stderr, "unix2dos: ");
489 	fprintf(stderr, format, args);
490 	fprintf(stderr, "  %s.\n", strerror(errno));
491 	exit(1);
492 }
493 
494 void
495 usage()
496 {
497 	fprintf(stderr,
498 	    "usage: unix2dos [ -ascii ] [ -iso ] [ -7 ] [ originalfile [ convertedfile ] ]\n");
499 	exit(1);
500 }
501