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