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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2015 Gary Mills 24 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. 25 */ 26 27 /* Copyright (c) 1988 AT&T */ 28 /* All Rights Reserved */ 29 30 /* 31 * cscope - interactive C symbol cross-reference 32 * 33 * terminal input functions 34 */ 35 36 #include "global.h" 37 #include <curses.h> /* KEY_BACKSPACE, KEY_BREAK, and KEY_ENTER */ 38 #include <setjmp.h> /* jmp_buf */ 39 40 static jmp_buf env; /* setjmp/longjmp buffer */ 41 static int prevchar; /* previous, ungotten character */ 42 43 /* catch the interrupt signal */ 44 45 /*ARGSUSED*/ 46 SIGTYPE 47 catchint(int sig) 48 { 49 (void) signal(SIGINT, catchint); 50 longjmp(env, 1); 51 } 52 53 /* unget a character */ 54 55 int 56 ungetch(int c) 57 { 58 prevchar = c; 59 return (0); 60 } 61 62 /* get a character from the terminal */ 63 64 int 65 mygetch(void) 66 { 67 SIGTYPE (*volatile savesig)() = SIG_DFL; /* old value of signal */ 68 int c; 69 70 /* change an interrupt signal to a break key character */ 71 if (setjmp(env) == 0) { 72 savesig = signal(SIGINT, catchint); 73 (void) refresh(); /* update the display */ 74 reinitmouse(); /* curses can change the menu number */ 75 if (prevchar) { 76 c = prevchar; 77 prevchar = 0; 78 } else { 79 c = getch(); /* get a character from the terminal */ 80 } 81 } else { /* longjmp to here from signal handler */ 82 c = KEY_BREAK; 83 } 84 (void) signal(SIGINT, savesig); 85 return (c); 86 } 87 88 /* get a line from the terminal in non-canonical mode */ 89 90 int 91 getaline(char s[], size_t size, int firstchar, BOOL iscaseless) 92 { 93 int c, i = 0; 94 int j; 95 96 /* if a character already has been typed */ 97 if (firstchar != '\0') { 98 if (iscaseless == YES) { 99 firstchar = tolower(firstchar); 100 } 101 (void) addch((unsigned)firstchar); /* display it */ 102 s[i++] = firstchar; /* save it */ 103 } 104 /* until the end of the line is reached */ 105 while ((c = mygetch()) != '\r' && c != '\n' && c != KEY_ENTER && 106 c != '\003' && c != KEY_BREAK) { 107 if (c == erasechar() || c == '\b' || /* erase */ 108 c == KEY_BACKSPACE) { 109 if (i > 0) { 110 (void) addstr("\b \b"); 111 --i; 112 } 113 } else if (c == killchar()) { /* kill */ 114 for (j = 0; j < i; ++j) { 115 (void) addch('\b'); 116 } 117 for (j = 0; j < i; ++j) { 118 (void) addch(' '); 119 } 120 for (j = 0; j < i; ++j) { 121 (void) addch('\b'); 122 } 123 i = 0; 124 } else if (isprint(c) || c == '\t') { /* printable */ 125 if (iscaseless == YES) { 126 c = tolower(c); 127 } 128 /* if it will fit on the line */ 129 if (i < size) { 130 (void) addch((unsigned)c); /* display it */ 131 s[i++] = c; /* save it */ 132 } 133 } else if (c == ctrl('X')) { 134 /* mouse */ 135 (void) getmouseevent(); /* ignore it */ 136 } else if (c == EOF) { /* end-of-file */ 137 break; 138 } 139 /* return on an empty line to allow a command to be entered */ 140 if (firstchar != '\0' && i == 0) { 141 break; 142 } 143 } 144 s[i] = '\0'; 145 return (i); 146 } 147 148 /* ask user to enter a character after reading the message */ 149 150 void 151 askforchar(void) 152 { 153 (void) addstr("Type any character to continue: "); 154 (void) mygetch(); 155 } 156 157 /* ask user to press the RETURN key after reading the message */ 158 159 void 160 askforreturn(void) 161 { 162 if (linemode == NO) { 163 (void) fprintf(stderr, "Press the RETURN key to continue: "); 164 (void) getchar(); 165 } 166 } 167 168 /* expand the ~ and $ shell meta characters in a path */ 169 170 void 171 shellpath(char *out, int limit, char *in) 172 { 173 char *lastchar; 174 char *s, *v; 175 176 /* skip leading white space */ 177 while (isspace(*in)) { 178 ++in; 179 } 180 lastchar = out + limit - 1; 181 182 /* 183 * a tilde (~) by itself represents $HOME; followed by a name it 184 * represents the $LOGDIR of that login name 185 */ 186 if (*in == '~') { 187 *out++ = *in++; /* copy the ~ because it may not be expanded */ 188 189 /* get the login name */ 190 s = out; 191 while (s < lastchar && *in != '/' && *in != '\0' && 192 !isspace(*in)) { 193 *s++ = *in++; 194 } 195 *s = '\0'; 196 197 /* if the login name is null, then use $HOME */ 198 if (*out == '\0') { 199 v = getenv("HOME"); 200 } else { /* get the home directory of the login name */ 201 v = logdir(out); 202 } 203 /* copy the directory name */ 204 if (v != NULL) { 205 (void) strcpy(out - 1, v); 206 out += strlen(v) - 1; 207 } else { 208 /* login not found so ~ must be part of the file name */ 209 out += strlen(out); 210 } 211 } 212 /* get the rest of the path */ 213 while (out < lastchar && *in != '\0' && !isspace(*in)) { 214 215 /* look for an environment variable */ 216 if (*in == '$') { 217 /* copy the $ because it may not be expanded */ 218 *out++ = *in++; 219 220 /* get the variable name */ 221 s = out; 222 while (s < lastchar && *in != '/' && *in != '\0' && 223 !isspace(*in)) { 224 *s++ = *in++; 225 } 226 *s = '\0'; 227 228 /* get its value */ 229 if ((v = getenv(out)) != NULL) { 230 (void) strcpy(out - 1, v); 231 out += strlen(v) - 1; 232 } else { 233 /* 234 * var not found, so $ must be part of 235 * the file name 236 */ 237 out += strlen(out); 238 } 239 } else { /* ordinary character */ 240 *out++ = *in++; 241 } 242 } 243 *out = '\0'; 244 } 245