Using a system call to execute "which" command in C - c

I'm trying to get the pathname for specific user input. For example, if the user inputs ls | wc I want to create two strings the first one being a which(ls), and the second one being a which(wc) so I have the pathname. I am doing this inside a C program and my code looks like the following.
/*This is a basic example of what i'm trying to do*/
char* temp;
printf("Enter a command\n");
/* assume user enters ls */
scanf("%s", temp);
char* path = system(which temp);
printf("Testing proper output: %s\n", path);
/*I should be seeing "/bin/ls" but the system call doesn't work properly*/
Can anyone point me in the right direction?

You are using an uninitialized pointer. But even if you had initialized it properly, it still wouldn't work because system() doesn't return the output of the command it executes.
You want to use popen() to do that.
Here's an example (untested):
if (fgets(cmd, sizeof cmd, stdin)) {
char cmd[512];
cmd[strcspn(cmd, "\n")] = 0; // in case there's a trailing newline
char which_cmd[1024];
snprintf(which_cmd, sizeof which_cmd, "which %s", cmd);
char out[1024];
FILE *fp = popen(which_cmd);
if (fp && fgets(out, sizeof out, fp)) {
printf("output: %s\n", out);
}
}

Related

get file path from stdin in C

I am trying to pass a file to my program however it always gives error, cannot open file.
My command is: (I am on desktop path, I am using ubuntu)
./out < /usr/share/dict/words > out.txt 2> out2.txt
Output files are created but file input seems empty. I am getting file path as:
char *infile;
scanf("%s", infile);
printf("file: %s\n", infile);
I also tried:
fscanf(stdin, "%s", infile);
Nothing changed. Also, I have to take input as shown above, I know < means stdin but I cannot read its content somehow.
This is file opening part and error message:
file = fopen(infile, "r");
if (file == 0) {
fprintf(stderr, "File failed\n");
return 1;
}
There seem to be some confusion in your approach:
you redirect input to your program from a text file containing words, the classic /usr/share/dict/words file. This file is the input to your program, you can read the contents with getchar(), scanf(), fgets() and other stream input functions, but the name of the file is not available to your program, nor do you need to fopen this file to read its contents.
scanf("%s", buf) is an unsafe way to read a word from stdin. You must pass a pointer to a char array, not an uninitialized pointer as you do in the fragment posted. scanf() will write to the memory pointed to by this pointer, so an uninitialized pointer will cause undefined behavior, probably a crash.
To use scanf() safely, you must provide the maximum number of characters to store into the destination array, otherwise a long enough word in the inoput file will cause scanf() to write beyond the end of the array, causing undefined behavior as well. Here is an example of this:
// filtering 4 letter words:
char buf[100];
while (scanf("%99s", buf) == 1) {
if (strlen(buf) == 4)
printf("%s\n", buf);
}
If you want to pass the path of the input file, use command line arguments.
The bash command would become:
./a.out /usr/share/dict/words > out.txt 2> out2.txt
And the main function:
#include <errno.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[) {
FILE *fp;
if (argc < 2) {
fprintf(stderr, "%s: missing file name argument\n", argv[0]);
return 1;
}
if ((fp = fopen(argv[1], "r")) == NULL) {
fprintf(stderr, "%s: cannot open file %s: %s\n",
argv[0], argv[1], strerror(errno));
return 1;
}
// for example's sake: filtering 4 letter words:
char buf[100];
while (fscanf(fp, "%99s", buf) == 1) {
if (strlen(buf) == 4)
printf("%s\n", buf);
}
fclose(fp);
return 0;
}
char *infile is just a pointer and does not allocate space for the string, so the input will not be saved. Try something like char infile[50]. Increase the size if needed for your input.

How can I get my C program to read more than one line of text from a file?

