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
main(int argc,char ** argv)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(®s, ®s);
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
error(format,args)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
usage()492 usage()
493 {
494 fprintf(stderr,
495 "usage: unix2dos [ -ascii ] [ -iso ] [ -7 ] [ originalfile [ convertedfile ] ]\n");
496 exit(1);
497 }
498