I'm currently working on this course assignment and I'm trying to set up code to search within a database file (really its just a text file named ). I hear we can use the popen function to implement shell code within a C program so here's what I tried:

----------------
outside main:

<all imports>
FILE *read_fp
char *command; ;
char *input;

input is a variable in my program

<in a signal handler outside main (called by child)>
command = "grep '[B]input[/B]' a1.dv\n"
if ( !(read_fp = (FILE*)popen(command,"r")) ) {
        (record not found) [read_fp is null] }
else {
        (record found)
     }

What I want to happen is that it would search my database file() for a user-specific word (chosen at runtime and set to variable 'input'). If that word is present, I want to display a message saying 'record found' or something and if not, then the other message saying not found.

The problem:
I'm trying to figure out a way to make that 'input' variable work, as I know right now it just takes it as the word 'input' instead of a variable. I heard snprintf was a solution, so I tried this code before doing the popen code above:

command:

command = "grep 'input' a1.db\n";
snprintf(command,sizeof command, "grep '%s' a1.db\n", input);

Also tried:

snprintf(NULL,0, "grep '%s' a1.db\n", input);

command wasn't set in this case.

The thing is, I don't really understand how snprintf works. I read some definitions here and there but I still don't really get it.

Another method I tried was concatenating, but that just crashed my program everytime saying Segmentation fault (core dumped) right after getting the input variable from me and right before doing the strncpy/strcat (I tried both) commands. It's also not a single concatenation, as you would concatenate these strings:

String1: "grep '"
String2: input (the variable delcared as 'char input' outside main)
String3: "' \n"
Final String: "grep 'input' \n"

---------------------------

(outside main) -- unncessary variables for this question removed
  <imports>
  char *input;
  FILE *read_fp;
  char *command;
  char *tmp1,*tmp2,*tmp3;

  (within main)

  printf("Please enter the string to enter/search within the database!\n");
  fgets(input,30,stdin);


  (never reaches to this point due to the crash after variable is entered)

  tmp1= "grep '";
  tmp2 = "' a1.db/n";
  printf("settings tmp1 and 2");
  tmp3 = input;
  printf("now strncyping!");
  tmp1 = strncpy(tmp1,tmp3,30);
  tmp1 = strncpy(tmp1,tmp2,10);
  printf("strnycpy done!!");
  command = tmp1;

When I don't use the concatenation method, my program works fine, except that it doesn't actually search for the string and I get the same result 'not found' or 'found' in every case.
-----------------------------

Any help is appreciated :D All I need to do is get the variable working with popen...simple and short code would be nice!

Dani AI

Generated

Quick diagnosis and a safe fix summary. The crash comes from writing input into unallocated memory: char *input; only declares a pointer, it does not reserve a buffer, so using fgets or strcpy into it invokes undefined behavior. and were on the right track — allocate or use a fixed buffer and always check fgets return. (man7.org)

A simple, robust C approach is to avoid the shell entirely and search the file in-process. This reads a size-limited pattern, strips the trailing newline, and scans each line with strstr:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(void) {
    char pattern[128];
    char line[512];
    FILE *fp;
    int found = 0;

    if (!fgets(pattern, sizeof pattern, stdin)) return 1;
    pattern[strcspn(pattern, "\n")] = '\0';

    fp = fopen("a1.db", "r");
    if (!fp) { perror("fopen"); return 1; }

    while (fgets(line, sizeof line, fp))
        if (strstr(line, pattern)) { found = 1; break; }

    fclose(fp);
    puts(found ? "record found" : "not found");
    return found ? 0 : 1;
}

If an external grep is required, do not build a shell command string with user data (that is what popen does — it runs a shell and is vulnerable to injection). Instead fork and exec grep with argv so no shell parses the input. That avoids shell metacharacter attacks; see OWASP on command injection and the exec docs for examples. (man7.org)

Troubleshooting tips: always check return values (fgets, fopen, snprintf), trim the newline (strcspn), prefer fixed-size buffers or malloc + checks, and if you must compose strings use snprintf and test its return to detect truncation. Prefer the in-process search for simplicity and safety unless you have a reason to spawn external tools. (man7.org)

Recommended Answers

All 2 Replies

I'm not sure but I do not think "char *input" reserves any space for input just defines a pointer. so as soon as typing starts you are writing into a undefined memory location. You would most likely receive some kind of runtime error.

Yeah, you have to allocate space for the strings using a function like malloc() or calloc(). Or you could also just declare your strings like char input[100] or something like that. Also, you should use // or /* and */ to indicate your comments.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.