Just trying to seek to understand. I'm writing a small program that will read in a keystroke event from the keyboard, and trigger certain events (using a switch statement). I'm making some assumptions, and attempting to treat the keyboard like a txt file to read from.
I'm kind of at a loss as to the simplest way to do this.
What i WANT to do it open the file(keyboard event4), and use something like fgets to read it in character by character in an infinite while loop, then use a switch statement to break out of the loop and exit.
Where i'm getting stuck is the fact that these are system calls, and i'm basically unsure how to handle them.
The code below definitely won't compile, just putting it there as a rough demonstration of what i am trying to do.
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
int main(void)
{
// errors on opening
int fd = open("/dev/input/event4", O_RDONLY);
if(fd < 0)
{
printf("error while opening/n");
return 1;
}
int keystroke = 0;
while (1)
{
keystroke = fgetsc(fd);
switch(keystroke)
{
case '1' :
break;
case '2' :
break;
case '3' :
break;
default:
printf("waiting for 1, 2, 3/n");
}
close(fd);
return 0;
}
1) Read "raw keyboard input" is generally OS-dependent. The APIs and techniques can vary greatly depending if you're on Windows vs Linux, for example.
2) It sounds like you're on a *nix variant (Linux or MacOS, for example). If you want to do all the "grunge" yourself, here's a great "howto":
http://www.tldp.org/HOWTO/pdf/Keyboard-and-Console-HOWTO.pdf
3) You'll need to put the keyboard device into "raw", "unbuffered" mode in order to read keystrokes. Among other things...
4) I would encourage you, however, to leverage a higher-level library, like ncurses or SDL.
'Hope that helps!
Related
I am trying to detect the Ctrl+D user input, which I know returns EOF. Right now, I know the code waits for input from the stdin stream, but is there a way to let the program continue until the Ctrl+D command is in stdin? The program should continue running past the if statement if Ctrl+D isn't inputted.
char buffer[];
if (fgets(buffer, 10, stdin) == NULL{
//write to file
}
You want to stop your program when the user presses Ctrl+D without actually reading stdin? In this case, you should consider using Ctrl+C instead. But first I will write something about non-blocking I/O, since this is what you are asking for.
There is no way to achieve nonblocking I/O in standard C. However, you could use POSIX-functions like select or fcntl in combination with read. There are other questions about it on StackOverflow which should provide all information you need. This question for example.
If you want to handle Ctrl+C instead, you can use thesignal function:
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
volatile bool shouldRun = true;
void sighandler(int) {
shouldRun = false;
}
int main(int argc, char *argv[]) {
if (signal(SIGINT, &sighandler) == SIG_ERR) {
fprintf(stderr, "Could not set signal handler\n");
return EXIT_FAILURE;
}
printf("Program started\n");
while (shouldRun) {
// Do something...
}
printf("Program is shutting down.\n");
return EXIT_SUCCESS;
}
Note that signal handlers (i.e. sighandler) might interrupt your thread at any moment. This means they are prone to race conditions. You must even avoid acquiring any locks within a signal handler. This means just calling printf within a signal handler can cause a deadlock. Just setting boolean flags as shown in the example is fine, though. There are solutions like signal masks and the self pipe trick to circumvent these limitations, but they should not be necessary here.
Since the machine generates EOF on Ctrl+D, you should be checking fgets() for NULL, as fgets() is obliged to return NULL on end of file.
line = fgets(l, BUFFSIZE, stdin)
if (line == NULL)
continue;
On most operating systems, stdin is buffered one line at a time, and any attempt to read it (without going into low-level nasties) will stop until either a line or EOF is available. If you don't mind this, and just want to check for EOF without reading-in any waiting input if EOF is not present, you could use ungetc:
#include <stdio.h>
int check_for_EOF() {
if (feof(stdin)) return 1;
int c = getc(stdin);
if (c == EOF) return 1;
ungetc(c, stdin);
}
int main() {
printf("Start typing:\n");
while (!check_for_EOF()) {
int bytes_typed = 0;
while (getchar() != '\n') bytes_typed++;
printf("You typed a line of %d bytes\n", bytes_typed);
}
printf("You typed EOF\n");
}
You are only guaranteed one character of push-back from ungetc, although most implementations give you much more. And it works only if you're not going to seek the stream later (which is the case with stdin). Notice also that I'm calling it "bytes typed", not "characters typed": Chinese, Japanese and Korean characters for example cannot fit into the char type of most C implementations, and it would depend how the console encodes them when you type (if you have a CJK input method set up or can copy/paste some, you can try it on the above program and see).
It is too much to post here and you are not specific what you have currently and what you want. So here gives you a general idea of how to do it:
Put that if statement inside a forked process or other thread
Send a posix signal to your (parent) process when the key is captured
Add signal handler in your program
If you just wanna terminate the program when C-d is entered, just send a SIGKILL in step 2 and ignore step 3.
If you do not know any term above, Google is your friend
I have a C program, that I would like to print its output from swift, and when it scans I can give it input through Swift. Is such thing possible? I tried this with a simple function, and it worked, but how can someone do so with many different functions that call other functions?
I know the question is a bit vague, but can someone point me into the right direction?
Example of code:
int main(int argc, char **argv) {
int i;
int hitme;
char ch;
prelim();
if (argc > 1) { // look for -f option
if (strcmp(argv[1], "-f")== 0) {
coordfixed = 1;
argc--;
argv++;
}
}
if (argc > 1) {
fromcommandline = 1;
line[0] = '\0';
while (--argc > 0) {
strcat(line, *(++argv));
strcat(line, " ");
}
}
else fromcommandline = 0;
while (TRUE) { /* Play a game */
setup();
if (alldone) {
score(0);
alldone = 0;
}
else makemoves();
skip(2);
stars();
skip(1);
if (tourn && alldone) {
printf("Do you want your score recorded?");
if (ja()) {
chew2();
freeze(FALSE);
}
}
printf("Do you want to play again?");
if (!ja()) break;
}
skip(1);
prout("May the Great Bird of the Galaxy roost upon your home planet.");
return 0;
}
Yes.
This is extensively covered in Using Swift with Cocoa and Objective-C. Objective-C is a superset of C, so all the instructions for Objective-C work equally well for C.
The short version is that you just add the C code to your project, import its header in your Objective-C Bridging Header, and then the C functions will be available in Swift (using various automatic translations).
That said, if you really want to read the output (i.e. the results of these printf) calls, that's a bit different problem. I'd avoid it if you can. Otherwise you'd need to do something like build the C program as its own executable and use NSTask within Swift to call it and capture the output, or you'd have to hijack stdout with something like fdopen. It's a pain to do that completely correctly.
I will focus on the second part of your question, how to interact with C code that uses the standard IO facilities:
The obvious choice as Rob Napier pointed out is just compiling the C code into an executable and using something akin to popen(3) to read and write to its standard IO facilities, the same way you would read/write any other FILE*.
Another way would be to seek out places where stdio is used and change these functions. For example you could use
#ifdef STANDALONE
#define print printf
#else
#define print passToSwift
#endif
Then you can change all the printfs to prints and just #define which mode you want your C code to operate in. In case STANDALONE is left undefined, you will have to provide a passToSwift function that will connect your C and Swift functionality.
One more way without having to change all printfs is using funopen(3) or friends, particularly fwopen(3). With fwopen(3) (man fwopen) you can provide a passToSwift function to be called whenever something is written to stdout.
#include <stdio.h>
int passToSwift(void * cookie, const char * buffer, int len)
{
(void)cookie;
// do stuff with the buffer you recieved
return len;
}
int main(void)
{
fflush(stdout);
stdout = fwopen(NULL, passToSwift);
printf("Hey\n");
}
The assignment to stdout is not portable, but works for me on OS X. I am not aware of any other way to achieve it. (dup2 gives EBADF for funopend streams, freopen expects an entry in the filesystem).
I am adressing a quite similar problem.
I have a solution open to discussion on codereview: C hack: replace printf to collect output and return complete string by using a line buffer
Maybe you could use that (or a part of it) for your text game as well ...
The improved version of C hack: replace printf to collect output and return complete string by using a line buffer is now availabe on github as Xcode 7 project swift-C-string-passing (and standalone gcc version).
Especially look at the #define preprocessor statements to make use of the bridge to swift (similar to a3f's answer).
My solution is able to pass strings in and out to the C code. But how are the answers retrieved from the user? I.e. what does the ja() function do?
I need a command in cmd that works like pause but I can code to continue.
e.g.
system("pause");
some lines of code;`
The problem with system("pause") is that "some lines of code" will not work until the user press sth.
I want to continue cmd with some command.
I want something that run the code but update cmd only when I give the
permission to it.
If I understand correctly, the code shall produce output which you don't want to be shown before you press a key. If you don't mind to have the output paged, you could use something like
FILE *stream = popen("PAUSE<CON&&MORE", "w");
and let the code output to stream (with fprintf(stream, ...) etc.).
Don't ever use system() if you can avoid it. It's crude, error-prone, and non-portable.
C11 introduces threading support, including thrd_sleep(). That should be your preferred solution (if supported by your compiler setup).
If your compiler vendor does not support C11, bugger him about it. That standard is almost four years old now.
WinAPI defines the Sleep() function:
VOID WINAPI Sleep(
_In_ DWORD dwMilliseconds
);
This function causes a thread to relinquish the remainder of its time
slice and become unrunnable for an interval based on the value of
dwMilliseconds.
#include <windows.h>
int main()
{
Sleep( 5000 ); // pause execution for at least 5 seconds
some_lines_of_code;
return 0;
}
I think what you're looking for is a method to check if stdin contains data ready to read; you want to use some non-blocking or asynchronous I/O so that you can read input when it becomes available, and perform other tasks until then.
You won't find a whole heap about non-blocking/asynchronous I/O in standard C, but in POSIX C you can set STDIN_FILENO as non-blocking using fcntl. As an example, here's a program which prompts you to press enter (like pause does) and busy-loops, allowing your code to conduct other (preferably non-blocking) actions inside the loop while it waits for the keystroke (ahemm, byte, since stdin is technically a file):
#include <stdio.h>
#include <fcntl.h>
int main(void) {
char c;
puts("Press any key to continue...");
fcntl(STDIN_FILENO, F_SETFL, fcntl(STDIN_FILENO, F_GETFL, 0) | O_NONBLOCK);
while (read(STDIN_FILENO, 1, &c) != 1 && errno == EAGAIN) {
/* code in here will execute repeatedly until a key is struck or a byte is sent */
errno = 0;
}
if (errno) {
/* code down here will execute when an input error occurs */
}
else {
/* code down here will execute when that precious byte is finally sent */
}
}
That's non-blocking I/O. Other alternatives include using asynchronous I/O or extra threads. You should probably use non-blocking I/O or asynchronous I/O (i.e. epoll or kqueue) for this task in particular; using extra threads just to determine when a character is sent to stdin is likely a little bit too hefty.
What I am trying to do
So, I have been trying to access keyboard input in Linux. Specifically, I need to be able to access modifier key presses without other keys being pressed. Furthermore, I want to be able to do this without an X system running.
So, in short, my requirements are these:
Works on Linux
Does not need X11
Can retrieve modifier key press without any other keys being pressed
This includes the following keys:
Shift
Control
Alt
All I need is a simple 0 = not pressed, 1 = currently pressed to let me know if
the key is being held down when the keyboard is checked
My computer setup
My normal Linux machine is on a truck towards my new apartment; so, I only have a Macbook Air to work with right now. Therefore, I am running Linux in a VM to test this out.
Virtual Machine in VirtualBox
OS: Linux Mint 16
Desktop Environment: XFCE
Everything below was done in this environment. I've tried both with X running and in one of the other ttys.
My Thoughts
I'll alter this if someone can correct me.
I've done a fair bit of reading to realize that higher-level libraries do not provide this kind of functionality. Modifier keys are used with other keys to provide an alternate key code. Accessing the modifier keys themselves through a high-level library in Linux isn't as easy. Or, rather, I haven't found a high-level API for this on Linux.
I thought libtermkey would be the answer, but it doesn't seem to support the Shift modifier key any better than normal keystroke retrieval. I'm also not sure if it works without X.
While working with libtermkey (before I realized it didn't get shift in cases like Shift-Return), I was planning to write a daemon that would run to gather keyboard events. Running copies of the daemon program would simply pipe requests for keyboard data and receive keyboard data in response. I could use this setup to have something always running in the background, in case I cannot check key code statuses at specific times (have to be receive key codes as they happen).
Below are my two attempts to write a program that can read from the Linux keyboard device. I've also included my small check to make sure I had the right device.
Attempt #1
I have tried to access the keyboard device directly, but am encountering issues. I have tried the suggestion here that is in another Stack Overflow thread. It gave me a segmentation fault; so, I changed it from fopen to open:
// ...
int fd;
fd = open("/dev/input/by-path/platform-i8042-serio-0-event-kbd", O_RDONLY);
char key_map[KEY_MAX/8 + 1];
memset(key_map, 0, sizeof(key_map));
ioctl(fd, EVIOCGKEY(sizeof key_map), key_map);
// ...
While there was no segmentation fault, there was no indicator of any key press (not just modifier keys). I tested this using:
./foo && echo "TRUE" || echo "FALSE"
I've used that to test for successful return codes from commands quite a lot; so, I know that's fine. I've also outputted the key (always 0) and mask (0100) to check. It just doesn't seem to detect anything.
Attempt #2
From here, I thought I'd try a slightly different approach. I wanted to figure out what I was doing wrong. Following this page providing a snippet demonstrating printing out key codes, I bundled that into a program:
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <fcntl.h>
#include <linux/input.h>
int main(int argc, char** argv) {
uint8_t keys[128];
int fd;
fd = open("/dev/input/by-path/platform-i8042-serio-event-kbd", O_RDONLY);
for (;;) {
memset(keys, 0, 128);
ioctl (fd, EVIOCGKEY(sizeof keys), keys);
int i, j;
for (i = 0; i < sizeof keys; i++)
for (j = 0; j < 8; j++)
if (keys[i] & (1 << j))
printf ("key code %d\n", (i*8) + j);
}
return 0;
}
Previously, I had the size to 16 bytes instead of 128 bytes. I should honestly spend a bit more time understanding ioctl and EVIOCGKEY. I just know that it supposedly maps bits to specific keys to indicate presses, or something like that (correct me if I'm wrong, please!).
I also didn't have a loop initially and would just hold down various keys to see if a key code appeared. I received nothing; so, I thought a loop might make the check easier to test in case a missed something.
How I know the input device is the right one
I tested it by running cat on the input device. Specifically:
$ sudo cat /dev/input/by-path/platform-i8042-serio-0-event-kbd
Garbage ASCII was sent to my terminal on key press and release events starting with the return (enter) key when I began the output using cat. I also know that this seems to work fine with modifier keys like shift, control, function, and even Apple's command key on my Macbook running a Linux VM. Output appeared when a key was pressed, began to appear rapidly from subsequent signals sent by holding the key down, and outputted more data when a key was released.
So, while my approach may not be the right one (I'm willing to hear any alternative), the device seems to provide what I need.
Furthermore, I know that this device is just a link pointing to /dev/input/event2 from running:
$ ls -l /dev/input/by-path/platform-i8042-serio-0-event-kbd
I've tried both programs above with /dev/input/event2 and received no data. Running cat on /dev/input/event2 provided the same output as with the link.
Open the input device,
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <linux/input.h>
#include <string.h>
#include <stdio.h>
static const char *const evval[3] = {
"RELEASED",
"PRESSED ",
"REPEATED"
};
int main(void)
{
const char *dev = "/dev/input/by-path/platform-i8042-serio-0-event-kbd";
struct input_event ev;
ssize_t n;
int fd;
fd = open(dev, O_RDONLY);
if (fd == -1) {
fprintf(stderr, "Cannot open %s: %s.\n", dev, strerror(errno));
return EXIT_FAILURE;
}
and then read keyboard events from the device:
while (1) {
n = read(fd, &ev, sizeof ev);
if (n == (ssize_t)-1) {
if (errno == EINTR)
continue;
else
break;
} else
if (n != sizeof ev) {
errno = EIO;
break;
}
The above snippet breaks out from the loop if any error occurs, or if the userspace receives only a partial event structure (which should not happen, but might in some future/buggy kernels). You might wish to use a more robust read loop; I personally would be satisfied by replacing the last break with continue, so that partial event structures are ignored.
You can then examine the ev event structure to see what occurred, and finish the program:
if (ev.type == EV_KEY && ev.value >= 0 && ev.value <= 2)
printf("%s 0x%04x (%d)\n", evval[ev.value], (int)ev.code, (int)ev.code);
}
fflush(stdout);
fprintf(stderr, "%s.\n", strerror(errno));
return EXIT_FAILURE;
}
For a keypress,
ev.time: time of the event (struct timeval type)
ev.type: EV_KEY
ev.code: KEY_*, key identifier; see complete list in /usr/include/linux/input.h
ev.value: 0 if key release, 1 if key press, 2 if autorepeat keypress
See Documentation/input/input.txt in the Linux kernel sources for further details.
The named constants in /usr/include/linux/input.h are quite stable, because it is a kernel-userspace interface, and the kernel developers try very hard to maintain compatibility. (That is, you can expect there to be new codes every now and then, but existing codes rarely change.)
In my C program I would like to know where my cursor is located in terminal. For example, another program could have written something before mine and I would like to know how much space is left before the last column of the terminal, or I could not know the terminal reaction to some special sequences (like colors: I could write it but they are not showed).
Any suggestion?
Edit: it would be better avoiding over complicated solutions like ncurses (ncurses doesn't know where's the cursor directly: it computes its position).
Edit 2: I found a way to do it, but it works only in non-graphical terminals: https://www.linuxquestions.org/questions/programming-9/get-cursor-position-in-c-947833/
Edit 3: Nice code and it works well, but it uses /dev/vcsaN (same problem of Edit 2): http://dell9.ma.utexas.edu/cgi-bin/man-cgi?vcs+4
Ncurses is a big and powerful library for creating terminal-based text interfaces.
tputs is a simple low-level universal function for manipulating terminal capabilities.
Either one could serve your needs.
You could try using ncurses' getyx().
This solution is not optimal because it refers to /dev/vcsa*. Hope this could help someone else.
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
int main(void)
{
int fd;
char *device = "/dev/vcsa2";
struct {unsigned char lines, cols, x, y;} scrn;
fd = open(device, O_RDWR);
if (fd < 0) {
perror(device);
exit(EXIT_FAILURE);
}
(void) read(fd, &scrn, 4);
printf("%d %d\n", scrn.x, scrn.y);
exit(EXIT_SUCCESS);
}
Generally you are supposed to remember where you've left the cursor.
However, most terminals do respond to DSR; Device Status Request. By sending
CSI 6 n
you'll receive a CPR; cursor position report, in the form of
CSI Pl;Pc R
where Pl and Pc give the cursor line and column number, indexed from 1.