shell with input & output on files in C - c

I'm having some trouble to run an interactive shell (/bin/bash, /bin/sh for ins) in the background with input and output redirected in files. I tried different things but it does not work.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void) {
char *argve[2];
argve[0]="/bin/sh";
argve[1]=NULL;
FILE *fichin, *fichout;
fichin=fopen("/root/C/fichin.temp", "w+");
fichout=fopen("/root/C/fichout.temp", "w+");
dup2(fileno(fichin), 0); //stdin
dup2(fileno(fichout), 1); //stdout
dup2(fileno(fichout), 2); //stderr
/*freopen("/root/C/fichin.temp", "r", stdin);
freopen("/root/C/fichout.temp", "w+", stdout);*/
system("/bin/sh");
//execve("/bin/sh", argve, NULL);
return 0;
}

you want this :
/* shell interactive */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc, char **argv) {
int file_input ;
int file_output;
int size_read = 0;
pid_t pid_command;
char _command[10];
char *read_one_char=NULL;
char command_separator;
int i=0;
/* open file input on READONLY */
/* open return file descriptor */
file_input = open("fichin.temp", O_RDONLY , 0666);
if (file_input <0 )
{
perror("can't open input file");
}
file_output = open("fichout.temp", O_CREAT | O_TRUNC | O_WRONLY , 0666) ;
if (file_output < 0)
{
perror("can't open output file");
}
read_one_char = malloc(sizeof(char));
if (read_one_char == NULL)
{
perror(" malloc failed ");
}
dup2(file_input, 0); //stdin
dup2(file_output, 1); //stdout
dup2(file_output, 2); //stderr
/*reading commands assuming that each line is a command
command 1
command 2
..
command n
you can change command_seperator
*/
command_separator = '\n';
do
{
size_read = read(file_input,(void*)read_one_char,1);
if (*read_one_char!=command_separator && size_read > 0)
{
_command[i]=*read_one_char;
i++;
}
else
{
_command[i--]='\0';
i=0;
write(1,"\n\t============ output for command ==========\n",45);
system(_command);
}
}while(size_read != 0);
return 0;
}
i wrote it quickly; try it and tell me if its that you want

Related

How do I fix "copy: Bad file descriptor" in my C program

