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