pass arguments to running C app - c

I am writing small C program which will act like daemon and do something every second. I managed it to run only single instance using filelock and last thing I need to know is if it is possible to send commandline arguments to running program, something like that:
first program start:
./sampleprogram
then decide to take some action/update setting
./sampleprogram -r
it will be another rotation script for my thinkpad X41 convertible:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
/*#include <stdbool.h>*/
#define TRUE 1
#define FALSE 0
#define NIL -1
int fdlock;
int get_lock(void)
{
struct flock fl;
fl.l_type = F_WRLCK;
fl.l_whence = SEEK_SET;
fl.l_start = 0;
fl.l_len = 1;
if((fdlock = open("oneproc.lock", O_WRONLY|O_CREAT, 0666)) == -1) { return 0; }
if(fcntl(fdlock, F_SETLK, &fl) == -1) { return 0; }
return 1;
}
int main() {
if(!get_lock()) {
fputs("Process already running!\n", stderr);
return 1;
}
int tabletmode;
int autorotate = TRUE;
int prevmode = NIL;
FILE *fstate;
char state[1];
FILE *fgyrovals;
char gyroval_a[1];
while (TRUE) {
fstate = fopen("/sys/devices/platform/thinkpad_acpi/hotkey_tablet_mode", "r");
fread(state, sizeof(state[0]), 1, fstate);
/*
printf("picaa");
fflush(stdout);
*/
/*tabletmode = atoi(state[0]);*/
tabletmode = state[0] - '0';
printf("koko: %d", tabletmode);
fflush(stdout);
fclose(fstate);
if (prevmode != tabletmode) {
if (tabletmode) {
system("notify-send 'Notebook v tablet móde'");
} else {
system("notify-send 'Notebook v štandartnom režime'");
}
}
if (tabletmode) {
if (autorotate) {
fgyrovals = fopen("/sys/devices/platform/hdaps/position", "r");
fclose(fgyrovals);
}
}
prevmode = tabletmode;
sleep(1);
}
return 0;
}

Related

FIBMAP vs FIEMAP ioctl syscall differences

I coded a little tool to show the number of logical blocks of a file and the physical blocks mapped. Using ictl FIBMAP system call, I'm looking on logical-to-physicaal block mapping. So I used an old FIBMAP ictl syscall. My question is : what are the differences between FIBMAP and FIEMAP ? Do you have some tips to deep further into log-phy mapping from my code ? Furthermore, many logical blocks dont seem to map physical blocks. What is the reason ?
ÉDIT :
So I just learned that FIBMAP needs CAP_SYS_RAWIO, so only for root.
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <linux/fs.h>
#define UNLESS(X) if (!(X))
#define ARRAY_NUM(X) sizeof(X)/sizeof(*(X))
#define ERROR(msg) do { perror(msg); exit(EXIT_FAILURE); } while (0)
#define RETURN(msg) do { perror(msg); return errno; } while (0)
#define XFREE(X) (X) do { free(X); X = NULL; } while (0)
int get_blck(int fd, int log_block){
int res;
res = ioctl(fd, FIBMAP, &log_block);
if (res < 0) {
ERROR("ioctl FIBMAP failed !\n");
}
return log_block;
}
/* we get the number of logical blocks */
int get_nbr_blcks(int fd){
struct stat buff;
int res;
res = fstat(fd, &buff);
if (res < 0) {
ERROR("fstat error !\n");
}
return buff.st_blocks;
}
/* We print the physical blocks sorted */
void print_blcks(int fd){
int nbr_blcks;
nbr_blcks = get_nbr_blcks(fd);
if (nbr_blcks < 0) {
ERROR("get_nbr_blcks failed!\n");
}
if (nbr_blcks == 0) {
ERROR("no allocated blocks\n");
} else if (nbr_blcks == 1) {
printf("1 block\n\n");
} else {
printf("%d blocks\n\n", nbr_blcks);
}
for (int i = 0; i < nbr_blcks; i++) {
int phy_blck;
phy_blck = get_blck(fd, i);
if (phy_blck < 0) {
ERROR("get_blck failed!\n");
}
/* many [%d, 0] in my case... Where are they */
//if (!phys_block)
//continue;
printf("[%u, %u] ", i, phy_blck);
}
putchar('\n');
}
int main(int argc, char *argv[])
{
int fd;
UNLESS(argc == 2) {
printf("usage: %s file\n", argv[0]);
return 1;
}
fd = open(argv[1], O_RDONLY);
if (fd < 0) {
RETURN("open failed !\n");
}
print_blcks(fd);
return 0;
}

