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
catchint(int sig)46 catchint(int sig)
47 {
48 (void) signal(SIGINT, catchint);
49 longjmp(env, 1);
50 }
51
52 /* unget a character */
53
54 int
ungetch(int c)55 ungetch(int c)
56 {
57 prevchar = c;
58 return (0);
59 }
60
61 /* get a character from the terminal */
62
63 int
mygetch(void)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
getaline(char s[],size_t size,int firstchar,BOOL iscaseless)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
askforchar(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
askforreturn(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
shellpath(char * out,int limit,char * in)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