luit.c revision a8fdb4bc
1a8fdb4bcSmrg/* 2a8fdb4bcSmrgCopyright (c) 2001 by Juliusz Chroboczek 3a8fdb4bcSmrg 4a8fdb4bcSmrgPermission is hereby granted, free of charge, to any person obtaining a copy 5a8fdb4bcSmrgof this software and associated documentation files (the "Software"), to deal 6a8fdb4bcSmrgin the Software without restriction, including without limitation the rights 7a8fdb4bcSmrgto use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8a8fdb4bcSmrgcopies of the Software, and to permit persons to whom the Software is 9a8fdb4bcSmrgfurnished to do so, subject to the following conditions: 10a8fdb4bcSmrg 11a8fdb4bcSmrgThe above copyright notice and this permission notice shall be included in 12a8fdb4bcSmrgall copies or substantial portions of the Software. 13a8fdb4bcSmrg 14a8fdb4bcSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15a8fdb4bcSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16a8fdb4bcSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17a8fdb4bcSmrgAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18a8fdb4bcSmrgLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19a8fdb4bcSmrgOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20a8fdb4bcSmrgTHE SOFTWARE. 21a8fdb4bcSmrg*/ 22a8fdb4bcSmrg/* $XFree86: xc/programs/luit/luit.c,v 1.9 2002/10/17 01:06:09 dawes Exp $ */ 23a8fdb4bcSmrg 24a8fdb4bcSmrg#include <stdio.h> 25a8fdb4bcSmrg#include <stdlib.h> 26a8fdb4bcSmrg#include <string.h> 27a8fdb4bcSmrg#include <locale.h> 28a8fdb4bcSmrg#include <sys/types.h> 29a8fdb4bcSmrg#include <fcntl.h> 30a8fdb4bcSmrg#include <unistd.h> 31a8fdb4bcSmrg#include <errno.h> 32a8fdb4bcSmrg#include <assert.h> 33a8fdb4bcSmrg#include <stdarg.h> 34a8fdb4bcSmrg#include <sys/ioctl.h> 35a8fdb4bcSmrg#include <signal.h> 36a8fdb4bcSmrg 37a8fdb4bcSmrg#ifdef SVR4 38a8fdb4bcSmrg#include <stropts.h> 39a8fdb4bcSmrg#endif 40a8fdb4bcSmrg 41a8fdb4bcSmrg#include <X11/fonts/fontenc.h> 42a8fdb4bcSmrg#include "luit.h" 43a8fdb4bcSmrg#include "sys.h" 44a8fdb4bcSmrg#include "other.h" 45a8fdb4bcSmrg#include "charset.h" 46a8fdb4bcSmrg#include "iso2022.h" 47a8fdb4bcSmrg 48a8fdb4bcSmrgstatic Iso2022Ptr inputState = NULL, outputState = NULL; 49a8fdb4bcSmrg 50a8fdb4bcSmrgstatic char *child_argv0 = NULL; 51a8fdb4bcSmrgstatic char *locale_name = NULL; 52a8fdb4bcSmrgint ilog = -1; 53a8fdb4bcSmrgint olog = -1; 54a8fdb4bcSmrgint verbose = 0; 55a8fdb4bcSmrgint converter = 0; 56a8fdb4bcSmrgint exitOnChild = 0; 57a8fdb4bcSmrg 58a8fdb4bcSmrgvolatile int sigwinch_queued = 0; 59a8fdb4bcSmrgvolatile int sigchld_queued = 0; 60a8fdb4bcSmrg 61a8fdb4bcSmrgstatic int convert(int, int); 62a8fdb4bcSmrgstatic int condom(int, char**); 63a8fdb4bcSmrg 64a8fdb4bcSmrgstatic void 65a8fdb4bcSmrgErrorF(char *f, ...) 66a8fdb4bcSmrg{ 67a8fdb4bcSmrg va_list args; 68a8fdb4bcSmrg va_start(args, f); 69a8fdb4bcSmrg vfprintf(stderr, f, args); 70a8fdb4bcSmrg va_end(args); 71a8fdb4bcSmrg} 72a8fdb4bcSmrg 73a8fdb4bcSmrgstatic void 74a8fdb4bcSmrgFatalError(char *f, ...) 75a8fdb4bcSmrg{ 76a8fdb4bcSmrg va_list args; 77a8fdb4bcSmrg va_start(args, f); 78a8fdb4bcSmrg vfprintf(stderr, f, args); 79a8fdb4bcSmrg va_end(args); 80a8fdb4bcSmrg exit(1); 81a8fdb4bcSmrg} 82a8fdb4bcSmrg 83a8fdb4bcSmrg 84a8fdb4bcSmrgstatic void 85a8fdb4bcSmrghelp(void) 86a8fdb4bcSmrg{ 87a8fdb4bcSmrg fprintf(stderr, 88a8fdb4bcSmrg "luit\n" 89a8fdb4bcSmrg " [ -h ] [ -list ] [ -v ] [ -argv0 name ]\n" 90a8fdb4bcSmrg " [ -gl gn ] [-gr gk] " 91a8fdb4bcSmrg "[ -g0 set ] [ -g1 set ] " 92a8fdb4bcSmrg "[ -g2 set ] [ -g3 set ]\n" 93a8fdb4bcSmrg " [ -encoding encoding ] " 94a8fdb4bcSmrg "[ +oss ] [ +ols ] [ +osl ] [ +ot ]\n" 95a8fdb4bcSmrg " [ -kgl gn ] [-kgr gk] " 96a8fdb4bcSmrg "[ -kg0 set ] [ -kg1 set ] " 97a8fdb4bcSmrg "[ -kg2 set ] [ -kg3 set ]\n" 98a8fdb4bcSmrg " [ -k7 ] [ +kss ] [ +kssgr ] [ -kls ]\n" 99a8fdb4bcSmrg " [ -c ] [ -x ] [ -ilog filename ] [ -olog filename ] [ -- ]\n" 100a8fdb4bcSmrg " [ program [ args ] ]\n"); 101a8fdb4bcSmrg 102a8fdb4bcSmrg} 103a8fdb4bcSmrg 104a8fdb4bcSmrg 105a8fdb4bcSmrgstatic int 106a8fdb4bcSmrgparseOptions(int argc, char **argv) 107a8fdb4bcSmrg{ 108a8fdb4bcSmrg int i = 1; 109a8fdb4bcSmrg while(i < argc) { 110a8fdb4bcSmrg if(argv[i][0] != '-' && argv[i][0] != '+') { 111a8fdb4bcSmrg break; 112a8fdb4bcSmrg } else if(!strcmp(argv[i], "--")) { 113a8fdb4bcSmrg i++; 114a8fdb4bcSmrg break; 115a8fdb4bcSmrg } else if(!strcmp(argv[i], "-v")) { 116a8fdb4bcSmrg verbose++; 117a8fdb4bcSmrg i++; 118a8fdb4bcSmrg } else if(!strcmp(argv[i], "-h")) { 119a8fdb4bcSmrg help(); 120a8fdb4bcSmrg exit(0); 121a8fdb4bcSmrg } else if(!strcmp(argv[i], "-list")) { 122a8fdb4bcSmrg reportCharsets(); 123a8fdb4bcSmrg exit(0); 124a8fdb4bcSmrg } else if(!strcmp(argv[i], "+oss")) { 125a8fdb4bcSmrg outputState->outputFlags &= ~OF_SS; 126a8fdb4bcSmrg i++; 127a8fdb4bcSmrg } else if(!strcmp(argv[i], "+ols")) { 128a8fdb4bcSmrg outputState->outputFlags &= ~OF_LS; 129a8fdb4bcSmrg i++; 130a8fdb4bcSmrg } else if(!strcmp(argv[i], "+osl")) { 131a8fdb4bcSmrg outputState->outputFlags &= ~OF_SELECT; 132a8fdb4bcSmrg i++; 133a8fdb4bcSmrg } else if(!strcmp(argv[i], "+ot")) { 134a8fdb4bcSmrg outputState->outputFlags = OF_PASSTHRU; 135a8fdb4bcSmrg i++; 136a8fdb4bcSmrg } else if(!strcmp(argv[i], "-k7")) { 137a8fdb4bcSmrg inputState->inputFlags &= ~IF_EIGHTBIT; 138a8fdb4bcSmrg i++; 139a8fdb4bcSmrg } else if(!strcmp(argv[i], "+kss")) { 140a8fdb4bcSmrg inputState->inputFlags &= ~IF_SS; 141a8fdb4bcSmrg i++; 142a8fdb4bcSmrg } else if(!strcmp(argv[1], "+kssgr")) { 143a8fdb4bcSmrg inputState->inputFlags &= ~IF_SSGR; 144a8fdb4bcSmrg i++; 145a8fdb4bcSmrg } else if(!strcmp(argv[i], "-kls")) { 146a8fdb4bcSmrg inputState->inputFlags |= IF_LS; 147a8fdb4bcSmrg i++; 148a8fdb4bcSmrg } else if(!strcmp(argv[i], "-g0")) { 149a8fdb4bcSmrg if(i + 1 >= argc) 150a8fdb4bcSmrg FatalError("-g0 requires an argument\n"); 151a8fdb4bcSmrg G0(outputState) = getCharsetByName(argv[i + 1]); 152a8fdb4bcSmrg i += 2; 153a8fdb4bcSmrg } else if(!strcmp(argv[i], "-g1")) { 154a8fdb4bcSmrg if(i + 1 >= argc) 155a8fdb4bcSmrg FatalError("-g1 requires an argument\n"); 156a8fdb4bcSmrg G1(outputState) = getCharsetByName(argv[i + 1]); 157a8fdb4bcSmrg i += 2; 158a8fdb4bcSmrg } else if(!strcmp(argv[i], "-g2")) { 159a8fdb4bcSmrg if(i + 1 >= argc) 160a8fdb4bcSmrg FatalError("-g2 requires an argument\n"); 161a8fdb4bcSmrg G2(outputState) = getCharsetByName(argv[i + 1]); 162a8fdb4bcSmrg i += 2; 163a8fdb4bcSmrg } else if(!strcmp(argv[i], "-g3")) { 164a8fdb4bcSmrg if(i + 1 >= argc) 165a8fdb4bcSmrg FatalError("-g3 requires an argument\n"); 166a8fdb4bcSmrg G3(outputState) = getCharsetByName(argv[i + 1]); 167a8fdb4bcSmrg 168a8fdb4bcSmrg i += 2; 169a8fdb4bcSmrg } else if(!strcmp(argv[i], "-gl")) { 170a8fdb4bcSmrg int j; 171a8fdb4bcSmrg if(i + 1 >= argc) 172a8fdb4bcSmrg FatalError("-gl requires an argument\n"); 173a8fdb4bcSmrg if(strlen(argv[i + 1]) != 2 || 174a8fdb4bcSmrg argv[i + 1][0] != 'g') 175a8fdb4bcSmrg j = -1; 176a8fdb4bcSmrg else 177a8fdb4bcSmrg j = argv[i + 1][1] - '0'; 178a8fdb4bcSmrg if(j < 0 || j > 3) 179a8fdb4bcSmrg FatalError("The argument of -gl " 180a8fdb4bcSmrg "should be one of g0 through g3,\n" 181a8fdb4bcSmrg "not %s\n", argv[i + 1]); 182a8fdb4bcSmrg else 183a8fdb4bcSmrg outputState->glp = &outputState->g[j]; 184a8fdb4bcSmrg i += 2; 185a8fdb4bcSmrg } else if(!strcmp(argv[i], "-gr")) { 186a8fdb4bcSmrg int j; 187a8fdb4bcSmrg if(i + 1 >= argc) 188a8fdb4bcSmrg FatalError("-gr requires an argument\n"); 189a8fdb4bcSmrg if(strlen(argv[i + 1]) != 2 || 190a8fdb4bcSmrg argv[i + 1][0] != 'g') 191a8fdb4bcSmrg j = -1; 192a8fdb4bcSmrg else 193a8fdb4bcSmrg j = argv[i + 1][1] - '0'; 194a8fdb4bcSmrg if(j < 0 || j > 3) 195a8fdb4bcSmrg FatalError("The argument of -gl " 196a8fdb4bcSmrg "should be one of g0 through g3,\n" 197a8fdb4bcSmrg "not %s\n", argv[i + 1]); 198a8fdb4bcSmrg else 199a8fdb4bcSmrg outputState->grp = &outputState->g[j]; 200a8fdb4bcSmrg i += 2; 201a8fdb4bcSmrg } else if(!strcmp(argv[i], "-kg0")) { 202a8fdb4bcSmrg if(i + 1 >= argc) 203a8fdb4bcSmrg FatalError("-kg0 requires an argument\n"); 204a8fdb4bcSmrg G0(inputState) = getCharsetByName(argv[i + 1]); 205a8fdb4bcSmrg i += 2; 206a8fdb4bcSmrg } else if(!strcmp(argv[i], "-kg1")) { 207a8fdb4bcSmrg if(i + 1 >= argc) 208a8fdb4bcSmrg FatalError("-kg1 requires an argument\n"); 209a8fdb4bcSmrg G1(inputState) = getCharsetByName(argv[i + 1]); 210a8fdb4bcSmrg i += 2; 211a8fdb4bcSmrg } else if(!strcmp(argv[i], "-kg2")) { 212a8fdb4bcSmrg if(i + 1 >= argc) 213a8fdb4bcSmrg FatalError("-kg2 requires an argument\n"); 214a8fdb4bcSmrg G2(inputState) = getCharsetByName(argv[i + 1]); 215a8fdb4bcSmrg i += 2; 216a8fdb4bcSmrg } else if(!strcmp(argv[i], "-kg3")) { 217a8fdb4bcSmrg if(i + 1 >= argc) 218a8fdb4bcSmrg FatalError("-kg3 requires an argument\n"); 219a8fdb4bcSmrg G3(inputState) = getCharsetByName(argv[i + 1]); 220a8fdb4bcSmrg 221a8fdb4bcSmrg i += 2; 222a8fdb4bcSmrg } else if(!strcmp(argv[i], "-kgl")) { 223a8fdb4bcSmrg int j; 224a8fdb4bcSmrg if(i + 1 >= argc) 225a8fdb4bcSmrg FatalError("-kgl requires an argument\n"); 226a8fdb4bcSmrg if(strlen(argv[i + 1]) != 2 || 227a8fdb4bcSmrg argv[i + 1][0] != 'g') 228a8fdb4bcSmrg j = -1; 229a8fdb4bcSmrg else 230a8fdb4bcSmrg j = argv[i + 1][1] - '0'; 231a8fdb4bcSmrg if(j < 0 || j > 3) 232a8fdb4bcSmrg FatalError("The argument of -kgl " 233a8fdb4bcSmrg "should be one of g0 through g3,\n" 234a8fdb4bcSmrg "not %s\n", argv[i + 1]); 235a8fdb4bcSmrg else 236a8fdb4bcSmrg inputState->glp = &inputState->g[j]; 237a8fdb4bcSmrg i += 2; 238a8fdb4bcSmrg } else if(!strcmp(argv[i], "-kgr")) { 239a8fdb4bcSmrg int j; 240a8fdb4bcSmrg if(i + 1 >= argc) 241a8fdb4bcSmrg FatalError("-kgl requires an argument\n"); 242a8fdb4bcSmrg if(strlen(argv[i + 1]) != 2 || 243a8fdb4bcSmrg argv[i + 1][0] != 'g') 244a8fdb4bcSmrg j = -1; 245a8fdb4bcSmrg else 246a8fdb4bcSmrg j = argv[i + 1][1] - '0'; 247a8fdb4bcSmrg if(j < 0 || j > 3) 248a8fdb4bcSmrg FatalError("The argument of -kgl " 249a8fdb4bcSmrg "should be one of g0 through g3,\n" 250a8fdb4bcSmrg "not %s\n", argv[i + 1]); 251a8fdb4bcSmrg else 252a8fdb4bcSmrg inputState->grp = &inputState->g[j]; 253a8fdb4bcSmrg i += 2; 254a8fdb4bcSmrg } else if(!strcmp(argv[i], "-argv0")) { 255a8fdb4bcSmrg if(i + 1 >= argc) 256a8fdb4bcSmrg FatalError("-argv0 requires an argument\n"); 257a8fdb4bcSmrg child_argv0 = argv[i + 1]; 258a8fdb4bcSmrg i += 2; 259a8fdb4bcSmrg } else if(!strcmp(argv[i], "-x")) { 260a8fdb4bcSmrg exitOnChild = 1; 261a8fdb4bcSmrg i++; 262a8fdb4bcSmrg } else if(!strcmp(argv[i], "-c")) { 263a8fdb4bcSmrg converter = 1; 264a8fdb4bcSmrg i++; 265a8fdb4bcSmrg } else if(!strcmp(argv[i], "-ilog")) { 266a8fdb4bcSmrg if(i + 1 >= argc) 267a8fdb4bcSmrg FatalError("-ilog requires an argument\n"); 268a8fdb4bcSmrg ilog = open(argv[i + 1], O_WRONLY | O_CREAT | O_TRUNC, 0777); 269a8fdb4bcSmrg if(ilog < 0) { 270a8fdb4bcSmrg perror("Couldn't open input log"); 271a8fdb4bcSmrg exit(1); 272a8fdb4bcSmrg } 273a8fdb4bcSmrg i += 2; 274a8fdb4bcSmrg } else if(!strcmp(argv[i], "-olog")) { 275a8fdb4bcSmrg if(i + 1 >= argc) 276a8fdb4bcSmrg FatalError("-olog requires an argument\n"); 277a8fdb4bcSmrg olog = open(argv[i + 1], O_WRONLY | O_CREAT | O_TRUNC, 0777); 278a8fdb4bcSmrg if(olog < 0) { 279a8fdb4bcSmrg perror("Couldn't open output log"); 280a8fdb4bcSmrg exit(1); 281a8fdb4bcSmrg } 282a8fdb4bcSmrg i += 2; 283a8fdb4bcSmrg } else if(!strcmp(argv[i], "-encoding")) { 284a8fdb4bcSmrg int rc; 285a8fdb4bcSmrg if(i + 1 >= argc) 286a8fdb4bcSmrg FatalError("-encoding requires an argument\n"); 287a8fdb4bcSmrg rc = initIso2022(NULL, argv[i + 1], outputState); 288a8fdb4bcSmrg if(rc < 0) 289a8fdb4bcSmrg FatalError("Couldn't init output state\n"); 290a8fdb4bcSmrg i += 2; 291a8fdb4bcSmrg } else { 292a8fdb4bcSmrg FatalError("Unknown option %s\n", argv[i]); 293a8fdb4bcSmrg } 294a8fdb4bcSmrg } 295a8fdb4bcSmrg return i; 296a8fdb4bcSmrg} 297a8fdb4bcSmrg 298a8fdb4bcSmrgstatic int 299a8fdb4bcSmrgparseArgs(int argc, char **argv, char *argv0, 300a8fdb4bcSmrg char **path_return, char ***argv_return) 301a8fdb4bcSmrg{ 302a8fdb4bcSmrg char *path = NULL; 303a8fdb4bcSmrg char **child_argv = NULL; 304a8fdb4bcSmrg 305a8fdb4bcSmrg if(argc <= 0) { 306a8fdb4bcSmrg char *shell; 307a8fdb4bcSmrg shell = getenv("SHELL"); 308a8fdb4bcSmrg if(shell) { 309a8fdb4bcSmrg path = strdup(shell); 310a8fdb4bcSmrg } else { 311a8fdb4bcSmrg path = strdup("/bin/sh"); 312a8fdb4bcSmrg } 313a8fdb4bcSmrg if(!path) 314a8fdb4bcSmrg goto bail; 315a8fdb4bcSmrg child_argv = malloc(2 * sizeof(char*)); 316a8fdb4bcSmrg if(!child_argv) 317a8fdb4bcSmrg goto bail; 318a8fdb4bcSmrg if(argv0) 319a8fdb4bcSmrg child_argv[0] = argv0; 320a8fdb4bcSmrg else 321a8fdb4bcSmrg child_argv[0] = my_basename(path); 322a8fdb4bcSmrg child_argv[1] = NULL; 323a8fdb4bcSmrg } else { 324a8fdb4bcSmrg path = strdup(argv[0]); 325a8fdb4bcSmrg if(!path) 326a8fdb4bcSmrg goto bail; 327a8fdb4bcSmrg child_argv = malloc((argc + 1) * sizeof(char*)); 328a8fdb4bcSmrg if(!child_argv) { 329a8fdb4bcSmrg goto bail; 330a8fdb4bcSmrg } 331a8fdb4bcSmrg if(child_argv0) 332a8fdb4bcSmrg child_argv[0] = argv0; 333a8fdb4bcSmrg else 334a8fdb4bcSmrg child_argv[0] = my_basename(argv[0]); 335a8fdb4bcSmrg memcpy(child_argv + 1, argv + 1, (argc - 1) * sizeof(char*)); 336a8fdb4bcSmrg child_argv[argc] = NULL; 337a8fdb4bcSmrg } 338a8fdb4bcSmrg 339a8fdb4bcSmrg *path_return = path; 340a8fdb4bcSmrg *argv_return = child_argv; 341a8fdb4bcSmrg return 0; 342a8fdb4bcSmrg 343a8fdb4bcSmrg bail: 344a8fdb4bcSmrg if(path) 345a8fdb4bcSmrg free(path); 346a8fdb4bcSmrg if(argv) 347a8fdb4bcSmrg free(argv); 348a8fdb4bcSmrg return -1; 349a8fdb4bcSmrg} 350a8fdb4bcSmrg 351a8fdb4bcSmrg 352a8fdb4bcSmrgint 353a8fdb4bcSmrgmain(int argc, char **argv) 354a8fdb4bcSmrg{ 355a8fdb4bcSmrg int rc; 356a8fdb4bcSmrg int i; 357a8fdb4bcSmrg char *l; 358a8fdb4bcSmrg 359a8fdb4bcSmrg l = setlocale(LC_ALL, ""); 360a8fdb4bcSmrg if(!l) 361a8fdb4bcSmrg ErrorF("Warning: couldn't set locale.\n"); 362a8fdb4bcSmrg 363a8fdb4bcSmrg inputState = allocIso2022(); 364a8fdb4bcSmrg if(!inputState) 365a8fdb4bcSmrg FatalError("Couldn't create input state\n"); 366a8fdb4bcSmrg 367a8fdb4bcSmrg outputState = allocIso2022(); 368a8fdb4bcSmrg if(!outputState) 369a8fdb4bcSmrg FatalError("Couldn't create output state\n"); 370a8fdb4bcSmrg 371a8fdb4bcSmrg if(l) { 372a8fdb4bcSmrg locale_name = setlocale(LC_CTYPE, NULL); 373a8fdb4bcSmrg } else { 374a8fdb4bcSmrg locale_name = getenv("LC_ALL"); 375a8fdb4bcSmrg if(locale_name == NULL) { 376a8fdb4bcSmrg locale_name = getenv("LC_CTYPE"); 377a8fdb4bcSmrg if(locale_name == NULL) { 378a8fdb4bcSmrg locale_name = getenv("LANG"); 379a8fdb4bcSmrg } 380a8fdb4bcSmrg } 381a8fdb4bcSmrg } 382a8fdb4bcSmrg 383a8fdb4bcSmrg if(locale_name == NULL) { 384a8fdb4bcSmrg ErrorF("Couldn't get locale name -- using C\n"); 385a8fdb4bcSmrg locale_name = "C"; 386a8fdb4bcSmrg } 387a8fdb4bcSmrg 388a8fdb4bcSmrg rc = initIso2022(locale_name, NULL, outputState); 389a8fdb4bcSmrg if(rc < 0) 390a8fdb4bcSmrg FatalError("Couldn't init output state\n"); 391a8fdb4bcSmrg 392a8fdb4bcSmrg i = parseOptions(argc, argv); 393a8fdb4bcSmrg if(i < 0) 394a8fdb4bcSmrg FatalError("Couldn't parse options\n"); 395a8fdb4bcSmrg 396a8fdb4bcSmrg rc = mergeIso2022(inputState, outputState); 397a8fdb4bcSmrg if(rc < 0) 398a8fdb4bcSmrg FatalError("Couldn't init input state\n"); 399a8fdb4bcSmrg 400a8fdb4bcSmrg if(converter) 401a8fdb4bcSmrg return convert(0, 1); 402a8fdb4bcSmrg else 403a8fdb4bcSmrg return condom(argc - i, argv + i); 404a8fdb4bcSmrg} 405a8fdb4bcSmrg 406a8fdb4bcSmrgstatic int 407a8fdb4bcSmrgconvert(int ifd, int ofd) 408a8fdb4bcSmrg{ 409a8fdb4bcSmrg int rc, i; 410a8fdb4bcSmrg unsigned char buf[BUFFER_SIZE]; 411a8fdb4bcSmrg 412a8fdb4bcSmrg rc = droppriv(); 413a8fdb4bcSmrg if(rc < 0) { 414a8fdb4bcSmrg perror("Couldn't drop priviledges"); 415a8fdb4bcSmrg exit(1); 416a8fdb4bcSmrg } 417a8fdb4bcSmrg 418a8fdb4bcSmrg while(1) { 419a8fdb4bcSmrg i = read(ifd, buf, BUFFER_SIZE); 420a8fdb4bcSmrg if(i <= 0) { 421a8fdb4bcSmrg if(i < 0) { 422a8fdb4bcSmrg perror("Read error"); 423a8fdb4bcSmrg exit(1); 424a8fdb4bcSmrg } 425a8fdb4bcSmrg break; 426a8fdb4bcSmrg } 427a8fdb4bcSmrg copyOut(outputState, ofd, buf, i); 428a8fdb4bcSmrg } 429a8fdb4bcSmrg return 0; 430a8fdb4bcSmrg} 431a8fdb4bcSmrg 432a8fdb4bcSmrgstatic void 433a8fdb4bcSmrgsigwinchHandler(int sig) 434a8fdb4bcSmrg{ 435a8fdb4bcSmrg sigwinch_queued = 1; 436a8fdb4bcSmrg} 437a8fdb4bcSmrg 438a8fdb4bcSmrgstatic void 439a8fdb4bcSmrgsigchldHandler(int sig) 440a8fdb4bcSmrg{ 441a8fdb4bcSmrg sigchld_queued = 1; 442a8fdb4bcSmrg} 443a8fdb4bcSmrg 444a8fdb4bcSmrgstatic int 445a8fdb4bcSmrgcondom(int argc, char **argv) 446a8fdb4bcSmrg{ 447a8fdb4bcSmrg int pty; 448a8fdb4bcSmrg int pid; 449a8fdb4bcSmrg char *line; 450a8fdb4bcSmrg char *path; 451a8fdb4bcSmrg char **child_argv; 452a8fdb4bcSmrg int rc; 453a8fdb4bcSmrg int val; 454a8fdb4bcSmrg 455a8fdb4bcSmrg rc = parseArgs(argc, argv, child_argv0, 456a8fdb4bcSmrg &path, &child_argv); 457a8fdb4bcSmrg if(rc < 0) 458a8fdb4bcSmrg FatalError("Couldn't parse arguments\n"); 459a8fdb4bcSmrg 460a8fdb4bcSmrg rc = allocatePty(&pty, &line); 461a8fdb4bcSmrg if(rc < 0) { 462a8fdb4bcSmrg perror("Couldn't allocate pty"); 463a8fdb4bcSmrg exit(1); 464a8fdb4bcSmrg } 465a8fdb4bcSmrg 466a8fdb4bcSmrg rc = droppriv(); 467a8fdb4bcSmrg if(rc < 0) { 468a8fdb4bcSmrg perror("Couldn't drop priviledges"); 469a8fdb4bcSmrg exit(1); 470a8fdb4bcSmrg } 471a8fdb4bcSmrg#ifdef SIGWINCH 472a8fdb4bcSmrg installHandler(SIGWINCH, sigwinchHandler); 473a8fdb4bcSmrg#endif 474a8fdb4bcSmrg installHandler(SIGCHLD, sigchldHandler); 475a8fdb4bcSmrg 476a8fdb4bcSmrg rc = copyTermios(0, pty); 477a8fdb4bcSmrg if(rc < 0) 478a8fdb4bcSmrg FatalError("Couldn't copy terminal settings\n"); 479a8fdb4bcSmrg 480a8fdb4bcSmrg rc = setRawTermios(); 481a8fdb4bcSmrg if(rc < 0) 482a8fdb4bcSmrg FatalError("Couldn't set terminal to raw\n"); 483a8fdb4bcSmrg 484a8fdb4bcSmrg val = fcntl(0, F_GETFL, 0); 485a8fdb4bcSmrg if(val >= 0) { 486a8fdb4bcSmrg fcntl(0, F_SETFL, val | O_NONBLOCK); 487a8fdb4bcSmrg } 488a8fdb4bcSmrg val = fcntl(pty, F_GETFL, 0); 489a8fdb4bcSmrg if(val >= 0) { 490a8fdb4bcSmrg fcntl(pty, F_SETFL, val | O_NONBLOCK); 491a8fdb4bcSmrg } 492a8fdb4bcSmrg 493a8fdb4bcSmrg setWindowSize(0, pty); 494a8fdb4bcSmrg 495a8fdb4bcSmrg pid = fork(); 496a8fdb4bcSmrg if(pid < 0) { 497a8fdb4bcSmrg perror("Couldn't fork"); 498a8fdb4bcSmrg exit(1); 499a8fdb4bcSmrg } 500a8fdb4bcSmrg 501a8fdb4bcSmrg if(pid == 0) { 502a8fdb4bcSmrg close(pty); 503a8fdb4bcSmrg#ifdef SIGWINCH 504a8fdb4bcSmrg installHandler(SIGWINCH, SIG_DFL); 505a8fdb4bcSmrg#endif 506a8fdb4bcSmrg installHandler(SIGCHLD, SIG_DFL); 507a8fdb4bcSmrg child(line, path, child_argv); 508a8fdb4bcSmrg } else { 509a8fdb4bcSmrg free(child_argv); 510a8fdb4bcSmrg free(path); 511a8fdb4bcSmrg free(line); 512a8fdb4bcSmrg parent(pid, pty); 513a8fdb4bcSmrg } 514a8fdb4bcSmrg 515a8fdb4bcSmrg return 0; 516a8fdb4bcSmrg} 517a8fdb4bcSmrg 518a8fdb4bcSmrgvoid 519a8fdb4bcSmrgchild(char *line, char *path, char **argv) 520a8fdb4bcSmrg{ 521a8fdb4bcSmrg int tty; 522a8fdb4bcSmrg int pgrp; 523a8fdb4bcSmrg 524a8fdb4bcSmrg close(0); 525a8fdb4bcSmrg close(1); 526a8fdb4bcSmrg close(2); 527a8fdb4bcSmrg 528a8fdb4bcSmrg pgrp = setsid(); 529a8fdb4bcSmrg if(pgrp < 0) { 530a8fdb4bcSmrg kill(getppid(), SIGABRT); 531a8fdb4bcSmrg exit(1); 532a8fdb4bcSmrg } 533a8fdb4bcSmrg 534a8fdb4bcSmrg tty = openTty(line); 535a8fdb4bcSmrg if(tty < 0) { 536a8fdb4bcSmrg kill(getppid(), SIGABRT); 537a8fdb4bcSmrg exit(1); 538a8fdb4bcSmrg } 539a8fdb4bcSmrg 540a8fdb4bcSmrg if(tty != 0) 541a8fdb4bcSmrg dup2(tty, 0); 542a8fdb4bcSmrg if(tty != 1) 543a8fdb4bcSmrg dup2(tty, 1); 544a8fdb4bcSmrg if(tty != 2) 545a8fdb4bcSmrg dup2(tty, 2); 546a8fdb4bcSmrg 547a8fdb4bcSmrg if(tty > 2) 548a8fdb4bcSmrg close(tty); 549a8fdb4bcSmrg 550a8fdb4bcSmrg execvp(path, argv); 551a8fdb4bcSmrg perror("Couldn't exec"); 552a8fdb4bcSmrg exit(1); 553a8fdb4bcSmrg} 554a8fdb4bcSmrg 555a8fdb4bcSmrgvoid 556a8fdb4bcSmrgparent(int pid, int pty) 557a8fdb4bcSmrg{ 558a8fdb4bcSmrg unsigned char buf[BUFFER_SIZE]; 559a8fdb4bcSmrg int i; 560a8fdb4bcSmrg int rc; 561a8fdb4bcSmrg 562a8fdb4bcSmrg if(verbose) { 563a8fdb4bcSmrg reportIso2022(outputState); 564a8fdb4bcSmrg } 565a8fdb4bcSmrg 566a8fdb4bcSmrg for(;;) { 567a8fdb4bcSmrg rc = waitForInput(0, pty); 568a8fdb4bcSmrg 569a8fdb4bcSmrg if(sigwinch_queued) { 570a8fdb4bcSmrg sigwinch_queued = 0; 571a8fdb4bcSmrg setWindowSize(0, pty); 572a8fdb4bcSmrg } 573a8fdb4bcSmrg 574a8fdb4bcSmrg if(sigchld_queued && exitOnChild) 575a8fdb4bcSmrg break; 576a8fdb4bcSmrg 577a8fdb4bcSmrg if(rc > 0) { 578a8fdb4bcSmrg if(rc & 2) { 579a8fdb4bcSmrg i = read(pty, buf, BUFFER_SIZE); 580a8fdb4bcSmrg if((i == 0) || ((i < 0) && (errno != EAGAIN))) 581a8fdb4bcSmrg break; 582a8fdb4bcSmrg if(i > 0) 583a8fdb4bcSmrg copyOut(outputState, 0, buf, i); 584a8fdb4bcSmrg } 585a8fdb4bcSmrg if(rc & 1) { 586a8fdb4bcSmrg i = read(0, buf, BUFFER_SIZE); 587a8fdb4bcSmrg if((i == 0) || ((i < 0) && (errno != EAGAIN))) 588a8fdb4bcSmrg break; 589a8fdb4bcSmrg if(i > 0) 590a8fdb4bcSmrg copyIn(inputState, pty, buf, i); 591a8fdb4bcSmrg } 592a8fdb4bcSmrg } 593a8fdb4bcSmrg } 594a8fdb4bcSmrg 595a8fdb4bcSmrg restoreTermios(); 596a8fdb4bcSmrg} 597