Hello I'm working on a program that prints all the characters like a cat program by using the POSIX functions, the program has to get more than one file when it does it writes the characters of all files in the destination file.
For example;
mycat.exe x.txt y.txt z.txt dest.txt
means write all the characters from x.txt, y.txt and z.txt in order to the file destination dest.txt that it's created after we run the program.
If any file not exits the program will not exit it prints a report that
file not exists
If any error occur, you have to exit the program.
When I compile it it compiles without any error(I'm compiling it in Windows 10), but when i try to run it it shows an error.
This is how I compile it:
gcc -o mycp.exe mycp.c
This is how i run it:
mycp.exe x.txt y.txt z.txt dest.txt
This is the error:
copy: Bad file descriptor
This is the code inside the mycp.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#define BUFSIZE 1024
void exit_sys(const char* msg)
{
perror(msg);
exit(EXIT_FAILURE);
}
void exit_fail(const char* msg)
{
fprintf(stderr, "%s\n", msg);
exit(EXIT_FAILURE);
}
void remove_dest_file(int fd, char** argv, int i)
{
_close(fd);
unlink(argv[i]);
}
int copy_file(int fdd, int fds)
{
char buf[BUFSIZE];
int n;
while ((n = read(fds, buf, BUFSIZE)) > 0)
{
_write(fdd, buf, n);
}
if (n < 0)
{
return n;
}
return 0;
}
int main(int argc, char** argv)
{
int fds, fdd;
int n;
char buf[BUFSIZE];
int ch;
int flags;
int argcm1;
int i;
flags = _O_WRONLY | _O_CREAT;
if (argc < 2)
exit_fail("usage:mycp.exe file1.exe file2.exe file3.exe ... filen filedest.exe");
argcm1 = argc - 1;
if (!access(argv[argcm1], F_OK)) {
printf("The file %s exists. Do you want to overwrite?[y]\n", argv[argcm1]);
ch = getchar();
if (ch == 'y' || ch == 'Y')
flags |= _O_TRUNC;
else
exit(EXIT_SUCCESS);
}
if ((fdd = _open(argv[argcm1], flags, _S_IREAD | _S_IWRITE)) < 0)
{
exit_sys("open for destination");
}
for (i = 0; i < argcm1; ++i)
{
if (fds = _open(argv[i], _O_RDONLY) < 0)
{
remove_dest_file(fdd, argv, argcm1);
exit_sys("open");
}
if (copy_file(fds, fdd) < 0)
{
remove_dest_file(fdd, argv, argcm1);
exit_sys("copy");
}
_close(fds);
}
printf("Succes");
_close(fdd);
return 0;
}

Trying to write a buffer to a file, but keep getting segmentation faults and I can't figure out why

I have some code whose goal is to open/create a file, read in messages, and then write those messages to the opened/created file. Everything up to the writing to the file seems to work just fine. Here is my code.
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include "message-lib.h"
int usage( char name[] );
void * recv_log_msgs( void * arg );
sem_t mutex;
int log_fd;
void * recv_log_msgs( void * arg ){
sleep(1);
sem_wait(&mutex);
char buffer[1024];
int number_bytes_read;
FILE *fp = log_fd;
do{
number_bytes_read = read_msg(arg, buffer, 1024);
printf("in recv\n");
printf(buffer);
fwrite(&buffer, 1, sizeof(buffer)/sizeof(buffer[0]), fp);
}while(number_bytes_read > 0);
if(number_bytes_read == 0){
close_connection(arg);
}
sem_post(&mutex);
return NULL;
}
int usage( char name[] ){
printf( "Usage:\n" );
printf( "\t%s <log-file-name> <UDS path>\n", name );
return 1;
}
int main( int argc, char * argv[] )
{
int connection;
pthread_t tid;
if ( argc != 3 )
return usage( argv[0] );
log_fd = creat(argv[1], S_IRUSR | S_IWUSR);
if(log_fd == -1){
perror(argv[1]);
return 1;
}
int listener = permit_connections(argv[2]);
if(listener == -1){
return -1;
}
sem_init(&mutex, 0, 1);
do{
connection = accept_next_connection(listener);
if(connection == -1){
return -1;
}
pthread_create(&tid, NULL, recv_log_msgs, connection);
}while(connection != -1);
close_connection(connection);
close_listener(listener);
fclose(log_fd);
return 0;
}
permit_connections, accept_next_connection, and read_msg are all from a library that was provided to me. I'm guessing my problem is in recv_log_msgs, but I'm not sure what it would be.
Here's the root of your problem:
FILE *fp = log_fd;
log_fd is a file descriptor, fp is a FILE pointer.
The two are not interchangeable, and what you need to do is use the write(...) system call for writing to the log file, or create the log file in some other fashion to get a hold of a FILEpointer to it.
FILE *fp = fopen(argv[1], "w"), might do the trick.
EDIT: As #DarrenSmith pointed out to me in the comments, you can also use
fp = fdopen(log_fd, "w")
and keep the rest of the code as is.

Using of a system call in c

I would like to create a program name patch witch recives a FILENAME and a string.In the file there is the string 'allis'.I need to replace each time the string 'allis' appears in the text with the string I recieved as an input.
I need to use only system call and not the standat libary.
This is an example code on how the code should look like(this just example of the structure it is not the mission, the code writes "allis" word instead of "hello world"):
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc , char* argv[], char* envp[])
{
char buf[6];
int fd = open(argv[1],O_WRONLY,0777);
if (fd == -1)
exit(1);
write(fd,"hello world!\n",13);
close(fd);
fd = open(argv[1], O_RDONLY);
if (fd == -1)
exit(1);
read(fd,buf,5);
buf[5]='\0';
close(fd);
fd = open(argv[1],O_WRONLY,0777);
if (fd == -1)
exit(1);
write(fd,"allis",5);
close(fd);
return 0;
}
I need to use the system call lseek but I dont know how I should use it because I dont know where in the text 'allis' is located and what happens if the string i get as an input is bigger than 'allis' I need to move all the text to the right or something because I will override other text.
EDIT:
I wrote a code which check char by char (instead of allis its shira and it replace it with sergay)It actually worked. and than I tried to change the code to work with argv[1] and argv[2] as needed and it didnt work I revert back to the code that originally worked for me and its just doesnt work now!! The problem is that the buf doesnt take 5 character (only 1)
and believe me or not it worked before.
The code :
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#define SYS_WRITE 1
#define STDOUT 1
extern int system_call();
int main(int argc , char* argv[], char* envp[])
{
char buf[5];
int index1=0,index2=0;//the index of the file
int fd1;
int fd = open("file.txt", O_RDONLY);
if (fd == -1)
return 1;
fd1 = open("copytext.txt",O_WRONLY,0777);
if (fd1 == -1)
return 1;
int i =0;
while (fd!=-1){//while there is still info to read
printf("enter the %d loop\n",i);
i++;
if(read(fd,buf,5) == 0 ) break;//read 5 chars from the file //buf[5]='\0';//!! not sure about this
printf("the buffer is: %s\n",buf);
if ((buf[0]=='s') && (buf[1]=='h') && (buf[2]=='i') && (buf[3]=='r') && (buf[4]=='a'))// if (strcmp(buf,"shira")==0)//if we found shira
{
write(fd1,"sergay",6);//replace shira
index2 = index2 + 6;
if(lseek(fd1,index2,SEEK_SET) < 0) break;
index1 = index1 + 5;//size of shira
if(lseek(fd,index1,SEEK_SET) < 0) break;
}
else {//we did not find shira;
write(fd1,buf,1);//write only one
index2++;
if(lseek(fd1,index2,SEEK_SET) < 0) break;
index1++;
if(lseek(fd,index1,SEEK_SET) < 0) break;
}
}
printf("get out of the loop\n");
char buffer[index2];
fd1 = open("copytext.txt", O_RDONLY);
if (fd1 == -1)
return 1;
if(lseek(fd1,0,SEEK_SET) < 0) return 1;
if(read(fd1,buffer,index2) == 0 ) return 1;
fd = open("file.txt",O_WRONLY,0777);
if (fd == -1)
return 1;
if(lseek(fd,0,SEEK_SET) < 0) return 1;
write(fd,buffer,index2);
close(fd);
close(fd1);
return 0;
}