Create file recursive in C Linux

I want to create file test in this path /tmp/a1/a2/a3/a4/test
But all the directories (a1..a4) doesn't exist, How can I create this file in C at Linux OS?
You can use the mkdir function from sys/stat.h to create the directories as you need them. E.g.,
mkdir("/tmp/a1",0766);
However, you should check, via stat, whether or not the directories exist already.
Once you've created the directory structure, your file can be created with
open("/tmp/a1/a2/a3/a4/test",O_WRONLY|O_CREAT);
Obviously, you need to check the return values of all of these function calls.
Below is a complete function in C that achieves what you want.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
int create_file_with_parent_dirs (char pathname[])
{
for (char *p = pathname; (p = strchr(p ,'/')) != NULL; ++p) {
char c = p[1];
p[1] = '\0';
errno = 0;
if (mkdir(pathname, 0700) != 0 && errno != EEXIST) {
perror("mkdir");
return -1;
}
p[1] = c;
}
int fd = creat(pathname, 0600);
if (fd < 0)
perror("creat");
return fd;
}
int main (void)
{
char pathname[] = "/tmp/a1/a2/a3/a4/test";
create_file_with_parent_dirs(pathname);
}
Note that the array pointed to by pathname must be modifiable. Do not call the function with a string literal. Also beware that the file will be truncated to zero length if it already exists.
You can use this code. This program split the path and check whether the path exist or not if not create the path and create the final path as file.
#include <dirent.h>
#include <errno.h>
#include <bits/stdc++.h>
#include <iostream>
#include <sys/stat.h>
#include <sys/types.h>
#include <vector>
#include <fstream>
using namespace std;
int checkDir(char * path)
{
DIR* dir = opendir(path);
if (dir) {
/* Directory exists. */
closedir(dir);
return 0;
} else if (ENOENT == errno) {
/* Directory does not exist. */
return -1;
} else {
/* opendir() failed for some other reason. */
return -2;
}
}
int make_dir(char *path)
{
int ret = checkDir(path);
if( ret == -1)
{
if (mkdir(path, 0777) == -1)
{
cerr << "Error : " << strerror(errno) << endl;
return -1;
}
else
{
cout << "Directory created";
return 0;
}
}
return ret;
}
int main(int args, char **argv)
{
std::string strpath(argv[1]);
std::string delimeter = "/";
std::string substr1 = "";
int cnt = 0;
std::vector<string> strPaths;
std::string strbck = strpath;
for( int i = strpath.find(delimeter); i != std::string::npos; i = strpath.find(delimeter))
{
if(cnt > 0)
{
substr1 = strbck.substr(0, substr1.length() + i + 1);
strPaths.push_back(substr1);
}
strpath = strpath.substr(i +1,strpath.length());
cnt++;
}
strPaths.push_back(strbck);
std::string str;
for_each( strPaths.begin() ,strPaths.end() -1 , [](std::string str) {make_dir((char*)str.c_str());});
ofstream outfile;
std::ofstream file {strPaths[strPaths.size() -1].c_str() };
file << "hello"<< std::endl;
file.close();
return 0;
}

Linux FIFO chat program - Read/Write issue

Program Behavior:
Server:
Create FIFOs
Listen to Write from Client, Block until something is read.
if Something is read, prompt a message to Write to Client.
repeat...
Client:
Prompt Message to write to Server.
After write, Listen to Incoming messages.
If something is read, prompt a message to reply.
repeat...
================================ISSUES===================================
The Programs does communicate, however sometimes the call READ won't catch the WRITE call from the other program.
========================================================================
Server Code:
#include <fcntl.h>
#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#define SERVER_FIFO_FILE "/lab7_server_fifo"
#define CLIENT_FIFO_FILE "/lab7_client_fifo"
#define PERM 0666
int main(int argc, char** argv)
{
int s_read = 0;
int s_write = 0;
int exit = 0;
int listening = 1;
int writing = 0;
char* w_buffer = NULL;
size_t w_buffer_len = 0;
char r_buffer[BUFSIZ];
char* home = getenv("HOME");
char SERVER_FIFO[100];
char CLIENT_FIFO[100];
strcpy(SERVER_FIFO,home);
strcat(SERVER_FIFO, SERVER_FIFO_FILE);
strcpy(CLIENT_FIFO,home);
strcat(CLIENT_FIFO, CLIENT_FIFO_FILE);
mkfifo(SERVER_FIFO, PERM);
mkfifo(CLIENT_FIFO, PERM);
s_read = open(SERVER_FIFO, O_RDONLY | O_NONBLOCK);
s_write = open(CLIENT_FIFO, O_WRONLY | O_NONBLOCK);
while (!exit)
{
if (writing)
{
printf(">>>");
getline(&w_buffer,&w_buffer_len,stdin);
if (strcmp("exit",w_buffer)==0)
{
exit = 1;
}
else
{
write(s_write,w_buffer,w_buffer_len);
writing = 0;
listening = 1;
}
}
else
{
if (listening)
{
printf("listening...\n");
listening = 0;
}
read(s_read, r_buffer, BUFSIZ);
if (strlen(r_buffer) != 0)
{
if (strcmp(r_buffer,"exit") == 0)
{
exit = 1;
}
else
{
printf("%s",r_buffer);
writing = 1;
}
}
}
memset(r_buffer, 0, sizeof(r_buffer));
}
close(s_read);
close(s_write);
remove(SERVER_FIFO);
remove(CLIENT_FIFO);
return 0;
}
Client Code:
#include <fcntl.h>
#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#define SERVER_FIFO_FILE "/lab7_server_fifo"
#define CLIENT_FIFO_FILE "/lab7_client_fifo"
int main(int argc, char** argv)
{
int c_read = 0;
int c_write = 0;
int exit = 0;
int listening = 0;
int writing = 1;
char* w_buffer = NULL;
size_t w_buffer_len = 0;
char r_buffer[BUFSIZ];
char* home = getenv("HOME");
char SERVER_FIFO[100];
char CLIENT_FIFO[100];
strcpy(SERVER_FIFO,home);
strcat(SERVER_FIFO, SERVER_FIFO_FILE);
strcpy(CLIENT_FIFO,home);
strcat(CLIENT_FIFO, CLIENT_FIFO_FILE);
c_write = open(SERVER_FIFO, O_WRONLY | O_NONBLOCK);
c_read = open(CLIENT_FIFO, O_RDONLY | O_NONBLOCK);
while (!exit)
{
if (writing)
{
printf(">>>");
getline(&w_buffer,&w_buffer_len,stdin);
if (strcmp("exit",w_buffer)==0)
{
exit = 1;
}
else
{
write(c_write,w_buffer,w_buffer_len);
writing = 0;
listening = 1;
}
}
else
{
if (listening)
{
printf("listening...\n");
listening = 0;
}
read(c_read, r_buffer, BUFSIZ);
if (strlen(r_buffer) != 0)
{
printf("%s",r_buffer);
writing = 1;
}
}
memset(r_buffer, 0, sizeof(r_buffer));
}
close(c_read);
close(c_write);
return 0;
}
CURRENT OUTPUT:
server:
listening...
hello
>>>hi
listening...
client:
>>>hello
listening...
hi
>>how are you
listening...
ISSUE: Server Does Not Receive the message "how are you" from server.
client went into listening stage, causing the programs to stuck in a loop of listening.
SOLVED All i had to do was add the flag O_SYNC to write in server and client so it'll auto flush to disk causing it to be slower, that way read will have enough time to catch the call.

