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