Writing to a Named Pipe not showing the full content of a string

I am trying to read data from 2 named pipe and write it to another named pipe concatenating the content from 2 inputs. But why my output only shows the string from first input?
Here is my code:
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#define MAX_REC_SIZE 1024
int open_fifo(char *name, int mode) {
mode = mode == O_RDONLY ? (O_RDONLY | O_NONBLOCK): mode;
int fd;
if (access(name, F_OK) == -1) {
if(mkfifo(name, 0777) != 0) {
fprintf(stderr, "Could not create fifo %s\n", name);
exit(EXIT_FAILURE);
}
}
fd = open(name, mode);;
return fd;
}
void read_fifo(int fd, char *out_r) {
memset (out_r, '\0', MAX_REC_SIZE);
do {
if(read(fd, out_r, MAX_REC_SIZE) > 0) {
out_r = strtok(out_r, "\n");
return;
}
} while (1);
}
void write_fifo(int fd, char *out_w) {
write(fd, out_w, sizeof(out_w));
}
int main()
{
int pipe_fd[3], i;
char *pipe_nm[] = {"./in_pipe_1", "./in_pipe_2", "./out_pipe_1"};
int read_mode = O_RDONLY;
int write_mode = O_WRONLY;
char out[MAX_REC_SIZE];
char out_store[MAX_REC_SIZE];
for(i=0; i<3; i++) {
pipe_fd[i] = open_fifo(pipe_nm[i], i == 2 ? write_mode : read_mode);
}
read_fifo(pipe_fd[0], out);
strcpy(out_store, out);
read_fifo(pipe_fd[1], out);
strcat(out_store, out);
strcat(out_store, "\n");
write_fifo(pipe_fd[2], out_store);
return 0;
}
A suspicious part of your code is:
write(fd, out_w, sizeof(out_w))
Here, out_w is not an array, and the sizeof operator would yield the size of a char * pointer, not the length of the block.
You should pass the length of out_store to your write_fifo function.
Also, I'm not really sure what your intent is when using the strtok function.

