my code is pasted below.
I'm trying to use dup2 to redirect my output to file.
if I use it to redirect it works fine (if I remove the comments), output in file and not on stdout. ex: ls > test , results in ls outputting to test.
the problem is that ls, without the > doesn't output anything. If I leave the comments ls outputs just as it should, albeit with no ability to redirect.
redirect[0] is either < or > or nothing
redirect[1] is the path for the file to redirect to
command is is an array of cstrings with the pices of the command commands is as well
example output
with code commented
xxxxx#myshell:/home/majors/kingacev/ubuntumap/cop4610/proj1> ls
a.out myshell.c myshell.c~
xxxxx#myshell:/home/majors/kingacev/ubuntumap/cop4610/proj1>
with code uncommented
xxxxx#myshell:/home/majors/kingacev/ubuntumap/cop4610/proj1> ls
xxxxx#myshell:/home/majors/kingacev/ubuntumap/cop4610/proj1>
/*
if (!strcmp(redirect[0],">")){
if ((fd = open(redirect[1], O_RDWR | O_CREAT)) != -1)
dup2(fd, STDOUT_FILENO);
close(fd);
}
*/
if (command[0][0] == '/'){
int c = execv(command[0], commands);
if (c != 0){
printf("ERROR: command does not exist at path specified\n");
exit(0);
}
}
else if (!execv(path, commands)){
exit(0);
}
This code works, redirecting to file.out:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
int main(void)
{
int fd;
char *redirect[] = { ">", "file.out" };
char *command[] = { "/bin/ls", "-l", 0 };
if (!strcmp(redirect[0], ">"))
{
if ((fd = open(redirect[1], O_WRONLY | O_CREAT, 0644)) != -1)
{
fprintf(stderr, "Dupping stdout to %s\n", redirect[1]);
dup2(fd, STDOUT_FILENO);
close(fd);
}
}
if (command[0][0] == '/')
{
execv(command[0], command);
fprintf(stderr, "ERROR: command %s does not exist at path specified\n", command[0]);
return(1);
}
else
{
fprintf(stderr, "ERROR: not handling relative names like %s\n", command[0]);
return(1);
}
return 0;
}
This code works too, not redirecting to file:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
int main(void)
{
int fd;
char *redirect[] = { "<", "file.in" };
char *command[] = { "/bin/ls", "-l", 0 };
if (!strcmp(redirect[0], ">"))
{
if ((fd = open(redirect[1], O_WRONLY | O_CREAT, 0644)) != -1)
{
fprintf(stderr, "Dupping stdout to %s\n", redirect[1]);
dup2(fd, STDOUT_FILENO);
close(fd);
}
}
if (command[0][0] == '/')
{
execv(command[0], command);
fprintf(stderr, "ERROR: command %s does not exist at path specified\n", command[0]);
return(1);
}
else
{
fprintf(stderr, "ERROR: not handling relative names like %s\n", command[0]);
return(1);
}
return 0;
}
Note that it sets up the command array and uses execv(command[0], command); — this is the recommended way of doing business. Your code appears to have a variable commands with presumably the arguments to the program; you also appear to have a variable path with presumably the path name of the program. Since we can't see what's in those, it is hard to know what they contain and where there might be problems. Note the explicit null pointer (0) at the end of the command array. That is crucial. Note too that the error messages identify what was failing. There are few things more frustrating than a program that says "it went wrong" without identifying what 'it' is.
Related
So I want to test if a file given is regular or not.
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
int main(int argc, char **argv)
{
// Input check.
if (argc != 2) {
fprintf(stdout,"Format: %s <filename.txt>\n", argv[0]);
return -1;
}
// Make sure the file is a regular file.
int fd;
if ((fd = open(argv[1], O_RDONLY) == -1)) {
fprintf(stdout, "%s", strerror(errno));
return -1;
}
struct stat st;
if ((fstat(fd, &st) == -1)) {
fprintf(stdout, "%s\n", strerror(errno));
return -1;
}
if (!(S_ISREG(st.st_mode))) {
fprintf(stdout, "Error, invalid file\n");
return -1;
}
close(fd);
return 0;
}
I run: .\a in.txt
I don't know what exactly is going on, but when I'm trying to test if the file is regular (last if statement), it fails. I tested to see if fstat fails, but it doesn't.
Here's the problem:
if ((fd = open(argv[1], O_RDONLY) == -1)) {
The equality operator == has higher precedence than the assignment operator =. So the above parses as:
if (fd = (open(argv[1], O_RDONLY) == -1)) {
Which assigns to fd the result of the comparison which will be either 0 or 1. These values both happen to be valid open file descriptors for stdin and stdout so the fstat call is successful and gets you the status of one of these streams.
You'll need to adjust the parenthesis to do the assignment first:
if ((fd = open(argv[1], O_RDONLY)) == -1) {
Also, it looks like you have other if statements that have a redundant set of parenthesis that you can remove. You want to avoid this because those extra parenthesis can silence warnings about exactly what you did.
My intention was to open two files, where the second one would be brand new, with the same permissions as the first file. So to test my code I changed the first file permissions to "777". Then I proceeded to run my program. And to my surprise, the permission of the newborn file2 were wrong! They where set to 755. Even weirder is when I set the first file to "111" and tried again, the result now was "1204".
Can someone explain to me this weird behavior?
Here's my code
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
int main(int argc, char *args[]) {
struct stat stats;
int fd1, fd2;
fd1 = open("testfile.txt", O_RDONLY);
/* Error check*/
if (fd1 == -1) {
/* Error handling */
perror("Opening");
printf("Unable to open file: %s\n", "testfile.txt");
printf("ERROR: %s\n", strerror(errno));
return 1;
}
if(fstat(fd1, &stats) == -1)
{
printf("Error while getting stats: %s\n", strerror(errno));
exit(-1);
}
//Receives the output file as a main argument . . .
if (argc > 1)
{
//(stats.st_mode = Gets the mask of the first file)
fd2 = open(args[1], O_WRONLY|O_CREAT, stats.st_mode);
/* Error check*/
if (fd2 == -1) {
/* Error handling */
perror("Opening");
printf("Unable to open file: %s\n",args[1]);
printf("ERROR: %s\n", strerror(errno));
return 1;
}
}
//. . . if it doesn't it creates a standard one warning you about it
else
{
fd2 = open("Nope.txt", O_WRONLY|O_CREAT, stats.st_mode);
/* Error check*/
if (fd2 == -1) {
/* Error handling */
perror("Opening");
printf("Unable to open file: %s\n",args[1]);
printf("ERROR: %s\n", strerror(errno));
return 1;
}
printf("Standard file created\n");
}
close(fd1);
close(fd2);
return 0;
}
I tried to make it as tidy as I could :)
From open(2) man page on the part about O_CREATE:
The effective mode is modified by the process's umask in the usual way: in the absence of a default ACL, the mode of the created file is (mode & ~umask).
If you type umask in bash you can see what value is used and which bits get cleared from the mode you provide.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
char *buffer = malloc(1024);
FILE* f = popen("ls", "r");
int byteReads = fread(buffer, 1, 1024, f);
fclose(f);
printf("%s\n", buffer);
return 0;
}
Ther are 2 folders ./parent/folder1 and ./parent/folder2 . ./main is in folder1, and I want it to execute ls in folder2 and get the result.
Not something that is specific to "ls", but that works for any commands in general.
How can I do it using popen()? Or do I have to use another command?
You could use popen as you use it in your question. You could pass the cmd you want to execute as argument to the program call, e.g. if your program is named myexecute the command line call would look like this:
myexecute folder2 'ls -l'
or
myexecute 'another folder' 'ls'
Please note the single quotes to get an argument if spaces are included in the argument.
With chdir you can change the current working directory. The output of the command can be read in a loop and output to the stdout.
Finally, with pclose, you would wait for the associated process to finish and it would even return the exit status of the executed command, just in case you are interested.
You code slightly modified could look like this:
#include <stdio.h>
#include <stdlib.h>
#include <libgen.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
if(argc != 3) {
fprintf(stderr, "usage: %s '<dir>' '<cmd>'\n", basename(argv[0]));
return EXIT_FAILURE;
}
if(chdir(argv[1]) != 0) {
perror(argv[1]);
return EXIT_FAILURE;
}
FILE *f = popen(argv[2], "r");
if (!f) {
perror("popen failed");
return EXIT_FAILURE;
}
char buf[1024];
while (fgets(buf, sizeof(buf), f)) {
printf("%s", buf);
}
if (pclose(f) != 0) {
perror("pclose failed");
}
return EXIT_SUCCESS;
}
So I am working on a simple program in C but have been stuck on the copying portion. The program takes two filenames on the command line as arguments and copies the first to the second by using system calls. If the second file exists it asks the user if they want to overwrite, if not it creates it. However, my program when the user choices overwrite goes on infinitely.
Here is my code:
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
int main(int argc, char *argv[])
{
int fd1, fd2;
char buffer[1024];
long int n;
char c;
int num;
if (argc != 3) {
printf("%d\n",argc);
printf("Error, you need to give 2 arguments. Such that [File to copy] [File to create].\n");
exit(1);
}
if (access(argv[1], F_OK) < 0) {
printf("File %s either does not exist or cannot be accessed.\n", argv[1]);
exit(1);
} else {
printf("file %s exists\n", argv[1]);
}
if (access(argv[2], F_OK) < 0) {
printf("File %s does not exist, but one will be created.\n", argv[1]);
fd2=open(argv[2],O_CREAT|O_WRONLY|O_TRUNC, 0700);
} else {
printf("file %s exists\n", argv[2]);
printf("Would you like to overwrite %s? (Type 1 for yes or 0 for no)\n", argv[2]);
scanf("%d%c", &num, &c); // use c to capture \n
if (num == 1) {
fd2=open(argv[2],O_CREAT|O_WRONLY|O_TRUNC, 0700);
} else {
if (num == 0) {
printf("Ok, the file will not be copied and the program will now exit.\n");
exit(1);
} else {
printf("I do not recognize this response, program will now be terminated.\n");
}
}
}
printf("step\n");
while ((n1 = read(fd1, buffer, 1024)) > 0) {
printf("step\n");
if(write(fd2, buffer, n1) != n1){
printf("step\n");
perror("Error writing file.");
printf("step\n");
exit(3);
}
printf("stepss\n");
}
close(fd1);
close(fd2);
}
The printf("step") is for debugging, but it only prints one. Meaning the program freezes up by the while loop. I can use stat(), open(), read(), write(), close(), and access(). Any ideas on what is wrong or how it can be done better would be appreciated!
Any ideas on what is wrong
Your fd1 never been assigned, so read(fd1, ...) returns an error.
Check return value of read and printf("%m\n") will print the details.
$ ./a.out a b
file a exists
file b exists
Would you like to overwrite b? (Type 1 for yes or 0 for no)
1
step
Bad file descriptor
I'm just doing this C program, which acts like a terminal and I've implemented the "dir" command, but I also want to implement the redirection ">" operator, so I can redirect everything to a file. I made a C program that waits for my input, and I want that input to be sent to the .txt file.
This is the output.c, which waits for an user input.
#include <stdio.h>
#define SIZE 500
int main(int argc, char *argv[]){
char text[SIZE];
scanf("%s", text);
return 0;
}
And this is the code that should redirect my input to my file.
UPDATE:
int rv;
pid_t pid;
int commpipe[2];
if(argc > 2){
char filename[] = "output.txt";
int old_prn_han, new_prn_han;
old_prn_han = dup(fileno(stdout));
strcpy(filename, argv[2]);
if((new_prn_han = open(filename, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR)) == -1){
fprintf(stderr, "Unable to create/open file '%s'\n", filename);
return 1;
}
dup2(new_prn_han, fileno(stdout));
if((pid=fork()) == -1){
fprintf(stderr, "Error forking new process!\n");
exit(2);
}
if(pid){
//Parent process
close(commpipe[0]);
setvbuf(stdout,(char*)NULL,_IONBF,0);
sleep(2);
wait(&rv);
fprintf(stderr, "Child exited with a %d value\n", rv);
}else{
//Child process
dup2(commpipe[0],0);
close(commpipe[1]);
if(execl("output", "output", NULL) == -1){
fprintf(stderr, "Error executing new process!\n");
exit(3);
}
}
close(fileno(stdout));
dup2(old_prn_han, fileno(stdout));
}
The problem is, that it seems my output program, which awaits user input does not execute. Can you guys help me out ?
UPDATE
I've updated my code. Now the new process is executing but when i type something in like 'name' at stdin, my file contains some weird symbols and they do not appear until I exit my main program. Why is that ?