Note that there are some explanatory texts on larger screens.

plurals
  1. POHow to fill array of character pointers with arguments taken from scanf?
    primarykey
    data
    text
    <p>I'm trying to write a VERY basic shell program in C. The problem I am facing is trying to fill my argv array of character pointers with the words taken from input. When I attempt to print out the contents of the argv array after attempting to fill it using the parse() function below I get a segmentation fault. I know this means that I am probably trying to access part of the argv array that is out of bounds. However, even when supplying only one argument to fill the array, I still get the segfault. The printf call used to print argc returns the correct value for argc based on input, but the second printf call with *argv[0] is the one causing the segfault. I am wondering if my error is in the way I am attempting to print the contents of argv, or if the error is because I am attempting to fill argv incorrectly.</p> <p>EDIT: I should add that the getword() function takes in a line of text and returns the first word delimited by spaces, and a number of other delimiters. I can post all the delimiters it breaks the words up by if necessary, but I do not think the problem is because of getword().</p> <p>EDIT 2: Added in the header file and included the #include statement in main.</p> <p>EDIT 3: Added the getword function under main(), and getword.h below p2.h</p> <p>Here is p2.h, the header file included in main:</p> <pre><code>#include &lt;stdio.h&gt; #include &lt;unistd.h&gt; #include &lt;sys/types.h&gt; #include &lt;sys/stat.h&gt; #include &lt;fcntl.h&gt; #include "getword.h" #include &lt;signal.h&gt; #define MAXITEM 100 </code></pre> <p>getword.h:</p> <pre><code>#include &lt;stdio.h&gt; #include &lt;string.h&gt; #include &lt;strings.h&gt; #define STORAGE 255 int getword(char *w); int parse(char *, char *[]); </code></pre> <p>Here is the main function :</p> <pre><code>#include "p2.h" int main() { pid_t pid, child_pid; int argc, inputRedirect; char *devNull; devNull = (char *) malloc(10); strcpy(devNull, "/dev/null"); char *argv[MAXITEM]; char commandLine[STORAGE]; for (;;) { printf("p2: "); scanf("%s", commandLine); argc = parse(commandLine, argv); printf("argc = %d\n", argc); if(argc == 0) continue; printf("*argv = %s\n", *argv[0]); child_pid = fork(); if (child_pid &lt; 0) { printf("Cannot fork! Terminating..."); exit(1); } else if (child_pid == 0) { inputRedirect = open(devNull, O_RDONLY); dup2(inputRedirect, STDIN_FILENO); close(inputRedirect); execvp(*argv, argv); } else { for(;;) { pid = wait(NULL); if(pid == child_pid) break; } printf("Child's pid is %d\n", child_pid); } } killpg(getpid(), SIGTERM); printf("p2 Terminated.\n"); exit(0); } int parse(char *commandLine, char *argv[]) { int i, argc = 0; char *commandPointer = commandLine; while (*commandPointer != '\0') { *argv = commandPointer; argc++; getword(commandPointer); } *commandPointer = '\0'; *argv = '\0'; return argc; } </code></pre> <p>getword.c:</p> <pre><code>#include "getword.h" #include &lt;stdlib.h&gt; /*Function Prototypes*/ int tilde(char *p, int i); int BSFollowedByMetaCharacter(int c, char *w); int getword(char *w) { int c; int index = 0; /*This while loop removes all leading blanks and whitespace characters * The if statement then tests if the first character is a new line or * semicolon metacharacter*/ while ((c = getchar()) == ' ' || c == '\t' || c == '\n' || c == ';') { if (c == '\n' || c == ';') { w[index] = '\0'; return 0; } } /*This if statement calls ungetc() to push whatever character was taken * from the input stream in the previous while loop back to the input * stream. If EOF was taken from the input stream, ungetc() will return EOF, * which will then cause getword() to return -1, signalling that it reached * the End Of File. */ if (ungetc(c, stdin) == EOF) return -1; /*This if statement deals with some of the "non-special" metacharacters. * If one of these metacharacters is pulled from the input stream by getchar(), * it is stored in w and null-terminated. getword() then returns the length of * the current string stored in w. If getchar() pulls anything besides one of the * specified metacharacters from the input stream, it is then returned using ungetc() after * the if statement.*/ if ((c = getchar()) == '&lt;' || c == '&gt;' || c == '|' || c == '&amp;') { w[index++] = c; int d = getchar(); if (c == '&gt;' &amp;&amp; d == '&gt;') w[index++] = d; else { ungetc(d, stdin); } w[index] = '\0'; return index; } ungetc(c, stdin); /*This while statement handles plain text from the input stream, as well as a few 'special' * metacharacters. It also ensures that the word scanned is shorter than STORAGE-1 bytes.*/ while ((c = getchar()) != ' ' &amp;&amp; c != '&lt;' &amp;&amp; c != '&gt;' &amp;&amp; c != '|' &amp;&amp; c != ';' &amp;&amp; c != '&amp;' &amp;&amp; c != '\t' &amp;&amp; c != '\n' &amp;&amp; c != '\0' &amp;&amp; index &lt;= STORAGE - 1) { if (c == '~') { int *ip = &amp;index; index = tilde(&amp;w[index], *ip); continue; }/*END IF*/ else if (c == '\\') { int d = c; c = getchar(); if (BSFollowedByMetaCharacter(c, w)) { w[index++] = c; continue; } else { w[index++] = d; } }/*END ELSE IF*/ w[index] = c; index++; }/*END WHILE*/ ungetc(c, stdin);/*This final ungetc() call is used to push any meta characters*/ w[index] = '\0'; /*used as delimiters back to the input stream, to be retrieved*/ return index; /*at the next call of getword(). */ }/*END getword()*/ int tilde(char *cp, int i) { int *ip; ip = &amp;i; char *p = cp; char *o; o = (strcpy(p, getenv("HOME"))); int offset = strlen(o); *ip = *ip + offset; return i; } int BSFollowedByMetaCharacter(int c, char *w) { if (c == '~' || c == '&lt;' || c == '&gt;' || c == '|' || c == ';' || c == '&amp;' || c == ' ' || c == '\t' || c == '\\') { return 1; } else { return 0; } } </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload