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