Error validating the contents of a file using regex in C

I am having a problem with the below code validating a file using regex. My file must only contain letters or numbers. My regular expression is:
#define to_find "^[a-zA-Z0-9]+$"
which is located in my main.h file. The below code is in my main.c
#include <ctype.h>
#include <errno.h>
#include <regex.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include "main.h"
int main(int argc, char * argv[])
{
int ret_val;
regex_t regex;
FILE *fp;
char line[1024];
if (regcomp(&regex, to_find, REG_EXTENDED) != 0)
{
fprintf(stderr, "Failed to compile regex '%s'\n", to_find);
return EXIT_FAILURE;
}
if (argc > 2)
{
printf("Usage: tree OR tree [filename]\n");
return EXIT_FAILURE;
}
else if (argc == 2)
{
fp = fopen(strcat(argv[1],".dat"), "r");
printf("file opened\n");
while ((fgets(line, 1024, fp)) != NULL)
{
line[strlen(line) - 1] = '\0';
if ((ret_val = regexec(&regex, line, 0, NULL, 0)) != 0);
{
printf("Error: %s\n", line);
return EXIT_FAILURE;
}
}
fclose(fp);
printf("File closed\n");
}
return 0;
}
My file I am reading is called names.dat and contains:
int
char
[
double
What is happening is it is kicking out at the very first line which it should kick out at the 3rd line. I am sure this is pretty simple to solve but it seems I have not figured it out. I would appreciate any help. Also, how do I deal with the
\n
character in the file? this file will have several lines. Thanks in advance.
You have some small errors but the one that cause the error is:
// Do you see this sweet little semicolon :P ----------------+
if ((ret_val = regexec(&regex, line, 0, NULL, 0)) != 0); // <+
{
printf("Error: %s\n", line);
return EXIT_FAILURE;
}
beside this line:
fp = fopen(strcat(argv[1],".dat"), "r");
You cannot add to argv, you need to create a new buffer to hold the data, create a buffer with PATH_MAX size add append the path to it. Here an improved version:
#include <ctype.h>
#include <errno.h>
#include <regex.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <limits.h>
#define to_find "^[a-zA-Z0-9]+$"
int main(int argc, char * argv[])
{
int ret_val;
regex_t regex;
FILE *fp;
char file[PATH_MAX];
char line[1024];
if (regcomp(&regex, to_find, REG_EXTENDED) != 0)
{
fprintf(stderr, "Failed to compile regex '%s'\n", to_find);
return EXIT_FAILURE;
}
if (argc > 2)
{
printf("Usage: tree OR tree [filename]\n");
return EXIT_FAILURE;
}
else if (argc == 2)
{
sprintf(file, "%s.dat", argv[1]);
fp = fopen(file, "r");
if( fp == NULL ) {
perror("Error");
return -1;
}
printf("file opened\n");
while (fscanf(fp, "%1023s", line) > 0)
{
if ((ret_val = regexec(&regex, line, 0, NULL, 0)) != 0)
{
printf("Not match: %s\n", line);
//return EXIT_FAILURE;
} else {
printf("Match: %s\n", line);
}
}
regfree(&regex);
fclose(fp);
printf("File closed\n");
}
return 0;
}
See the diff: http://www.diffchecker.com/8itbz5dy
test:
$ gcc -Wall sample.c
$
$ cat name.dat
int
char
[
double
$ ./a.out name
file opened
Match: int
Match: char
Not match: [
Match: double
File closed
$

Resources