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(®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 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