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 }