--- /dev/null
+.\" A man page for getkey(1). -*- nroff -*-
+.\"
+.\" Copyright (C) 2006 Red Hat, Inc. All rights reserved.
+.\"
+.\" This copyrighted material is made available to anyone wishing to use,
+.\" modify, copy, or redistribute it subject to the terms and conditions of the
+.\" GNU General Public License v.2.
+.\"
+.\" This program is distributed in the hope that it will be useful, but WITHOUT
+.\" ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+.\" FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+.\" more details.
+.\"
+.\" You should have received a copy of the GNU General Public License along
+.\" with this program; if not, write to the Free Software Foundation, Inc.,
+.\" 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+.\"
+.\" Author: Miloslav Trmac <mitr@redhat.com>
+.TH getkey 1 "Jan 2006"
+
+.SH NAME
+getkey \- wait until a key is pressed
+
+.SH SYNOPSIS
+\fBgetkey\fR [\fIOPTION\fR]... [\fIKEYS\fR]
+
+.SH DESCRIPTION
+.B getkey
+waits until one of
+.I KEYS
+is pressed.
+If
+.I KEYS
+are not specified, any key is accepted.
+.I KEYS
+are matched case-insensitive.
+
+.SH EXIT STATUS
+.B getkey
+exits with status 0 if one of the expected keys is pressed.
+If invalid arguments are specified,
+.B getkey
+exits with status 255.
+If
+.B getkey
+is interrupted or the wait times out,
+.B getkey
+exits with other non-zero status.
+
+.SH OPTIONS
+.TP
+\fB\-c\fR, \fB\-\-wait\fR \fISECONDS\fR
+Wait only for
+.I SECONDS
+seconds.
+The default is 0, which means to wait without a time limit.
+
+.TP
+\fB\-i\fR, \fB\-\-ignore\-control\-chars\fR
+Don't treat Ctrl+C and Ctrl+D specially.
+When this option is not specified, these characters interrupt \fBgetkey\fR.
+
+.TP
+\fB\-m\fR, \fB\-\-message\fR \fIMESSAGE\fR
+Display
+.I MESSAGE
+while waiting.
+The message is used as a format string in
+.BR sprintf (3),
+with a single argument, the number of seconds left.
+Typical usage is therefore
+\fB"Press a key within %d seconds to ..."\fR.
+If
+.I MESSAGE
+contains other format string directives, the behavior is undefined and
+.B getkey
+may crash.
+
+If there is no time limit specified,
+the number of seconds left is reported as 0.
/*\r
- * Copyright (c) 1999-2003 Red Hat, Inc. All rights reserved.\r
+ * Copyright (c) 1999-2003, 2006 Red Hat, Inc. All rights reserved.\r
*\r
* This software may be freely redistributed under the terms of the GNU\r
* public license.\r
#include <sys/poll.h>\r
#include "popt.h"\r
\r
-struct termios tp;\r
+static struct termios orig_tp;\r
\r
-void reset_term(int x) {\r
- tcsetattr(0,TCSANOW,&tp);\r
- exit(x);\r
+static void reset_term(int x) {\r
+ tcsetattr(0,TCSANOW,&orig_tp);\r
+ _exit(x);\r
}\r
\r
int main(int argc, char **argv) {\r
- char foo[2];\r
- char list[100]; /* should be enough */\r
+ static const char default_list[] = "";\r
+\r
+ const char *list;\r
char *waitmessage = NULL;\r
char *waitprint, *waitsprint;\r
- const char *fooptr;\r
int waitseconds=0;\r
int alarmlen=0;\r
int ignore_control=0;\r
- int tp_if,tp_of,tp_lf;\r
- int x, r;\r
+ struct termios tp;\r
+ int r;\r
struct pollfd ufds; /* only one, no need for an array... */\r
poptContext context;\r
struct poptOption options[] = {\r
{ "wait", 'c', POPT_ARG_INT, &waitseconds, 0, "Number of seconds to wait for keypress", NULL },\r
- /* { "message", 'm', POPT_ARG_STRING, &waitmessage, 0, "Message to print out while waiting for string", "NOTE: argument must have a \"%d\" in it so the number of seconds\nleft until getkey times out can be printed" },*/\r
- { "message", 'm', POPT_ARG_STRING, &waitmessage, 0, "Message to print out while waiting for string\nNOTE: message must have a \"%d\" in it, to hold the number of seconds left to wait", NULL },\r
+ { "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
{ "ignore-control-chars", 'i', POPT_ARG_NONE, &ignore_control, 0, "Ignore Control-C and Control-D", NULL },\r
POPT_AUTOHELP\r
POPT_TABLEEND\r
};\r
\r
- strcpy(list, "");\r
- context = poptGetContext("getkey", argc, argv, options, \r
+ context = poptGetContext("getkey", argc, (const char **)argv, options,\r
POPT_CONTEXT_POSIXMEHARDER);\r
poptSetOtherOptionHelp(context, "[keys]");\r
\r
\r
return -1;\r
}\r
- fooptr = poptGetArg(context);\r
- if (fooptr != NULL) {\r
- strncpy(list, fooptr, sizeof(list) - 1);\r
- list[99] = '\0';\r
- for (x=0;list[x];x++) list[x]=toupper(list[x]);\r
- }\r
+ list = poptGetArg(context);\r
+ if (list != NULL) {\r
+ char *p;\r
+\r
+ p = strdup(list);\r
+ list = p;\r
+ while (*p != 0) {\r
+ *p = toupper(*p);\r
+ p++;\r
+ }\r
+ } else\r
+ list = default_list;\r
if (waitseconds) {\r
+ if (waitseconds < 0) {\r
+ fprintf(stderr, "--wait: Invalid time %d seconds\n",\r
+ waitseconds);\r
+ return -1;\r
+ }\r
alarmlen = waitseconds;\r
}\r
- foo[0]=foo[1]='\0';\r
\r
+ tcgetattr(0,&tp);\r
+ orig_tp = tp;\r
signal(SIGTERM,reset_term);\r
- alarm(alarmlen);\r
- signal(SIGALRM,reset_term);\r
+ if (alarmlen != 0) {\r
+ signal(SIGALRM,reset_term);\r
+ alarm(alarmlen);\r
+ }\r
\r
- tcgetattr(0,&tp);\r
- tp_if=tp.c_iflag;\r
- tp_of=tp.c_oflag;\r
- tp_lf=tp.c_lflag;\r
tp.c_iflag=0;\r
tp.c_oflag &= ~OPOST;\r
tp.c_lflag &= ~(ISIG | ICANON);\r
tcsetattr(0,TCSANOW,&tp);\r
- tp.c_iflag=tp_if;\r
- tp.c_oflag=tp_of;\r
- tp.c_lflag=tp_lf;\r
\r
ufds.events = POLLIN;\r
ufds.fd = 0;\r
\r
- if (waitseconds && waitmessage) {\r
+ if (waitmessage) {\r
waitprint = alloca (strlen(waitmessage)+15); /* long enough */\r
waitprint[0] = '\r';\r
waitsprint = waitprint + 1;\r
}\r
\r
while (1) {\r
- if (waitseconds && waitmessage) {\r
+ if (waitmessage) {\r
sprintf (waitsprint, waitmessage, waitseconds);\r
write (1, waitprint, strlen(waitprint));\r
}\r
waitseconds--;\r
}\r
if (r > 0) {\r
- read(0,foo,1);\r
- foo[0]=toupper(foo[0]);\r
+ char ch;\r
+\r
+ read(0, &ch, sizeof(ch));\r
+ ch = toupper(ch);\r
/* Die if we get a control-c or control-d */\r
- if (ignore_control == 0) {\r
- if (foo[0]==3 || foo[0]==4) reset_term(1);\r
- }\r
+ if (ignore_control == 0 && (ch == 3 || ch == 4))\r
+ reset_term(1);\r
/* Don't let a null character be interpreted as a match\r
- by strstr */\r
- if (foo[0] != 0) {\r
- if (strcmp(list, "") == 0 || strstr(list,foo)) {\r
- reset_term(0);\r
- }\r
- }\r
+ by strchr */\r
+ if (ch != 0\r
+ && (strcmp(list, "") == 0 || strchr(list, ch) != NULL))\r
+ reset_term(0);\r
}\r
}\r
}\r