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*/ 2277683534Smrg 2377683534Smrg#ifdef HAVE_CONFIG_H 2477683534Smrg# include "config.h" 2577683534Smrg#endif 26a8fdb4bcSmrg 27a8fdb4bcSmrg#include <stdio.h> 28a8fdb4bcSmrg#include <stdlib.h> 29a8fdb4bcSmrg#include <string.h> 30a8fdb4bcSmrg#include <locale.h> 31a8fdb4bcSmrg#include <sys/types.h> 32a8fdb4bcSmrg#include <fcntl.h> 33a8fdb4bcSmrg#include <unistd.h> 34a8fdb4bcSmrg#include <errno.h> 35a8fdb4bcSmrg#include <assert.h> 36a8fdb4bcSmrg#include <stdarg.h> 37a8fdb4bcSmrg#include <sys/ioctl.h> 38a8fdb4bcSmrg#include <signal.h> 39a8fdb4bcSmrg 40a8fdb4bcSmrg#include "luit.h" 41a8fdb4bcSmrg#include "sys.h" 42a8fdb4bcSmrg#include "other.h" 4377683534Smrg#include "parser.h" 44a8fdb4bcSmrg#include "iso2022.h" 45a8fdb4bcSmrg 4677683534Smrgstatic int pipe_option = 0; 4777683534Smrgstatic int p2c_waitpipe[2]; 4877683534Smrgstatic int c2p_waitpipe[2]; 4977683534Smrg 50a8fdb4bcSmrgstatic Iso2022Ptr inputState = NULL, outputState = NULL; 51a8fdb4bcSmrg 52a8fdb4bcSmrgstatic char *child_argv0 = NULL; 5377683534Smrgstatic const char *locale_name = NULL; 5477683534Smrgstatic int exitOnChild = 0; 5577683534Smrgstatic int converter = 0; 5677683534Smrg 5777683534Smrgconst char *locale_alias = LOCALE_ALIAS_FILE; 5877683534Smrg 59a8fdb4bcSmrgint ilog = -1; 60a8fdb4bcSmrgint olog = -1; 61a8fdb4bcSmrgint verbose = 0; 62a8fdb4bcSmrg 63dbe7da2eSmrgstatic volatile int sigwinch_queued = 0; 64dbe7da2eSmrgstatic volatile int sigchld_queued = 0; 65a8fdb4bcSmrg 66a8fdb4bcSmrgstatic int convert(int, int); 6777683534Smrgstatic int condom(int, char **); 68a8fdb4bcSmrg 694ed31819Smrgvoid 7077683534SmrgErrorF(const char *f,...) 71a8fdb4bcSmrg{ 72a8fdb4bcSmrg va_list args; 73a8fdb4bcSmrg va_start(args, f); 74a8fdb4bcSmrg vfprintf(stderr, f, args); 75a8fdb4bcSmrg va_end(args); 76a8fdb4bcSmrg} 77a8fdb4bcSmrg 784ed31819Smrgvoid 7977683534SmrgFatalError(const char *f,...) 80a8fdb4bcSmrg{ 81a8fdb4bcSmrg va_list args; 82a8fdb4bcSmrg va_start(args, f); 83a8fdb4bcSmrg vfprintf(stderr, f, args); 84a8fdb4bcSmrg va_end(args); 8577683534Smrg ExitProgram(1); 86a8fdb4bcSmrg} 87a8fdb4bcSmrg 88a8fdb4bcSmrgstatic void 89a8fdb4bcSmrghelp(void) 90a8fdb4bcSmrg{ 9177683534Smrg fprintf(stderr, 9277683534Smrg "luit\n" 9377683534Smrg " [ -V ] [ -h ] [ -list ] [ -v ] [ -argv0 name ]\n" 9477683534Smrg " [ -gl gn ] [-gr gk] " 9577683534Smrg "[ -g0 set ] [ -g1 set ] " 9677683534Smrg "[ -g2 set ] [ -g3 set ]\n" 9777683534Smrg " [ -encoding encoding ] " 9877683534Smrg "[ +oss ] [ +ols ] [ +osl ] [ +ot ]\n" 9977683534Smrg " [ -kgl gn ] [-kgr gk] " 10077683534Smrg "[ -kg0 set ] [ -kg1 set ] " 10177683534Smrg "[ -kg2 set ] [ -kg3 set ]\n" 10277683534Smrg " [ -k7 ] [ +kss ] [ +kssgr ] [ -kls ]\n" 10377683534Smrg " [ -c ] " 10477683534Smrg "[ -p ] " 10577683534Smrg "[ -x ] " 10677683534Smrg "[ -ilog filename ] " 10777683534Smrg "[ -olog filename ] " 10877683534Smrg "[ -alias filename ] " 10977683534Smrg "[ -- ]\n" 11077683534Smrg " [ program [ args ] ]\n"); 111a8fdb4bcSmrg} 112a8fdb4bcSmrg 113a8fdb4bcSmrgstatic int 114a8fdb4bcSmrgparseOptions(int argc, char **argv) 115a8fdb4bcSmrg{ 116a8fdb4bcSmrg int i = 1; 11777683534Smrg while (i < argc) { 11877683534Smrg if (argv[i][0] != '-' && argv[i][0] != '+') { 11977683534Smrg break; 12077683534Smrg } else if (!strcmp(argv[i], "--")) { 12177683534Smrg i++; 12277683534Smrg break; 12377683534Smrg } else if (!strcmp(argv[i], "-v")) { 12477683534Smrg verbose++; 12577683534Smrg i++; 12677683534Smrg } else if (!strcmp(argv[i], "-V")) { 12777683534Smrg printf("%s - %s\n", argv[0], VERSION); 12877683534Smrg ExitProgram(0); 12977683534Smrg } else if (!strcmp(argv[i], "-h")) { 13077683534Smrg help(); 13177683534Smrg ExitProgram(0); 13277683534Smrg } else if (!strcmp(argv[i], "-list")) { 13377683534Smrg reportCharsets(); 13477683534Smrg ExitProgram(0); 13577683534Smrg } else if (!strcmp(argv[i], "+oss")) { 13677683534Smrg outputState->outputFlags &= ~OF_SS; 13777683534Smrg i++; 13877683534Smrg } else if (!strcmp(argv[i], "+ols")) { 13977683534Smrg outputState->outputFlags &= ~OF_LS; 14077683534Smrg i++; 14177683534Smrg } else if (!strcmp(argv[i], "+osl")) { 14277683534Smrg outputState->outputFlags &= ~OF_SELECT; 14377683534Smrg i++; 14477683534Smrg } else if (!strcmp(argv[i], "+ot")) { 14577683534Smrg outputState->outputFlags = OF_PASSTHRU; 14677683534Smrg i++; 14777683534Smrg } else if (!strcmp(argv[i], "-k7")) { 14877683534Smrg inputState->inputFlags &= ~IF_EIGHTBIT; 14977683534Smrg i++; 15077683534Smrg } else if (!strcmp(argv[i], "+kss")) { 15177683534Smrg inputState->inputFlags &= ~IF_SS; 15277683534Smrg i++; 15377683534Smrg } else if (!strcmp(argv[1], "+kssgr")) { 15477683534Smrg inputState->inputFlags &= ~IF_SSGR; 15577683534Smrg i++; 15677683534Smrg } else if (!strcmp(argv[i], "-kls")) { 15777683534Smrg inputState->inputFlags |= IF_LS; 15877683534Smrg i++; 15977683534Smrg } else if (!strcmp(argv[i], "-g0")) { 16077683534Smrg if (i + 1 >= argc) 16177683534Smrg FatalError("-g0 requires an argument\n"); 16277683534Smrg G0(outputState) = getCharsetByName(argv[i + 1]); 16377683534Smrg i += 2; 16477683534Smrg } else if (!strcmp(argv[i], "-g1")) { 16577683534Smrg if (i + 1 >= argc) 16677683534Smrg FatalError("-g1 requires an argument\n"); 16777683534Smrg G1(outputState) = getCharsetByName(argv[i + 1]); 16877683534Smrg i += 2; 16977683534Smrg } else if (!strcmp(argv[i], "-g2")) { 17077683534Smrg if (i + 1 >= argc) 17177683534Smrg FatalError("-g2 requires an argument\n"); 17277683534Smrg G2(outputState) = getCharsetByName(argv[i + 1]); 17377683534Smrg i += 2; 17477683534Smrg } else if (!strcmp(argv[i], "-g3")) { 17577683534Smrg if (i + 1 >= argc) 17677683534Smrg FatalError("-g3 requires an argument\n"); 17777683534Smrg G3(outputState) = getCharsetByName(argv[i + 1]); 17877683534Smrg 17977683534Smrg i += 2; 18077683534Smrg } else if (!strcmp(argv[i], "-gl")) { 18177683534Smrg int j; 18277683534Smrg if (i + 1 >= argc) 18377683534Smrg FatalError("-gl requires an argument\n"); 18477683534Smrg if (strlen(argv[i + 1]) != 2 || 18577683534Smrg argv[i + 1][0] != 'g') 18677683534Smrg j = -1; 18777683534Smrg else 18877683534Smrg j = argv[i + 1][1] - '0'; 18977683534Smrg if (j < 0 || j > 3) 19077683534Smrg FatalError("The argument of -gl " 19177683534Smrg "should be one of g0 through g3,\n" 19277683534Smrg "not %s\n", argv[i + 1]); 19377683534Smrg else 19477683534Smrg outputState->glp = &outputState->g[j]; 19577683534Smrg i += 2; 19677683534Smrg } else if (!strcmp(argv[i], "-gr")) { 19777683534Smrg int j; 19877683534Smrg if (i + 1 >= argc) 19977683534Smrg FatalError("-gr requires an argument\n"); 20077683534Smrg if (strlen(argv[i + 1]) != 2 || 20177683534Smrg argv[i + 1][0] != 'g') 20277683534Smrg j = -1; 20377683534Smrg else 20477683534Smrg j = argv[i + 1][1] - '0'; 20577683534Smrg if (j < 0 || j > 3) 20677683534Smrg FatalError("The argument of -gl " 20777683534Smrg "should be one of g0 through g3,\n" 20877683534Smrg "not %s\n", argv[i + 1]); 20977683534Smrg else 21077683534Smrg outputState->grp = &outputState->g[j]; 21177683534Smrg i += 2; 21277683534Smrg } else if (!strcmp(argv[i], "-kg0")) { 21377683534Smrg if (i + 1 >= argc) 21477683534Smrg FatalError("-kg0 requires an argument\n"); 21577683534Smrg G0(inputState) = getCharsetByName(argv[i + 1]); 21677683534Smrg i += 2; 21777683534Smrg } else if (!strcmp(argv[i], "-kg1")) { 21877683534Smrg if (i + 1 >= argc) 21977683534Smrg FatalError("-kg1 requires an argument\n"); 22077683534Smrg G1(inputState) = getCharsetByName(argv[i + 1]); 22177683534Smrg i += 2; 22277683534Smrg } else if (!strcmp(argv[i], "-kg2")) { 22377683534Smrg if (i + 1 >= argc) 22477683534Smrg FatalError("-kg2 requires an argument\n"); 22577683534Smrg G2(inputState) = getCharsetByName(argv[i + 1]); 22677683534Smrg i += 2; 22777683534Smrg } else if (!strcmp(argv[i], "-kg3")) { 22877683534Smrg if (i + 1 >= argc) 22977683534Smrg FatalError("-kg3 requires an argument\n"); 23077683534Smrg G3(inputState) = getCharsetByName(argv[i + 1]); 23177683534Smrg 23277683534Smrg i += 2; 23377683534Smrg } else if (!strcmp(argv[i], "-kgl")) { 23477683534Smrg int j; 23577683534Smrg if (i + 1 >= argc) 23677683534Smrg FatalError("-kgl requires an argument\n"); 23777683534Smrg if (strlen(argv[i + 1]) != 2 || 23877683534Smrg argv[i + 1][0] != 'g') 23977683534Smrg j = -1; 24077683534Smrg else 24177683534Smrg j = argv[i + 1][1] - '0'; 24277683534Smrg if (j < 0 || j > 3) 24377683534Smrg FatalError("The argument of -kgl " 24477683534Smrg "should be one of g0 through g3,\n" 24577683534Smrg "not %s\n", argv[i + 1]); 24677683534Smrg else 24777683534Smrg inputState->glp = &inputState->g[j]; 24877683534Smrg i += 2; 24977683534Smrg } else if (!strcmp(argv[i], "-kgr")) { 25077683534Smrg int j; 25177683534Smrg if (i + 1 >= argc) 25277683534Smrg FatalError("-kgl requires an argument\n"); 25377683534Smrg if (strlen(argv[i + 1]) != 2 || 25477683534Smrg argv[i + 1][0] != 'g') 25577683534Smrg j = -1; 25677683534Smrg else 25777683534Smrg j = argv[i + 1][1] - '0'; 25877683534Smrg if (j < 0 || j > 3) 25977683534Smrg FatalError("The argument of -kgl " 26077683534Smrg "should be one of g0 through g3,\n" 26177683534Smrg "not %s\n", argv[i + 1]); 26277683534Smrg else 26377683534Smrg inputState->grp = &inputState->g[j]; 26477683534Smrg i += 2; 26577683534Smrg } else if (!strcmp(argv[i], "-argv0")) { 26677683534Smrg if (i + 1 >= argc) 26777683534Smrg FatalError("-argv0 requires an argument\n"); 26877683534Smrg child_argv0 = argv[i + 1]; 26977683534Smrg i += 2; 27077683534Smrg } else if (!strcmp(argv[i], "-x")) { 27177683534Smrg exitOnChild = 1; 27277683534Smrg i++; 27377683534Smrg } else if (!strcmp(argv[i], "-c")) { 27477683534Smrg converter = 1; 27577683534Smrg i++; 27677683534Smrg } else if (!strcmp(argv[i], "-ilog")) { 27777683534Smrg if (i + 1 >= argc) 27877683534Smrg FatalError("-ilog requires an argument\n"); 27977683534Smrg ilog = open(argv[i + 1], O_WRONLY | O_CREAT | O_TRUNC, 0777); 28077683534Smrg if (ilog < 0) { 28177683534Smrg perror("Couldn't open input log"); 28277683534Smrg ExitProgram(1); 28377683534Smrg } 28477683534Smrg i += 2; 28577683534Smrg } else if (!strcmp(argv[i], "-olog")) { 28677683534Smrg if (i + 1 >= argc) 28777683534Smrg FatalError("-olog requires an argument\n"); 28877683534Smrg olog = open(argv[i + 1], O_WRONLY | O_CREAT | O_TRUNC, 0777); 28977683534Smrg if (olog < 0) { 29077683534Smrg perror("Couldn't open output log"); 29177683534Smrg ExitProgram(1); 29277683534Smrg } 29377683534Smrg i += 2; 29477683534Smrg } else if (!strcmp(argv[i], "-alias")) { 29577683534Smrg if (i + 1 >= argc) 29677683534Smrg FatalError("-alias requires an argument\n"); 29777683534Smrg locale_alias = argv[i + 1]; 29877683534Smrg i += 2; 29977683534Smrg } else if (!strcmp(argv[i], "-encoding")) { 30077683534Smrg if (i + 1 >= argc) 30177683534Smrg FatalError("-encoding requires an argument\n"); 30277683534Smrg locale_name = argv[i + 1]; 30377683534Smrg i += 2; 30477683534Smrg } else if (!strcmp(argv[i], "-p")) { 30577683534Smrg pipe_option = 1; 30677683534Smrg i += 1; 30777683534Smrg } else { 30877683534Smrg FatalError("Unknown option %s\n", argv[i]); 30977683534Smrg } 310a8fdb4bcSmrg } 311a8fdb4bcSmrg return i; 312a8fdb4bcSmrg} 313a8fdb4bcSmrg 314a8fdb4bcSmrgstatic int 31577683534SmrgparseArgs(int argc, char **argv, 31677683534Smrg char *argv0, 31777683534Smrg char **path_return, 31877683534Smrg char ***argv_return) 319a8fdb4bcSmrg{ 320a8fdb4bcSmrg char *path = NULL; 321a8fdb4bcSmrg char **child_argv = NULL; 322a8fdb4bcSmrg 32377683534Smrg if (argc <= 0) { 32477683534Smrg char *shell; 32577683534Smrg shell = getenv("SHELL"); 32677683534Smrg if (shell) { 32777683534Smrg path = strmalloc(shell); 32877683534Smrg if (!path) 32977683534Smrg goto bail; 33077683534Smrg } else { 33177683534Smrg path = strmalloc("/bin/sh"); 33277683534Smrg if (!path) 33377683534Smrg goto bail; 33477683534Smrg } 33577683534Smrg child_argv = malloc(2 * sizeof(char *)); 33677683534Smrg if (!child_argv) 33777683534Smrg goto bail; 33877683534Smrg if (argv0) 33977683534Smrg child_argv[0] = argv0; 34077683534Smrg else 34177683534Smrg child_argv[0] = my_basename(path); 34277683534Smrg child_argv[1] = NULL; 343a8fdb4bcSmrg } else { 34477683534Smrg path = strmalloc(argv[0]); 34577683534Smrg if (!path) 34677683534Smrg goto bail; 34777683534Smrg child_argv = malloc((unsigned) (argc + 1) * sizeof(char *)); 34877683534Smrg if (!child_argv) { 34977683534Smrg goto bail; 35077683534Smrg } 35177683534Smrg if (child_argv0) 35277683534Smrg child_argv[0] = argv0; 35377683534Smrg else 35477683534Smrg child_argv[0] = my_basename(argv[0]); 35577683534Smrg memcpy(child_argv + 1, argv + 1, (unsigned) (argc - 1) * sizeof(char *)); 35677683534Smrg child_argv[argc] = NULL; 357a8fdb4bcSmrg } 358a8fdb4bcSmrg 359a8fdb4bcSmrg *path_return = path; 360a8fdb4bcSmrg *argv_return = child_argv; 361a8fdb4bcSmrg return 0; 362a8fdb4bcSmrg 363a8fdb4bcSmrg bail: 36477683534Smrg if (path) 36577683534Smrg free(path); 366893028efSmrg if (child_argv) 367893028efSmrg free(child_argv); 368a8fdb4bcSmrg return -1; 369a8fdb4bcSmrg} 370a8fdb4bcSmrg 371a8fdb4bcSmrgint 372a8fdb4bcSmrgmain(int argc, char **argv) 373a8fdb4bcSmrg{ 374a8fdb4bcSmrg int rc; 375a8fdb4bcSmrg int i; 376a8fdb4bcSmrg char *l; 377a8fdb4bcSmrg 37877683534Smrg#ifdef HAVE_PUTENV 37977683534Smrg if ((l = strmalloc("NCURSES_NO_UTF8_ACS=1")) != 0) 38077683534Smrg putenv(l); 38177683534Smrg#endif 38277683534Smrg 383a8fdb4bcSmrg l = setlocale(LC_ALL, ""); 38477683534Smrg if (!l) 38577683534Smrg ErrorF("Warning: couldn't set locale.\n"); 386a8fdb4bcSmrg 387a8fdb4bcSmrg inputState = allocIso2022(); 38877683534Smrg if (!inputState) 38977683534Smrg FatalError("Couldn't create input state\n"); 39077683534Smrg 391a8fdb4bcSmrg outputState = allocIso2022(); 39277683534Smrg if (!outputState) 39377683534Smrg FatalError("Couldn't create output state\n"); 39477683534Smrg 39577683534Smrg if (l) { 39677683534Smrg locale_name = setlocale(LC_CTYPE, NULL); 397a8fdb4bcSmrg } else { 39877683534Smrg locale_name = getenv("LC_ALL"); 39977683534Smrg if (locale_name == NULL) { 40077683534Smrg locale_name = getenv("LC_CTYPE"); 40177683534Smrg if (locale_name == NULL) { 40277683534Smrg locale_name = getenv("LANG"); 40377683534Smrg } 40477683534Smrg } 405a8fdb4bcSmrg } 406a8fdb4bcSmrg 40777683534Smrg if (locale_name == NULL) { 40877683534Smrg ErrorF("Couldn't get locale name -- using C\n"); 40977683534Smrg locale_name = "C"; 410a8fdb4bcSmrg } 411a8fdb4bcSmrg 412a8fdb4bcSmrg i = parseOptions(argc, argv); 41377683534Smrg if (i < 0) 41477683534Smrg FatalError("Couldn't parse options\n"); 41577683534Smrg 41677683534Smrg rc = initIso2022(locale_name, NULL, outputState); 41777683534Smrg if (rc < 0) 41877683534Smrg FatalError("Couldn't init output state\n"); 419a8fdb4bcSmrg 420a8fdb4bcSmrg rc = mergeIso2022(inputState, outputState); 42177683534Smrg if (rc < 0) 42277683534Smrg FatalError("Couldn't init input state\n"); 423a8fdb4bcSmrg 42477683534Smrg if (converter) 42577683534Smrg rc = convert(0, 1); 426a8fdb4bcSmrg else 42777683534Smrg rc = condom(argc - i, argv + i); 42877683534Smrg 42977683534Smrg#ifdef NO_LEAKS 43077683534Smrg ExitProgram(rc); 43177683534Smrg#endif 43277683534Smrg return rc; 433a8fdb4bcSmrg} 434a8fdb4bcSmrg 435a8fdb4bcSmrgstatic int 436a8fdb4bcSmrgconvert(int ifd, int ofd) 437a8fdb4bcSmrg{ 438a8fdb4bcSmrg int rc, i; 439a8fdb4bcSmrg unsigned char buf[BUFFER_SIZE]; 440a8fdb4bcSmrg 441a8fdb4bcSmrg rc = droppriv(); 44277683534Smrg if (rc < 0) { 44377683534Smrg perror("Couldn't drop privileges"); 44477683534Smrg ExitProgram(1); 445a8fdb4bcSmrg } 446a8fdb4bcSmrg 44777683534Smrg while (1) { 44877683534Smrg i = (int) read(ifd, buf, (size_t) BUFFER_SIZE); 44977683534Smrg if (i <= 0) { 45077683534Smrg if (i < 0) { 45177683534Smrg perror("Read error"); 45277683534Smrg ExitProgram(1); 45377683534Smrg } 45477683534Smrg break; 45577683534Smrg } 45677683534Smrg copyOut(outputState, ofd, buf, (unsigned) i); 457a8fdb4bcSmrg } 458a8fdb4bcSmrg return 0; 459a8fdb4bcSmrg} 46077683534Smrg 46177683534Smrg#ifdef SIGWINCH 462a8fdb4bcSmrgstatic void 46377683534SmrgsigwinchHandler(int sig GCC_UNUSED) 464a8fdb4bcSmrg{ 465a8fdb4bcSmrg sigwinch_queued = 1; 466a8fdb4bcSmrg} 46777683534Smrg#endif 468a8fdb4bcSmrg 469a8fdb4bcSmrgstatic void 47077683534SmrgsigchldHandler(int sig GCC_UNUSED) 471a8fdb4bcSmrg{ 472a8fdb4bcSmrg sigchld_queued = 1; 473a8fdb4bcSmrg} 474a8fdb4bcSmrg 475a8fdb4bcSmrgstatic int 47677683534Smrgsetup_io(int pty) 477a8fdb4bcSmrg{ 478a8fdb4bcSmrg int rc; 479a8fdb4bcSmrg int val; 480a8fdb4bcSmrg 481a8fdb4bcSmrg#ifdef SIGWINCH 482a8fdb4bcSmrg installHandler(SIGWINCH, sigwinchHandler); 483a8fdb4bcSmrg#endif 484a8fdb4bcSmrg installHandler(SIGCHLD, sigchldHandler); 485a8fdb4bcSmrg 486a8fdb4bcSmrg rc = copyTermios(0, pty); 48777683534Smrg if (rc < 0) 48877683534Smrg FatalError("Couldn't copy terminal settings\n"); 489a8fdb4bcSmrg 490a8fdb4bcSmrg rc = setRawTermios(); 49177683534Smrg if (rc < 0) 49277683534Smrg FatalError("Couldn't set terminal to raw\n"); 493a8fdb4bcSmrg 494a8fdb4bcSmrg val = fcntl(0, F_GETFL, 0); 49577683534Smrg if (val >= 0) { 49677683534Smrg fcntl(0, F_SETFL, val | O_NONBLOCK); 497a8fdb4bcSmrg } 498a8fdb4bcSmrg val = fcntl(pty, F_GETFL, 0); 49977683534Smrg if (val >= 0) { 50077683534Smrg fcntl(pty, F_SETFL, val | O_NONBLOCK); 501a8fdb4bcSmrg } 502a8fdb4bcSmrg 503a8fdb4bcSmrg setWindowSize(0, pty); 504a8fdb4bcSmrg 50577683534Smrg return rc; 50677683534Smrg} 50777683534Smrg 50877683534Smrgstatic void 50977683534Smrgcleanup_io(int pty) 51077683534Smrg{ 51177683534Smrg int val; 512a8fdb4bcSmrg 513a8fdb4bcSmrg#ifdef SIGWINCH 51477683534Smrg installHandler(SIGWINCH, SIG_DFL); 515a8fdb4bcSmrg#endif 51677683534Smrg installHandler(SIGCHLD, SIG_DFL); 51777683534Smrg 51877683534Smrg val = fcntl(0, F_GETFL, 0); 51977683534Smrg if (val >= 0) { 52077683534Smrg fcntl(0, F_SETFL, val & ~O_NONBLOCK); 52177683534Smrg } 52277683534Smrg val = fcntl(pty, F_GETFL, 0); 52377683534Smrg if (val >= 0) { 52477683534Smrg fcntl(pty, F_SETFL, val & ~O_NONBLOCK); 52577683534Smrg } 52677683534Smrg} 52777683534Smrg 52877683534Smrgstatic void 52977683534Smrgclose_waitpipe(int which) 53077683534Smrg{ 53177683534Smrg close(p2c_waitpipe[which]); 53277683534Smrg close(c2p_waitpipe[!which]); 53377683534Smrg} 53477683534Smrg 53577683534Smrgstatic void 53677683534Smrgwrite_waitpipe(int fds[2]) 53777683534Smrg{ 53877683534Smrg IGNORE_RC(write(fds[1], "1", (size_t) 1)); 53977683534Smrg} 54077683534Smrg 54177683534Smrgstatic void 54277683534Smrgread_waitpipe(int fds[2]) 54377683534Smrg{ 54477683534Smrg char tmp[10]; 54577683534Smrg IGNORE_RC(read(fds[0], tmp, (size_t) 1)); 54677683534Smrg} 54777683534Smrg 54877683534Smrgstatic int 54977683534Smrgcondom(int argc, char **argv) 55077683534Smrg{ 55177683534Smrg int pty; 55277683534Smrg int pid; 55377683534Smrg char *line; 55477683534Smrg char *path = 0; 55577683534Smrg char **child_argv = 0; 55677683534Smrg int rc; 55777683534Smrg 55877683534Smrg rc = parseArgs(argc, argv, child_argv0, 55977683534Smrg &path, &child_argv); 56077683534Smrg if (rc < 0) 56177683534Smrg FatalError("Couldn't parse arguments\n"); 56277683534Smrg 56377683534Smrg rc = allocatePty(&pty, &line); 56477683534Smrg if (rc < 0) { 56577683534Smrg perror("Couldn't allocate pty"); 56677683534Smrg ExitProgram(1); 56777683534Smrg } 56877683534Smrg 56977683534Smrg rc = droppriv(); 57077683534Smrg if (rc < 0) { 57177683534Smrg perror("Couldn't drop privileges"); 57277683534Smrg ExitProgram(1); 57377683534Smrg } 57477683534Smrg 57577683534Smrg if (pipe_option) { 57677683534Smrg IGNORE_RC(pipe(p2c_waitpipe)); 57777683534Smrg IGNORE_RC(pipe(c2p_waitpipe)); 57877683534Smrg } 57977683534Smrg 58077683534Smrg pid = fork(); 58177683534Smrg if (pid < 0) { 58277683534Smrg perror("Couldn't fork"); 58377683534Smrg ExitProgram(1); 58477683534Smrg } 58577683534Smrg 58677683534Smrg if (pid == 0) { 58777683534Smrg close(pty); 58877683534Smrg if (pipe_option) { 58977683534Smrg close_waitpipe(1); 59077683534Smrg } 59177683534Smrg child(line, path, child_argv); 592a8fdb4bcSmrg } else { 59377683534Smrg if (pipe_option) { 59477683534Smrg close_waitpipe(0); 59577683534Smrg } 59677683534Smrg free(child_argv); 59777683534Smrg free(path); 59877683534Smrg free(line); 59977683534Smrg parent(pid, pty); 600a8fdb4bcSmrg } 601a8fdb4bcSmrg 602a8fdb4bcSmrg return 0; 603a8fdb4bcSmrg} 604a8fdb4bcSmrg 605a8fdb4bcSmrgvoid 60677683534Smrgchild(char *line, char *path, char *const argv[]) 607a8fdb4bcSmrg{ 608a8fdb4bcSmrg int tty; 609a8fdb4bcSmrg int pgrp; 610a8fdb4bcSmrg 611a8fdb4bcSmrg close(0); 612a8fdb4bcSmrg close(1); 613a8fdb4bcSmrg close(2); 614a8fdb4bcSmrg 615a8fdb4bcSmrg pgrp = setsid(); 61677683534Smrg if (pgrp < 0) { 61777683534Smrg kill(getppid(), SIGABRT); 61877683534Smrg ExitProgram(1); 619a8fdb4bcSmrg } 620a8fdb4bcSmrg 621a8fdb4bcSmrg tty = openTty(line); 62277683534Smrg if (tty < 0) { 62377683534Smrg kill(getppid(), SIGABRT); 62477683534Smrg ExitProgram(1); 62577683534Smrg } 62677683534Smrg if (pipe_option) { 62777683534Smrg write_waitpipe(c2p_waitpipe); 62877683534Smrg } 62977683534Smrg 63077683534Smrg if (tty != 0) 63177683534Smrg dup2(tty, 0); 63277683534Smrg if (tty != 1) 63377683534Smrg dup2(tty, 1); 63477683534Smrg if (tty != 2) 63577683534Smrg dup2(tty, 2); 63677683534Smrg 63777683534Smrg if (tty > 2) 63877683534Smrg close(tty); 63977683534Smrg 64077683534Smrg if (pipe_option) { 64177683534Smrg read_waitpipe(p2c_waitpipe); 64277683534Smrg close_waitpipe(0); 643a8fdb4bcSmrg } 64477683534Smrg 645a8fdb4bcSmrg execvp(path, argv); 646a8fdb4bcSmrg perror("Couldn't exec"); 64777683534Smrg ExitProgram(1); 648a8fdb4bcSmrg} 649a8fdb4bcSmrg 650a8fdb4bcSmrgvoid 65177683534Smrgparent(int pid GCC_UNUSED, int pty) 652a8fdb4bcSmrg{ 653a8fdb4bcSmrg unsigned char buf[BUFFER_SIZE]; 654a8fdb4bcSmrg int i; 655a8fdb4bcSmrg int rc; 656a8fdb4bcSmrg 65777683534Smrg if (pipe_option) { 65877683534Smrg read_waitpipe(c2p_waitpipe); 659a8fdb4bcSmrg } 660a8fdb4bcSmrg 66177683534Smrg if (verbose) { 66277683534Smrg reportIso2022(outputState); 66377683534Smrg } 66477683534Smrg setup_io(pty); 66577683534Smrg 66677683534Smrg if (pipe_option) { 66777683534Smrg write_waitpipe(p2c_waitpipe); 66877683534Smrg close_waitpipe(1); 66977683534Smrg } 67077683534Smrg 67177683534Smrg for (;;) { 67277683534Smrg rc = waitForInput(0, pty); 67377683534Smrg 67477683534Smrg if (sigwinch_queued) { 67577683534Smrg sigwinch_queued = 0; 67677683534Smrg setWindowSize(0, pty); 67777683534Smrg } 67877683534Smrg 67977683534Smrg if (sigchld_queued && exitOnChild) 68077683534Smrg break; 68177683534Smrg 68277683534Smrg if (rc > 0) { 68377683534Smrg if (rc & 2) { 68477683534Smrg i = (int) read(pty, buf, (size_t) BUFFER_SIZE); 68577683534Smrg if ((i == 0) || ((i < 0) && (errno != EAGAIN))) 68677683534Smrg break; 68777683534Smrg if (i > 0) 68877683534Smrg copyOut(outputState, 0, buf, (unsigned) i); 68977683534Smrg } 69077683534Smrg if (rc & 1) { 69177683534Smrg i = (int) read(0, buf, (size_t) BUFFER_SIZE); 69277683534Smrg if ((i == 0) || ((i < 0) && (errno != EAGAIN))) 69377683534Smrg break; 69477683534Smrg if (i > 0) 69577683534Smrg copyIn(inputState, pty, buf, i); 69677683534Smrg } 69777683534Smrg } 698a8fdb4bcSmrg } 699a8fdb4bcSmrg 700a8fdb4bcSmrg restoreTermios(); 70177683534Smrg cleanup_io(pty); 70277683534Smrg} 70377683534Smrg 70477683534Smrg#ifdef NO_LEAKS 70577683534Smrgvoid 70677683534Smrgluit_leaks(void) 70777683534Smrg{ 70877683534Smrg destroyIso2022(inputState); 70977683534Smrg destroyIso2022(outputState); 710a8fdb4bcSmrg} 71177683534Smrg#endif 712