open system calls in C on linux - c

There are probably several problems with the code below. Found it online after searching for a way to get keyboard input in linux. I've verified the correct event for keyboard input. The reason it seems fishy to me is regardless of what i put in the filepath, it always seems to pass the error check (the open call returns something greater than 0). Something is obviously wrong, so suggestions are welcome.
This won't run correctly unless you run the exe as su.
When i want to read in my keystroke, do i just use something like fgets on the file descriptor in an infinite while loop(would that even work)? I want it to be constantly polling for keyboard inputs. Any tips on decoding the inputs from the keyboard event?
Thanks again! This project of mine may be overly ambitious, as it's been a really long time since i've done any coding.
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <fcntl.h>
#include <linux/input.h>
#include <unistd.h>
// Edit this line to reflect your filepath
#define FILE_PATH "/dev/input/event4"
int main()
{
printf("Starting KeyEvent Module\n");
size_t file; //will change this to int file; to make it possible to be negative
const char *str = FILE_PATH;
printf("File Path: %s\n", str);
error check here
if((file = open(str, O_RDONLY)) < 0)
{
printf("ERROR:File can not open\n");
exit(0);
}
struct input_event event[64];
size_t reader;
reader = read(file, event, sizeof(struct input_event) * 64);
printf("DO NOT COME HERE...\n");
close(file);
return 0;
}

the problem is here:
size_t file;
size_t is unsigned, so it will always be >=0
it should have been:
int file;

the open call returns something greater than 0
open returns int, but you put in in an unsigned variable (size_t is usually unsigned), so you fail to detect when it is <0

Related

How to read an integer and a char with read() function in C?

I'm working on linux, I have a file that contains a line like this:
328abc
I would like, in C, to read the integer part (328) and the characters 'a','b','c', using only the function:
ssize_t read (int filedes, void *buffer, size_t size))
This is the only thing the file contains.
I know there are better ways to do that with other functions, but I haven't coded in C for a long time, and trying to help a friend, only this function is alowed.
How do I play with the buffer to do that?
Thanks
edit:
I understand that I need to parse the buffer manually. and my question is how?
If that's the only thing in the file. This will do:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main() {
char buffer[6];
char intBuffer[4];
ssize_t bytesRead;
int number;
int fd;
if ((fd = open("file.txt", O_RDONLY)) == -1) {
perror("Error opening file");
exit(EXIT_FAILURE);
}
if ((bytesRead = read(fd, buffer, 6)) == -1) {
perror("Error reading file");
exit(EXIT_FAILURE);
}
memcpy(intBuffer, buffer, 3);
intBuffer[3] = '\0';
number = atoi(intBuffer);
printf("The number is %d\n", number);
exit(EXIT_SUCCESS);
}
The following code will print "The number is 328".
Is this some kind of homework?
I am asking because there are better ways to do that than using the read function.
Anyway to answer your question, read reads size bytes from the file whose file descriptor is filedes and places them to the buffer.
It does not know anything about line breaks etc. So you need to manually find where a line ends, etc. If you want to only use read, then you need to manually parse the buffer after each call to read (supposing your files contains many lines, that you want to parse).
Beware that a line may be split between two read calls, so you need to handle that case with caution.

shred and remove files in linux from a C program

