c open() function isn't working - c

so i'm trying to write this function that gets an argument that tells it whether to display the input to the screen or to redirect it to some file.
I'm doing it by redirecting the stdout part.
For some reason, the flags in the open() function are not recognized, even though i did #include as required.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#define TRUE 1
#define FALSE 0
void writer(char* fileName);
void writerEmpty();
void writer(char* fileName)
{
char buffer[64];
int size = 64;
int fd;
read(0, buffer, size);
if (!strcmp("std", fileName))
{
close(1);
fd = open(fileName, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
}
write(1, buffer, size);
}
The visual studio doesn't recognize the S_IRUSR and S_IWUSR flags, and when I don't use them at all, open() returns -1 (error).
Help? someone? :)

Related

Using named pipes in c

i have this simple program that passes a value through a named pipe from child to parent process:
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/stat.h>
#include <semaphore.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <stdio.h>
int main()
{
char * myfifo = "/home/tmp/myfifo";
mkfifo(myfifo, 0666);
int fd,rec;
pid_t c=fork();
if(c==0){
fd = open(myfifo, O_WRONLY);
rec=100;
write(fd, rec, sizeof(rec));
}
if(c>0){
sleep(1);
fd = open(myfifo, O_RDONLY);
read(fd, rec, sizeof(rec));
printf("%d\n",fd);
printf("%d\n",rec);
}
}
This program prints fd=-1 and instead of rec being 100 it prints rec's address.I also tried putting &rec in read and write but it did not solve anything.What am i doing wrong?
There's an issue with this line:
write(fd, rec, sizeof(rec));
This is the prototype of write():
ssize_t write(int fd, const void *buf, size_t count);
That means that you're reading from the memory location stored in rec, not the content of rec.
The same thing applies for read(). You need to pass a pointer to rec instead of rec itself.
Also, always make sure to close files after you open and perform I/O on them.
Here's a correct copy of your code:
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/stat.h>
#include <semaphore.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <stdio.h>
int main()
{
const char *myfifo = "/home/tmp/myfifo";
mkfifo(myfifo, 0666);
int fd, rec;
pid_t c = fork();
if(c == 0) {
fd = open(myfifo, O_WRONLY);
rec = 100;
write(fd, &rec, sizeof(rec));
close(fd);
}
if(c > 0) {
sleep(1);
fd = open(myfifo, O_RDONLY);
read(fd, &rec, sizeof(rec));
printf("%d\n", fd);
printf("%d\n", rec);
close(fd);
}
}
Of course, always make sure you have the proper permissions to create, read, and write files in that directory. Also, make sure the directory /home/tmp exists.

Posix semaphores with FIFO not working properly

i've written a small client-server demo program that should implement a simple comunication between two process using a FIFO and two semaphores.
The problem is that even if i've put a sem_wait before the client reads the fifo, he dosen't wait for the server to write on the fifo so the client reads the old value ("2" instead of "pippo"). I really can't find where the mistake is. Following the code of Server and Client.
I hope someone could help me.
Client:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <signal.h>
#include <stdarg.h>
#include <fcntl.h>
#define FIFO_FILE "MIA_FIFO"
FILE * fiforw ;
int fifo_write ( char * buf );
int fifo_read ( char * buf );
sem_t *pizz;
sem_t *cli;
int main(void){
fiforw=fopen ( FIFO_FILE, "rw");
pizz=sem_open("pizz", O_EXCL, S_IRUSR | S_IWUSR, 0);
cli=sem_open("cli", O_EXCL, S_IRUSR | S_IWUSR, 0);
char buff[20];
int pieces=10;;
sprintf(buff,"%d",pieces);
fifo_write(buff);
sem_post(cli);
sem_wait(pizz);
fifo_read(buff);
printf("I've read %s \n",buff); //here he should read "pippo" instead of "2"
fclose ( fiforw );
}
int fifo_write ( char * buf ) {
fputs ( buf, fiforw );
return 1;
}
int fifo_read ( char * buf ) {
fgets( buf, sizeof(buf)+1, fiforw);
return 1;
}
Server:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <signal.h>
#include <stdarg.h>
#include <fcntl.h>
#define FIFO_FILE "MIA_FIFO"
int fifo_write ( char * buf );
int fifo_read ( char * buf );
sem_t *pizz;
sem_t *cli;
FILE * fiforw;
int main(void){
mkfifo(FIFO_FILE,0666);
fiforw = fopen ( FIFO_FILE, "rw");
char buff[20];
char temp[]="pippo";
pizz = sem_open("pizz", O_CREAT, S_IRUSR | S_IWUSR, 0);
cli= sem_open("cli", O_CREAT, S_IRUSR | S_IWUSR, 0);
//while(1) {
sem_wait(cli);
fifo_read(buff);
printf("the value is %s \n",buff);
sprintf(buff,"%s",temp);
printf("i will write pippo on the fifo \n");
fifo_write(buff);
sem_post(pizz);
fclose ( fiforw );
//}
}
int fifo_write ( char * buf ) {
fputs ( buf, fiforw );
return 1;
}
int fifo_read ( char * buf ) {
fgets( buf, sizeof(buf)+1, fiforw);
return 1;
}
Running server first then client is required. If that is the case, it can be helpful to check return codes from system calls.

