17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 523a1cceaSRoger A. Faulkner * Common Development and Distribution License (the "License"). 623a1cceaSRoger A. Faulkner * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate 227c478bd9Sstevel@tonic-gate /* 23*67a4bb8fSGary Mills * Copyright 2015 Gary Mills 2423a1cceaSRoger A. Faulkner * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 2723a1cceaSRoger A. Faulkner /* Copyright (c) 1988 AT&T */ 2823a1cceaSRoger A. Faulkner /* All Rights Reserved */ 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate /* 317c478bd9Sstevel@tonic-gate * cscope - interactive C symbol cross-reference 327c478bd9Sstevel@tonic-gate * 337c478bd9Sstevel@tonic-gate * terminal input functions 347c478bd9Sstevel@tonic-gate */ 357c478bd9Sstevel@tonic-gate 367c478bd9Sstevel@tonic-gate #include "global.h" 377c478bd9Sstevel@tonic-gate #include <curses.h> /* KEY_BACKSPACE, KEY_BREAK, and KEY_ENTER */ 387c478bd9Sstevel@tonic-gate #include <setjmp.h> /* jmp_buf */ 397c478bd9Sstevel@tonic-gate 407c478bd9Sstevel@tonic-gate static jmp_buf env; /* setjmp/longjmp buffer */ 417c478bd9Sstevel@tonic-gate static int prevchar; /* previous, ungotten character */ 427c478bd9Sstevel@tonic-gate 437c478bd9Sstevel@tonic-gate /* catch the interrupt signal */ 447c478bd9Sstevel@tonic-gate 457c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 467c478bd9Sstevel@tonic-gate SIGTYPE 477c478bd9Sstevel@tonic-gate catchint(int sig) 487c478bd9Sstevel@tonic-gate { 497c478bd9Sstevel@tonic-gate (void) signal(SIGINT, catchint); 507c478bd9Sstevel@tonic-gate longjmp(env, 1); 517c478bd9Sstevel@tonic-gate } 527c478bd9Sstevel@tonic-gate 537c478bd9Sstevel@tonic-gate /* unget a character */ 547c478bd9Sstevel@tonic-gate 557c478bd9Sstevel@tonic-gate int 567c478bd9Sstevel@tonic-gate ungetch(int c) 577c478bd9Sstevel@tonic-gate { 587c478bd9Sstevel@tonic-gate prevchar = c; 597c478bd9Sstevel@tonic-gate return (0); 607c478bd9Sstevel@tonic-gate } 617c478bd9Sstevel@tonic-gate 627c478bd9Sstevel@tonic-gate /* get a character from the terminal */ 637c478bd9Sstevel@tonic-gate 647c478bd9Sstevel@tonic-gate int 657c478bd9Sstevel@tonic-gate mygetch(void) 667c478bd9Sstevel@tonic-gate { 67*67a4bb8fSGary Mills SIGTYPE (*volatile savesig)() = SIG_DFL; /* old value of signal */ 687c478bd9Sstevel@tonic-gate int c; 697c478bd9Sstevel@tonic-gate 707c478bd9Sstevel@tonic-gate /* change an interrupt signal to a break key character */ 717c478bd9Sstevel@tonic-gate if (setjmp(env) == 0) { 727c478bd9Sstevel@tonic-gate savesig = signal(SIGINT, catchint); 737c478bd9Sstevel@tonic-gate (void) refresh(); /* update the display */ 747c478bd9Sstevel@tonic-gate reinitmouse(); /* curses can change the menu number */ 757c478bd9Sstevel@tonic-gate if (prevchar) { 767c478bd9Sstevel@tonic-gate c = prevchar; 777c478bd9Sstevel@tonic-gate prevchar = 0; 787c478bd9Sstevel@tonic-gate } else { 797c478bd9Sstevel@tonic-gate c = getch(); /* get a character from the terminal */ 807c478bd9Sstevel@tonic-gate } 817c478bd9Sstevel@tonic-gate } else { /* longjmp to here from signal handler */ 827c478bd9Sstevel@tonic-gate c = KEY_BREAK; 837c478bd9Sstevel@tonic-gate } 847c478bd9Sstevel@tonic-gate (void) signal(SIGINT, savesig); 857c478bd9Sstevel@tonic-gate return (c); 867c478bd9Sstevel@tonic-gate } 877c478bd9Sstevel@tonic-gate 887c478bd9Sstevel@tonic-gate /* get a line from the terminal in non-canonical mode */ 897c478bd9Sstevel@tonic-gate 907c478bd9Sstevel@tonic-gate int 9123a1cceaSRoger A. Faulkner getaline(char s[], size_t size, int firstchar, BOOL iscaseless) 927c478bd9Sstevel@tonic-gate { 937c478bd9Sstevel@tonic-gate int c, i = 0; 947c478bd9Sstevel@tonic-gate int j; 957c478bd9Sstevel@tonic-gate 967c478bd9Sstevel@tonic-gate /* if a character already has been typed */ 977c478bd9Sstevel@tonic-gate if (firstchar != '\0') { 987c478bd9Sstevel@tonic-gate if (iscaseless == YES) { 997c478bd9Sstevel@tonic-gate firstchar = tolower(firstchar); 1007c478bd9Sstevel@tonic-gate } 1017c478bd9Sstevel@tonic-gate (void) addch((unsigned)firstchar); /* display it */ 1027c478bd9Sstevel@tonic-gate s[i++] = firstchar; /* save it */ 1037c478bd9Sstevel@tonic-gate } 1047c478bd9Sstevel@tonic-gate /* until the end of the line is reached */ 1057c478bd9Sstevel@tonic-gate while ((c = mygetch()) != '\r' && c != '\n' && c != KEY_ENTER && 1067c478bd9Sstevel@tonic-gate c != '\003' && c != KEY_BREAK) { 1077c478bd9Sstevel@tonic-gate if (c == erasechar() || c == '\b' || /* erase */ 1087c478bd9Sstevel@tonic-gate c == KEY_BACKSPACE) { 1097c478bd9Sstevel@tonic-gate if (i > 0) { 1107c478bd9Sstevel@tonic-gate (void) addstr("\b \b"); 1117c478bd9Sstevel@tonic-gate --i; 1127c478bd9Sstevel@tonic-gate } 1137c478bd9Sstevel@tonic-gate } else if (c == killchar()) { /* kill */ 1147c478bd9Sstevel@tonic-gate for (j = 0; j < i; ++j) { 1157c478bd9Sstevel@tonic-gate (void) addch('\b'); 1167c478bd9Sstevel@tonic-gate } 1177c478bd9Sstevel@tonic-gate for (j = 0; j < i; ++j) { 1187c478bd9Sstevel@tonic-gate (void) addch(' '); 1197c478bd9Sstevel@tonic-gate } 1207c478bd9Sstevel@tonic-gate for (j = 0; j < i; ++j) { 1217c478bd9Sstevel@tonic-gate (void) addch('\b'); 1227c478bd9Sstevel@tonic-gate } 1237c478bd9Sstevel@tonic-gate i = 0; 1247c478bd9Sstevel@tonic-gate } else if (isprint(c) || c == '\t') { /* printable */ 1257c478bd9Sstevel@tonic-gate if (iscaseless == YES) { 1267c478bd9Sstevel@tonic-gate c = tolower(c); 1277c478bd9Sstevel@tonic-gate } 1287c478bd9Sstevel@tonic-gate /* if it will fit on the line */ 1297c478bd9Sstevel@tonic-gate if (i < size) { 1307c478bd9Sstevel@tonic-gate (void) addch((unsigned)c); /* display it */ 1317c478bd9Sstevel@tonic-gate s[i++] = c; /* save it */ 1327c478bd9Sstevel@tonic-gate } 1337c478bd9Sstevel@tonic-gate } else if (c == ctrl('X')) { 1347c478bd9Sstevel@tonic-gate /* mouse */ 1357c478bd9Sstevel@tonic-gate (void) getmouseevent(); /* ignore it */ 1367c478bd9Sstevel@tonic-gate } else if (c == EOF) { /* end-of-file */ 1377c478bd9Sstevel@tonic-gate break; 1387c478bd9Sstevel@tonic-gate } 1397c478bd9Sstevel@tonic-gate /* return on an empty line to allow a command to be entered */ 1407c478bd9Sstevel@tonic-gate if (firstchar != '\0' && i == 0) { 1417c478bd9Sstevel@tonic-gate break; 1427c478bd9Sstevel@tonic-gate } 1437c478bd9Sstevel@tonic-gate } 1447c478bd9Sstevel@tonic-gate s[i] = '\0'; 1457c478bd9Sstevel@tonic-gate return (i); 1467c478bd9Sstevel@tonic-gate } 1477c478bd9Sstevel@tonic-gate 1487c478bd9Sstevel@tonic-gate /* ask user to enter a character after reading the message */ 1497c478bd9Sstevel@tonic-gate 1507c478bd9Sstevel@tonic-gate void 1517c478bd9Sstevel@tonic-gate askforchar(void) 1527c478bd9Sstevel@tonic-gate { 1537c478bd9Sstevel@tonic-gate (void) addstr("Type any character to continue: "); 1547c478bd9Sstevel@tonic-gate (void) mygetch(); 1557c478bd9Sstevel@tonic-gate } 1567c478bd9Sstevel@tonic-gate 1577c478bd9Sstevel@tonic-gate /* ask user to press the RETURN key after reading the message */ 1587c478bd9Sstevel@tonic-gate 1597c478bd9Sstevel@tonic-gate void 1607c478bd9Sstevel@tonic-gate askforreturn(void) 1617c478bd9Sstevel@tonic-gate { 1627c478bd9Sstevel@tonic-gate if (linemode == NO) { 1637c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "Press the RETURN key to continue: "); 1647c478bd9Sstevel@tonic-gate (void) getchar(); 1657c478bd9Sstevel@tonic-gate } 1667c478bd9Sstevel@tonic-gate } 1677c478bd9Sstevel@tonic-gate 1687c478bd9Sstevel@tonic-gate /* expand the ~ and $ shell meta characters in a path */ 1697c478bd9Sstevel@tonic-gate 1707c478bd9Sstevel@tonic-gate void 1717c478bd9Sstevel@tonic-gate shellpath(char *out, int limit, char *in) 1727c478bd9Sstevel@tonic-gate { 1737c478bd9Sstevel@tonic-gate char *lastchar; 1747c478bd9Sstevel@tonic-gate char *s, *v; 1757c478bd9Sstevel@tonic-gate 1767c478bd9Sstevel@tonic-gate /* skip leading white space */ 1777c478bd9Sstevel@tonic-gate while (isspace(*in)) { 1787c478bd9Sstevel@tonic-gate ++in; 1797c478bd9Sstevel@tonic-gate } 1807c478bd9Sstevel@tonic-gate lastchar = out + limit - 1; 1817c478bd9Sstevel@tonic-gate 1827c478bd9Sstevel@tonic-gate /* 1837c478bd9Sstevel@tonic-gate * a tilde (~) by itself represents $HOME; followed by a name it 1847c478bd9Sstevel@tonic-gate * represents the $LOGDIR of that login name 1857c478bd9Sstevel@tonic-gate */ 1867c478bd9Sstevel@tonic-gate if (*in == '~') { 1877c478bd9Sstevel@tonic-gate *out++ = *in++; /* copy the ~ because it may not be expanded */ 1887c478bd9Sstevel@tonic-gate 1897c478bd9Sstevel@tonic-gate /* get the login name */ 1907c478bd9Sstevel@tonic-gate s = out; 1917c478bd9Sstevel@tonic-gate while (s < lastchar && *in != '/' && *in != '\0' && 1927c478bd9Sstevel@tonic-gate !isspace(*in)) { 1937c478bd9Sstevel@tonic-gate *s++ = *in++; 1947c478bd9Sstevel@tonic-gate } 1957c478bd9Sstevel@tonic-gate *s = '\0'; 1967c478bd9Sstevel@tonic-gate 1977c478bd9Sstevel@tonic-gate /* if the login name is null, then use $HOME */ 1987c478bd9Sstevel@tonic-gate if (*out == '\0') { 1997c478bd9Sstevel@tonic-gate v = getenv("HOME"); 2007c478bd9Sstevel@tonic-gate } else { /* get the home directory of the login name */ 2017c478bd9Sstevel@tonic-gate v = logdir(out); 2027c478bd9Sstevel@tonic-gate } 2037c478bd9Sstevel@tonic-gate /* copy the directory name */ 2047c478bd9Sstevel@tonic-gate if (v != NULL) { 2057c478bd9Sstevel@tonic-gate (void) strcpy(out - 1, v); 2067c478bd9Sstevel@tonic-gate out += strlen(v) - 1; 2077c478bd9Sstevel@tonic-gate } else { 2087c478bd9Sstevel@tonic-gate /* login not found so ~ must be part of the file name */ 2097c478bd9Sstevel@tonic-gate out += strlen(out); 2107c478bd9Sstevel@tonic-gate } 2117c478bd9Sstevel@tonic-gate } 2127c478bd9Sstevel@tonic-gate /* get the rest of the path */ 2137c478bd9Sstevel@tonic-gate while (out < lastchar && *in != '\0' && !isspace(*in)) { 2147c478bd9Sstevel@tonic-gate 2157c478bd9Sstevel@tonic-gate /* look for an environment variable */ 2167c478bd9Sstevel@tonic-gate if (*in == '$') { 2177c478bd9Sstevel@tonic-gate /* copy the $ because it may not be expanded */ 2187c478bd9Sstevel@tonic-gate *out++ = *in++; 2197c478bd9Sstevel@tonic-gate 2207c478bd9Sstevel@tonic-gate /* get the variable name */ 2217c478bd9Sstevel@tonic-gate s = out; 2227c478bd9Sstevel@tonic-gate while (s < lastchar && *in != '/' && *in != '\0' && 2237c478bd9Sstevel@tonic-gate !isspace(*in)) { 2247c478bd9Sstevel@tonic-gate *s++ = *in++; 2257c478bd9Sstevel@tonic-gate } 2267c478bd9Sstevel@tonic-gate *s = '\0'; 2277c478bd9Sstevel@tonic-gate 2287c478bd9Sstevel@tonic-gate /* get its value */ 2297c478bd9Sstevel@tonic-gate if ((v = getenv(out)) != NULL) { 2307c478bd9Sstevel@tonic-gate (void) strcpy(out - 1, v); 2317c478bd9Sstevel@tonic-gate out += strlen(v) - 1; 2327c478bd9Sstevel@tonic-gate } else { 2337c478bd9Sstevel@tonic-gate /* 2347c478bd9Sstevel@tonic-gate * var not found, so $ must be part of 2357c478bd9Sstevel@tonic-gate * the file name 2367c478bd9Sstevel@tonic-gate */ 2377c478bd9Sstevel@tonic-gate out += strlen(out); 2387c478bd9Sstevel@tonic-gate } 2397c478bd9Sstevel@tonic-gate } else { /* ordinary character */ 2407c478bd9Sstevel@tonic-gate *out++ = *in++; 2417c478bd9Sstevel@tonic-gate } 2427c478bd9Sstevel@tonic-gate } 2437c478bd9Sstevel@tonic-gate *out = '\0'; 2447c478bd9Sstevel@tonic-gate } 245