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