I want to shred some temp files produced by my C program before the files are removed.
Currently I am using
system("shred /tmp/datafile");
system("rm /tmp/datafile");
from within my program, but I think instead of calling the system function is not the best way (correct me if I am wrong..) Is there any other way I can do it? How do I shred the file from within my code itself? A library, or anything? Also, about deletion part, is this answer good?
Can I ask why you think this is not the best way to achieve this? It looks like a good solution to me, if it is genuinely necessary to destroy the file contents irretrievably.
The advantage of this way of doing it are:
the program already exists (so it's faster to develop); and
the program is already trusted.
The second is an important point. It's possible to overstate the necessity of elaborately scrubbing files (Peter Gutmann, in a remark quoted on the relevant wikipedia page, has described some uses of his method as ‘voodoo’), but that doesn't matter: in any security context, using a pre-existing tool is almost always more defensible than using something home-made.
About the only criticism I'd make of your current approach, using system(3), is that since it looks up the shred program in the PATH, it would be possible in principle for someone to play games with that and get up to mischief. But that's easily dealt with: use fork(2) and execve(2) to invoke a specific binary using its full path.
That said, if this is just a low-impact bit of tidying up, then it might be still more straightforward to simply mmap the file and quickly write zeros into it.
You can use the following code:
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#define BUF_SIZE 4096
#define ABS_FILE_PATH "/tmp/aaa"
int main()
{
//get file size
struct stat stat_buf;
if (stat(ABS_FILE_PATH, &stat_buf) == -1)
return errno;
off_t fsize = stat_buf.st_size;
//get file for writing
int fd = open(ABS_FILE_PATH, O_WRONLY);
if (fd == -1)
return errno;
//fill file with 0s
void *buf = malloc(BUF_SIZE);
memset(buf, 0, BUF_SIZE);
ssize_t ret = 0;
off_t shift = 0;
while((ret = write(fd, buf,
((fsize - shift >BUF_SIZE)?
BUF_SIZE:(fsize - shift)))) > 0)
shift += ret;
close(fd);
free(buf);
if (ret == -1)
return errno;
//remove file
if (remove(ABS_FILE_PATH) == -1)
return errno;
return 0;
}

C Linux - Not Writing Integers

I don't know why I keep getting troubles to write an integer to a file.
Here's the code:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
int main (int argc, char* argv[]) {
int fd, w;
int num=80;
fd=open ("file3.txt", O_CREAT|O_WRONLY, 0777);
if (fd>0) {
w=write (fd, &num, sizeof (int));
if (w==-1) {
printf ("Writing Error \n");
return EXIT_FAILURE;
}
}
close (fd);
return EXIT_SUCCESS;
}
Does anyone know what could it be?
Thanks a lot...
You're writing binary values to the file, not ascii. If you want ascii in the file, you need to sprintf it first to a char buffer, then write the char buffer. Or open your file with fopen instead of open and use fprintf.
p.s. you want close(fd) inside your if (fd > 0) { block. Also, technically the only error return of open is -1. All other values (positive, zero, negative) are success.
From your comments it is working 100% correctly: P happens to be decimal 80.
write() is outputting bytes of the integer not a decimal representation.
You might want to look at fopen and fprintf as an easy way to get what it looks like you are expecting.

Win32 dispatch program and redirect stdout to file buffer problem?

On Wi32
I am trying to start a executable who redirects to a filename (current date) e.g. the same as:
Someexecutable.exe > 20101220000000.txt
When I do this from windows cmd.exe everything works fine. However when doing this from my program as shown below the system seems ot either drop the redirect even if it creates the file and/or it seems to buffer a large amount of data before flushing to disk.
I can't change the executable that is being run.
The program beeing executed now only writes to stdout, but remember I can't change this at all. (the simplest way woud be to just do stdout = filehandle; but I that is sadly impossible for me right now!)
(Not required: Also the program waits as system() this is not required but what is the simplest way of detaching the program being run via system() )
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(int argc, char *argv[])
{
char execstr[512];
char s[30];
size_t i;
struct tm tim;
time_t now;
now = time(NULL);
tim = *(localtime(&now));
i = strftime(s,30,"%Y%m%d%H%M",&tim);
sprintf(execstr,"someexecutable.exe > %s.txt",s);
printf("Executing: \"%s\"\n",execstr);
system(execstr);
exit(0);
return 0;
}
I don't see any reason for this to not work, but if this is the case with you, one of the alternative solution could be to use popen and then read from the pipe for writing in the desired file. Here is some sample code which is printing on the screen. You can write that to file instead of screen/console as per your requirement.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(int argc, char *argv[])
{
char execstr[512];
char s[30];
size_t i;
struct tm tim;
time_t now;
char buf[128];
FILE *pipe;
now = time(NULL);
tim = *(localtime(&now));
i = strftime(s,30,"%Y%m%d%H%M",&tim);
#if 0
sprintf(execstr,"a.exe > %s.txt",s);
printf("Executing: \"%s\"\n",execstr);
#endif /* #if 0 */
if( (pipe = _popen("a.exe", "rt")) == NULL )
exit( 1 );
while(!feof(pipe))
{
if (fgets(buf, 128, pipe) != NULL )
printf(buf); /* write to the required file here */
}
_pclose(pipe);
return 0;
}
Your program works fine for me (testing in VS 2010). Some problems you might run into if you're running your tests in the IDE are:
the current directory for the program might not be what you expect it to be (so you might be looking for the output file in the wrong place). By default, the current directory for the program when run in the IDE will be the directory that has the project file (whatever.vcproj or whatever,.vcxproj) - not the directory that has the executable. This can be changed in the project settings.
the IDE's path might not be the same as what you get at a standard command line, so you program might not be finding someexecutable.exe
If you change you program so that the line with the sprintf() call looks like:
sprintf(execstr,"someexecutable.exe",s);
Do you see the output of someexecutable.exe in the console window?

Reading Serial Data From C (OSX /dev/tty)

I am trying to read data from a bluetooth barcode scanner (KDC300) using C. Here is the code I have so far, and the program successfully establishes a bluetooth connection to the scanner, but when a barcode is scanned, no input is displayed on the screen (Eventually more will be done with the data, but we have to get it working first, right).
Here is the program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>
#include <sys/ioctl.h>
int main (int argc, const char * argv[]) {
// define vars
int STOP = 0;
//char buf[255];
if(argv[1])
{
int fd = open("/dev/tty.KDC1", O_RDONLY);
if(fd == -1)
{
printf("%s", strcat("Unable to open /dev/tty.", argv[1]));
}
int res;
while(STOP == 0)
{
while((res = read(fd,buf,255)) == 0);
{
if(res > 0)
{
buf[res]=0;
printf("%s:%d\n", buf, res);
if(buf[sizeof(buf)]=='\n') break;
}
}
}
}
return 0;
}
If anyone has any ideas, I am at a loss on this so far. If it is any help, I can run screen /dev/tty.KDC1 and any barcodes scanned on the scanner appear in the terminal, I just can't do anything with the data.
Jud
This line:
while((res = read(fd,buf,255)) == 0);
Does not do what you think it does. That's a while loop with an empty body.
#tommieb75,
the strcat statement was from the first "go" at the program, I took a variable from argv[1] and appended it to the /dev/tty.* so you could select which device you wanted to monitor.
I am not sure why I had commented out buf, probably stems from looking at the code too much / trying different approaches and forgetting where I was (not much of a C programmer, which is how I can get lost in 30 LOC).
#caf, Good catch on the extra semi-colon after the while loop, unfortunately, even after correcting it, the program doesn't behave correctly.
I am researching the problem further. I can verify (with osx packetlogger) that the computer is getting the data, but the but the buffer never has any data placed in it.
-Jud
---------------Edit--------------
I solved the problem after a little trial and error. Adding the following code to setup the serial connection solved everything:
struct termios theTermios;
memset(&theTermios, 0, sizeof(struct termios));
cfmakeraw(&theTermios);
cfsetspeed(&theTermios, 115200);
theTermios.c_cflag = CREAD | CLOCAL; // turn on READ
theTermios.c_cflag |= CS8;
theTermios.c_cc[VMIN] = 0;
theTermios.c_cc[VTIME] = 10; // 1 sec timeout
ioctl(fileDescriptor, TIOCSETA, &theTermios);
Thanks to the other answers for getting me to this point.
Here is the best info I've found.
The C program on there using termios worked just by adding
#include<string.h>
And changing the baudrate to match my needs.
In your code
printf("%s", strcat("Unable to open /dev/tty.", argv[1]));
Why did you do that? It would be easier to do it this way:
printf("%s: Unable to open /dev/tty.KDC1", argv[0]);
Why the parameter referencing to the command line?
res = read(fd,buf,255)
Why did you have buf declaration commented out above?

Resources