]> TLD Linux GIT Repositories - rc-scripts.git/blob - src/getkey.c
- from PLD
[rc-scripts.git] / src / getkey.c
1 /*\r
2  * Copyright (c) 1999-2003, 2006 Red Hat, Inc. All rights reserved.\r
3  *\r
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License, version 2,
6  * as published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA\r
16  *
17  * getkey\r
18  *\r
19  * A very simple keygrabber.\r
20  *\r
21  */\r
22 #include <ctype.h>\r
23 #include <errno.h>\r
24 #include <signal.h>\r
25 #include <stdlib.h>\r
26 #include <stdio.h>\r
27 #include <string.h>\r
28 #include <termios.h>\r
29 #include <unistd.h>\r
30 #include <sys/poll.h>\r
31 #include "popt.h"\r
32 \r
33 static struct termios orig_tp;\r
34 \r
35 static void reset_term(int x) {\r
36         tcsetattr(0,TCSANOW,&orig_tp);\r
37         _exit(x);\r
38 }\r
39 \r
40 int main(int argc, char **argv) {\r
41         static const char default_list[] = "";\r
42 \r
43         const char *list;\r
44         char *waitmessage = NULL;\r
45         char *waitprint, *waitsprint;\r
46         int waitseconds=0;\r
47         int alarmlen=0;\r
48         int ignore_control=0;\r
49         struct termios tp;\r
50         int r;\r
51         struct pollfd ufds; /* only one, no need for an array... */\r
52         poptContext context;\r
53         struct poptOption options[] = {\r
54             { "wait", 'c', POPT_ARG_INT, &waitseconds, 0, "Number of seconds to wait for keypress", NULL },\r
55             { "message", 'm', POPT_ARG_STRING, &waitmessage, 0, "Message to print out while waiting for string\nNOTE: The message may have a \"%d\" in it, to hold the number of seconds left to wait.", NULL },\r
56             { "ignore-control-chars", 'i', POPT_ARG_NONE, &ignore_control, 0, "Ignore Control-C and Control-D", NULL },\r
57             POPT_AUTOHELP\r
58             POPT_TABLEEND\r
59         };\r
60 \r
61         context = poptGetContext("getkey", argc, (const char **)argv, options,\r
62                                 POPT_CONTEXT_POSIXMEHARDER);\r
63         poptSetOtherOptionHelp(context, "[keys]");\r
64 \r
65         r = poptGetNextOpt(context);\r
66         if (r < -1) {\r
67             fprintf(stderr, "%s: %s\n", \r
68                    poptBadOption(context, POPT_BADOPTION_NOALIAS),\r
69                    poptStrerror(r));\r
70 \r
71             return -1;\r
72         }\r
73         list = poptGetArg(context);\r
74         if (list != NULL) {\r
75             char *p;\r
76 \r
77             p = strdup(list);\r
78             list = p;\r
79             while (*p != 0) {\r
80                 *p = toupper(*p);\r
81                 p++;\r
82             }\r
83         } else\r
84             list = default_list;\r
85         if (waitseconds) {\r
86             if (waitseconds < 0) {\r
87                 fprintf(stderr, "--wait: Invalid time %d seconds\n",\r
88                         waitseconds);\r
89                 return -1;\r
90             }\r
91             alarmlen = waitseconds;\r
92         }\r
93 \r
94         tcgetattr(0,&tp);\r
95         orig_tp = tp;\r
96         signal(SIGTERM,reset_term);\r
97         if (alarmlen != 0) {\r
98             signal(SIGALRM,reset_term);\r
99             alarm(alarmlen);\r
100         }\r
101 \r
102         tp.c_iflag=0;\r
103         tp.c_oflag &= ~OPOST;\r
104         tp.c_lflag &= ~(ISIG | ICANON);\r
105         tcsetattr(0,TCSANOW,&tp);\r
106 \r
107         ufds.events = POLLIN;\r
108         ufds.fd = 0;\r
109 \r
110         if (waitmessage) {\r
111             waitprint = alloca (strlen(waitmessage)+15); /* long enough */\r
112             waitprint[0] = '\r';\r
113             waitsprint = waitprint + 1;\r
114         }\r
115 \r
116         while (1) {\r
117             if (waitmessage) {\r
118                 sprintf (waitsprint, waitmessage, waitseconds);\r
119                 write (1, waitprint, strlen(waitprint));\r
120             }\r
121             r = poll(&ufds, 1, alarmlen ? 1000 : -1);\r
122             if (r == 0) {\r
123                 /* we have waited a whole second with no keystroke... */\r
124                 waitseconds--;\r
125             }\r
126             if (r > 0) {\r
127                 char ch;\r
128 \r
129                 read(0, &ch, sizeof(ch));\r
130                 ch = toupper(ch);\r
131                 /* Die if we get a control-c or control-d */\r
132                 if (ignore_control == 0 && (ch == 3 || ch == 4))\r
133                     reset_term(1);\r
134                 /* Don't let a null character be interpreted as a match\r
135                    by strchr */\r
136                 if (ch != 0\r
137                     && (strcmp(list, "") == 0 || strchr(list, ch) != NULL))\r
138                     reset_term(0);\r
139             }\r
140         }\r
141 }\r