Error when changing the console output to file in C

I'm new to stack overflow so bear with me :)
I am trying to create a custom linux shell as a project.
Right now I want to make the default output going to a file instead of console when the user uses > symbol for example ls > filename.txt
But , the program crashes and a Bad address error pops yet it writes the command output to the file.
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
typedef char* string;
int main (int argc,char** argv) {
int error = 0;
int posIn=0; int posOut=0; int appendMark=0;
string Output,Input;
while (1) {
error=0;
char progName[255];
printf("\nmysh3 > ");
if(fgets(progName,500,stdin)==NULL){return 0 ;}
char dir[1024];
string params[40];
string pch=progName;
int i=0;
while ((pch = strtok (pch," \n")) != NULL){
params[i]=pch;
if (strcmp(pch,"<")==0) { posIn = i;params[i]=NULL;i--;} // < is skipped and we put only the name of the command on the params array
if (strcmp(pch,">")==0) { posOut = i;params[i]=NULL;i--;} //output
if (strcmp(pch,">>")==0) {appendMark=1;params[i]=NULL;i--;}
i++;
pch = NULL;
}
params[i]=NULL;
if(strlen(progName)>255){
printf("The commands can't be over 255 characters\n");
return 0;
}
if (posOut) {
int out = open(params[posOut], O_CREAT|O_TRUNC|O_WRONLY, 0777);
params[posOut]=NULL;
if (out < 0) {
error = 1;
fprintf(stderr,"open error: %d [%s]\n",errno,strerror(errno));
exit(1); }
int k = dup2(out,1);
if (k<0) {
error = 1;
perror("Cannot redirect output");
}
close(out);
}
pid_t proccess1,waitpid;
int status;
proccess1 = fork();
if (proccess1<0) {perror("Out of memory"); } //Monos tropos na apotyxei h fork einai na mhn yparxei mnhmh
else if (proccess1==0) {
execvp(params[0],params);
if (!error) {perror("Unknown command");}
}
else {
waitpid=wait(&status);
if (waitpid==-1) {perror("ERROR: A NEW ZOMBIE IS BORN 3:)");return 0;}
}
}
return 0; }

Video for Linux two poll returning POLLERR with errno EINVAL