I am trying to write a program that reads lines of texts from an input file, rearrange the letters in the words and then writes them to an output file. So far I have this:
void processFile(FILE* ifp, FILE* ofp) {
char line[1024];
char word[1024];
char* lineptr = line;
char temp;
printf("Begin file processing\n");
while (fgets(line, BIGLINE, ifp) != NULL){
while(sscanf(lineptr,"%s",word) == true)
{
if (strlen(word) >= 4){
temp = word[1];
word[1] = word[2];
word[2] = temp;
}
fputs(word,stdout);
fputs(word,ofp);
fputs(" ",stdout);
fputs(" ", ofp);
lineptr += strlen(word) + 1;
}
}/*while*/
printf("End file processing\n");} /* processFile */
Right now the output file reads:
<rpe><div calss="text_to_html">Project Gtuenberg The Avdentures of Sehrlock Hlomes, by Atrhur Cnoan Dyole
But I need it to read all of the lines in my test file
<pre><div class="text_to_html">Project Gutenberg The Adventures of Sherlock Holmes, by Arthur Conan Doyle
This eBook is for the use of anyone anywhere at no cost and with
almost no restrictions whatsoever. You may copy it, give it away or
re-use it under the terms of the Project Gutenberg License included
with this eBook or online at <a href="http://www.gutenberg.net"
class="_blanktarget">www.gutenberg.net</a>
</div></pre>
I also need to make sure that if I put any text file as the input file it would read all of the lines instead of just the first. How can I do this with what I have already?
As I noted in a comment, your primary problem is that you need to reset lineptr inside the while (fgets(…) != NULL) loop before starting the inner loop. You'd be less likely to run into this problem if you placed all variables so they had the minimum possible scope — so temp should be defined inside the if block, while word and lineptr should be defined between the outer and inner loops. You're marginally unlucky that the first line you're processing is the longest line; it means that lineptr is left pointing at a null byte.
You should use sizeof(line) rather than BIGLINE in the call to fgets(). The use of true where the count is 1 is not appropriate either (though not technically incorrect).
Those changes yield:
#include <stdio.h>
#include <string.h>
static void processFile(FILE *ifp, FILE *ofp)
{
char line[1024];
printf("Begin file processing\n");
while (fgets(line, sizeof(line), ifp) != NULL)
{
char word[1024];
char *lineptr = line;
while (sscanf(lineptr, "%s", word) == 1)
{
if (strlen(word) >= 4)
{
char temp = word[1];
word[1] = word[2];
word[2] = temp;
}
fputs(word, stdout);
fputs(word, ofp);
fputs(" ", stdout);
fputs(" ", ofp);
lineptr += strlen(word) + 1;
}
putchar('\n');
}
printf("End file processing\n");
}
int main(void)
{
processFile(stdin, stderr);
return 0;
}
When compiled from rf79.c into rf79 and run with standard error redirected to /dev/null, I get the output:
$ ./rf79 < data 2>/dev/null
Begin file processing
<rpe><div calss="text_to_html">Project Gtuenberg The Avdentures of Sehrlock Hlomes, by Atrhur Cnoan Dyole
Tihs eoBok is for the use of aynone aynwhere at no csot and wtih
amlost no rsetrictions wahtsoever. You u may cpoy it, gvie it aawy or
r-euse it udner the trems of the Porject Gtuenberg Lciense icnluded
wtih tihs eoBok or olnine at <a herf="http://www.gutenberg.net"
calss="_blanktarget">www.gutenberg.net</a>
<d/iv></pre>
End file processing
$
This looks like what you want.

How to read all the lines in a file and store them in a string

I am trying to read some commands which should be passed to my program from a file. The commands are on different lines, so I guess this means that they are separated by \n character. This is my command reading section:
FILE *fop;
char command[50];
fopen("mbr.op", "r");
while(!feof(fop))
{
fscanf(fop,"%s[^\n]", command);
printf("%s\n", command);
}
fclose(fop);
This prints some words that are in the file, but not all, and not in the expected order. How could I change this code to achieve the desired result?
You open your file incorrectly (it returns a FILE pointer which is associated with the opened file), fopen should be used as this -
fop=fopen("mbr.op", "r");
And while(!feof(fop)) should not be used .
You can write your loop as follows -
while(fscanf(fop,"%[^\n]%*c", command)==1)
{
printf("%s\n", command);
}
Note - Also check if file was opened successfully.
FILE *fop;
char command[50];
fop = fopen("mbr.op", "r"); /* get the file pointer */
if (fop == NULL) exit(1); /* check if the file successfully opened */
while(fscanf(fop,"%49[^\n]%*c", command) == 1) /* see notes after this code */
{
printf("%s\n", command);
}
fclose(fop);
Notes on the usage of fscanf():
They say using feof() is not good.
Yon won't need the s.
Specify the maximum length to read to avoid buffer overflow.
Added %*c to have it skip the newline character.
This code above won't work well if there are blank lines.
I think using fgets() is better to read lines.
FILE *fop;
char command[51]; /* added 1 byte to store the newline character */
fop = fopen("mbr.op", "r");
if (fop == NULL) exit(1);
while(fgets(command, sizeof(command), fop))
{
/* remove the newline character */
char* p;
for(p = command; *p != '\0' && *p != '\n'; p++);
*p = '\0';
/* print what is read */
printf("%s\n", command);
}
fclose(fop);

