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