I'v written a simple C shared object library which calls v4l2(Video for Linux two) API e.g. v4l2_open(). Then I'm trying to poll() on the returned device handle but it always return POLLERR in the revents. I tried different parameters with timeout but it does not help. Here is the complete code.
/*
* libwebcam.h
*
* Created on: 13.04.2016
* Author: max
*/
#ifndef LIBWEBCAM_H_
#define LIBWEBCAM_H_
#include <stdint.h>
struct webcam
{
int fd;
uint32_t width;
uint32_t height;
uint32_t sizeimage;
uint32_t bytesperline;
uint8_t *image_buffer;
void *priv_data;
};
int webcam_open(struct webcam *w);
int webcam_close(struct webcam *w);
int webcam_take_image(struct webcam *w);
int webcam_poll(struct webcam *w);
#endif /* LIBWEBCAM_H_ */
/*
* libwebcam.c
*
* Created on: 13.04.2016
* Author: max
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <linux/videodev2.h>
#include <libv4l2.h>
#include <poll.h>
#include "libwebcam.h"
int webcam_open(struct webcam *w)
{
struct v4l2_capability caps;
struct v4l2_format fmt;
int dev_index;
int dev;
char buffer[255];
for (dev_index = 0; dev_index < 64; dev_index++) {
memset(&buffer, 0, sizeof(buffer));
sprintf(buffer, "/dev/video%d", dev_index);
#ifdef DEBUG
printf("libwebcam: Probing %s\n", buffer);
#endif
dev = v4l2_open(buffer, O_RDWR | O_NONBLOCK, 0);
if (dev != -1) {
memset(&caps, 0, sizeof(caps));
if (v4l2_ioctl(dev, VIDIOC_QUERYCAP, &caps) == -1) {
return -1;
}
if (caps.capabilities & V4L2_CAP_VIDEO_CAPTURE) {
#ifdef DEBUG
printf("libwebcam: %s is video capture device\n", buffer);
#endif
memset(&fmt, 0, sizeof(fmt));
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if(v4l2_ioctl(dev, VIDIOC_G_FMT, &fmt) == -1) {
return -1;
}
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB24;
if(v4l2_ioctl(dev, VIDIOC_S_FMT, &fmt) == -1) {
return -1;
}
if(v4l2_ioctl(dev, VIDIOC_G_FMT, &fmt) == -1) {
return -1;
}
if(w)
{
w->fd = dev;
w->bytesperline = fmt.fmt.pix.bytesperline;
w->height = fmt.fmt.pix.height;
w->sizeimage = fmt.fmt.pix.sizeimage;
w->width = fmt.fmt.pix.width;
w->image_buffer = calloc(fmt.fmt.pix.sizeimage, sizeof(uint8_t));
if(w->image_buffer == NULL)
return -1;
w->priv_data = calloc(1, sizeof(struct pollfd));
if(w->priv_data == NULL)
return -1;
return 0;
}
else
{
errno = EINVAL;
return -1;
}
}
}
}
errno = ENODEV;
return -1;
}
int webcam_close(struct webcam *w)
{
if(w)
{
if(w->image_buffer != NULL){
free(w->image_buffer);
w->image_buffer = NULL;
}
if(w->priv_data != NULL) {
free(w->priv_data);
w->priv_data = NULL;
}
if(w->fd != -1)
if(v4l2_close(w->fd) == -1)
return -1;
return 0;
}
errno = EINVAL;
return -1;
}
int webcam_take_image(struct webcam *w)
{
if(w)
{
return v4l2_read(w->fd, w->image_buffer, w->sizeimage * sizeof(uint8_t));
}
errno = EINVAL;
return -1;
}
int webcam_poll(struct webcam *w)
{
if(w)
{
((struct pollfd *)w->priv_data)->events = POLLIN;
((struct pollfd *)w->priv_data)->revents = 0;
((struct pollfd *)w->priv_data)->fd = w->fd;
if(poll(((struct pollfd*)w->priv_data), 1, -1) == -1)
{
return -1;
}
if(((struct pollfd*)w->priv_data)->revents & POLLIN) {
#ifdef DEBUG
printf("libwebcam: Data is available...\n");
#endif
return 1;
}
if(((struct pollfd*)w->priv_data)->revents & POLLERR) {
#ifdef DEBUG
printf("libwebcam: Error in poll...\n");
#endif
return -1;
}
#ifdef DEBUG
printf("libwebcam: Timeout...\n");
#endif
return 0;
}
#ifdef DEBUG
printf("libwebcam: Struct not valid...\n");
#endif
errno = EINVAL;
return -1;
}
/*
* test.c
*
* Created on: 14.04.2016
* Author: max
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <libwebcam.h>
int main(int argc, char **argv)
{
struct webcam w;
int polled;
memset(&w, 0, sizeof(w));
if(webcam_open(&w) == -1)
{
perror("Unable to find webcam");
return EXIT_FAILURE;
}
while(1)
{
polled = webcam_poll(&w);
if(polled == -1)
{
perror("Error in poll");
return EXIT_FAILURE;
}
if(polled == 1)
{
webcam_take_image(&w);
}
}
if(webcam_close(&w) == -1)
{
perror("Unable to close webcam");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
Can anyone tell me what is going on in the code?
I tested your code, and on my system the poll call is returning 0. From the man page, "A value of 0 indicates that the call timed out and no file descriptors were ready." So you should test for 0 in addition to -1 and 1.
I don't know why it fills in revents with POLLERR, but I would only check the resulting revents field if poll returned 1.
Also, not all V4L2 devices support read(), so you should check that your device supports it by testingcaps.capabilities & V4L2_CAP_READWRITE. My laptop webcam where I tested this does not support read/write.
See this example program for reference.

Resources