How input works in C

I'm quite confused about the function scanf and how the input works in C.
See this code :
#include<stdio.h>
int main()
{
FILE pt = *stdin;
char b[100];
scanf("%s", b);
scanf("%s", b); //breakpoint here
scanf(" "); //breakpoint here
}
When the code runs, I input 12345 into the console. I found that pt _ptr(which I don't actually know what it is) has the value "12345\n\n" and b[] has the value "12345".
Then I continue the program and input 23456. Now pt _ptr is "23456\n\n" and b[] is "23456".
My question :
How does the input work in C? Why does pt _ptr have the value of "12345\n\n" not "12345\n" since I pressed enter only one time(and it seems like the function scanf skips those two \n after successfully read "12345" ).
You are looking under the carpet... You are not supposed to copy FILE structs so the first line
FILE pt = *stdin;
results are actually undefined. Do not look inside, unless you are willing to read and understand the source of you standard C library!
The rest of the code is pretty easy to understand, as b has always the expected value, isn't it?
It is not apparent what it is you are really trying to do besides learn scanf, but you are also invoking stdin and the FILE struct.
Using fscanf instead, (read link for details on `fscanf) it will be easier to use all three.
Here is a simple example of how you can combine fscanf, FILE, and stdin:
int main(void)
{
FILE *fp={0};
int res =0 //use to check return value of fscanf
char buf[80]; //use 80 for demonstration only
fp = fopen("c:\\dev\\play\\playtext.txt", "w");//create file and stream
res = fscanf(stdin, "%s", buf);//stream input from stdin
if(res == EOF)
{
printf("Exiting... input error");//notify and exit upon error
return -1;
}
while (strstr(buf, "quit") == NULL)//allow exit by typing quit
{
if(fputs(buf, fp) == EOF) return -1;
buf[0]=0;//reset buffer
res = fscanf(stdin, "%s", buf);
if(res == EOF)
{
printf("Exiting... input error");//notify and exit upon error
return -1;
}
}
fclose(fp);
return 0;
}

Why does this code compile but not actuall work?

Line 12 to 23 runs. But doesn't actually run when the if statement is added. it does compile and runs. It asks the first printf statement then terminates when I choose a character. Why is this happening and how do I fix it.
#include <stdio.h>
#include <stdlib.h>
int main()
{
char ch, file_name[25];
FILE *fp;
printf("Enter [A] and select file or [X] to exit:"); // Prompt user to select file or exit
scanf("%c",&ch);
scanf("%c",&ch);
if (ch=='A')
{
printf("Enter the file name\n"); // if user chooses 'A' this code should run
gets(file_name);
fp = fopen(file_name,"r"); // reading file
if( fp == NULL )
{
perror("File not found.\n");
exit(EXIT_FAILURE);
}
printf("Contents of %s are:\n", file_name);
while( ( ch = fgetc(fp) ) != EOF )
printf("%c",ch);
}
else if (ch=='X')
{
printf("Exiting program...");
exit(0);
}
}
Because you have two calls to scanf..
In the first one, you are reading your input 'A' or 'X' successfully.
In the next call, you are reading the newline character(\n) which was pressed earlier into the same variable ch. So it doesn't satisfy any if clause and simply comes out of program..
Instead make second call to temporary variable..
char temp;
scanf("%c", &temp);
Also fgets is preferred over gets
I guess you are not reading properly from the file , Try:
char buff[255]; //define buffer to read lines
while ( !feof(fp ) ){
memset(buff, '\0', sizeof( buff) );
fgets(buff, 255, (FILE*)fp);
printf("%s", buff );
}
fclose(fp); //don't forget to close
There are a large class of programs that compile yet don't run properly. That's why a distinction is made between syntax errors and runtime/logic errors.
scanf("%c",&ch);
scanf("%c",&ch);
I'm assuming that's to get rid of the newline character but it's a bad idea to read it into ch, since that should keep the first character.
If that is the case, simply read it into some junk variable so that ch is preserved.
char ch, junk, file_name[25];
:
scanf("%c",&ch);
scanf("%c",&junk);
Sadly though, there may be numerous other problems with this approach. If you want a decent line input function, you can find one here. That's much better than using gets(), which is inherently unsafe.
It has buffer overflow detection and prevention, automatic flushing of input lines where too long, prompt output and so on. Once you've used it to get an input line, all you need to do is compare that with what you want, something like:
if (strcmp (buff, "A") == 0)
doSectionA();
else
if (strcmp (buff, "X") == 0)
doSectionX();

Resources