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 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 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 495 usage() 496 { 497 fprintf(stderr, 498 "usage: unix2dos [ -ascii ] [ -iso ] [ -7 ] [ originalfile [ convertedfile ] ]\n"); 499 exit(1); 500 } 501