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