infinite loop in shared memory

Within a Ubuntu virtal machine, I have created two c programs called "server" and "client". When I run server with an input (some integer) and then run client afterwards, client will output the integer that I gave to server. This is working with shared memory. My problem is, after client receives the info, it sets a variable to "CONSUMED", and server has a loop that waits for that to happen, but it never seems to work correctly. This all works if I remove the loop altogether, but I need it in there to be able to ensure that client receives the integer and I don't just continue without it happening.
Here is my code for server.c:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/types.h>
#include "shm.h"
int main(int argc, char* argv[]){
int retVal = 0;
ShmData *addr;
if(argc != 2){
printf("please enter 1 argument.\n");
return 0;
}
int fd = shm_open("shm.h", O_CREAT | O_RDWR , 0666);
if(fd == -1){
printf("!!!error with shm_open.\n");
}
if(ftruncate(fd, sizeof(ShmData)) == -1){
printf("!!!error with ftruncate.\n");
}
addr = mmap(0, sizeof(ShmData), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if(addr == MAP_FAILED){
printf("!!!error with mmap.\n");
}
addr->status = INVALID;
addr->data = atoi(argv[1]);
addr->status = VALID;
printf("[Server]: Server data Valid... waiting for client\n");
while(addr->status != CONSUMED){
sleep(1); //THIS LOOP NEVER EXITS
}
printf("[Server]: Server Data consumed!\n");
munmap(addr, 0);
if(close(fd) == -1){
printf("!!!error with close.\n");
}
shm_unlink("smh.h");
printf("[Server]: Server exiting...\n\n\n");
return(retVal);
}
Here is my code for client.c:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/types.h>
#include "shm.h"
int main(int argc, char* argv[]){
int retVal = 0;
int fd = shm_open("shm.h", O_CREAT | O_RDWR , 0666);
if(fd == -1){
printf("!!!error with shm_open.\n");
}
ShmData *addr;
addr = mmap(0, sizeof(ShmData), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
printf("[Client]: Waiting for valid data ...\n");
while(addr->status != VALID){
sleep(1);
}
printf("[Client]: Received %d\n", addr->data);
addr->status = CONSUMED;
munmap(addr, 0);
printf("[Client]: Client exiting...\n");
return(retVal);
}
And here is the shm.h file:
enum StatusEnum{INVALID, VALID, CONSUMED};
typedef struct{
enum StatusEnum status;
int data;
}ShmData;
I've been banging my head against the computer screen for a long time but I still don't see anything wrong with my code. How can I get this loop to succeed and exit?

why execl overwrite the file

#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <fcntl.h> // open
#include <stdio.h>
int main() {
close(1); // close standard out
open("log.txt", O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR);
puts("Captain's log");
chdir("/usr/include");
execl("/bin/ls", "ls", ".", (char *)NULL);
perror("exec failed");
return 0;
}
When I check log.txt, I could not find "Captain's log". I supposed it runs before execl, thus it should be there!
You are writing it to the standard output, why would you expect it to be in the file?
If you want to redirect stdout just use freopen()
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
int main()
{
FILE *file;
file = freopen("log.txt", "w", stdout);
if (file == NULL)
return -1;
printf("Captain's log");
chdir("/usr/include");
if (execl("/bin/ls", "ls", ".", NULL) != 0)
perror("exec failed");
fclose(file);
return 0;
}

sending a string between two programs using named pipes

I am trying to send a string to another program
but i am having problem using O_WRONLY | O_NONBLOCK,
if i replace that with O_RDWR the program works fine
but i wanted to know if there is a way to send/read the
string without using O_RDWR. Right now it returns a
empty string for some reason.
Writer:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#define MAX_LINE 1024
int main(int argc, char **argv)
{
char line[MAX_LINE];
int pipe;
printf("Enter line: \n");
fgets(line, MAX_LINE, stdin);
pipe = open("link1", O_WRONLY | O_NONBLOCK);
write(pipe, line, strlen(line));
system("./run"); //executing the reader
close(pipe);
return 0;
}
reader:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#define MAX_BUF 1024
int main(int argc, char **argv)
{
int fd;
char * link1 = "link1";
char buf[MAX_BUF];
fd = open(link1, O_RDONLY | O_NONBLOCK);
read(fd, buf, MAX_BUF);
printf("%s\n", buf);
close(fd);
return 0;
}
Are you running the reader first? If no process has the FIFO open for reading when the writer attempts to open it write only, then the open will fail.
From the Open Group man page:
When opening a FIFO with O_RDONLY or O_WRONLY set: If O_NONBLOCK is set:
An open() for reading only will return without delay. An open() for writing only will return an error if no process currently has the file open for reading.

Resources