Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>This is one of the tougher nuts to crack. The code is doing an obscure job and is written rather obscurely. As far as I can tell, it is supposed to be called <code>my_program</code>, and is due to be invoked with a file name as a single argument. The process will then open the file, read its content into two arrays (<code>left</code> and <code>right</code>), without bothering to ensure that they are strings (no null termination). The process then forks twice. One then execs itself with the <code>left</code> (non-)string as an argument and the information that it is <code>left</code>, and one execs itself with the <code>right</code> (non-)string as an argument and the information that it is right. The parent process messes around with <code>select()</code> for no very good reason, and without checking the return value. It then calls read to get information on the two pipes. These reads would block until there's data ready, so the <code>select()</code> really doesn't help at all. (I'm still trying to work out where the recursion bit fits in.) Also, most of the system calls are not error checked.</p> <p>However, given that outline operation (read file, split, children exec and do half each and report back), I would be writing something like this:</p> <pre><code>#include &lt;errno.h&gt; #include &lt;stdarg.h&gt; #include &lt;stdio.h&gt; #include &lt;stdlib.h&gt; #include &lt;string.h&gt; #include &lt;unistd.h&gt; static void err_exit(char const *fmt, ...); int main(int argc, char * *argv) { int l_data[2] = { -1, -1 }; int r_data[2] = { -1, -1 }; char *string; size_t size; char *arg0 = argv[0]; if (argc != 2 &amp;&amp; argc != 3) err_exit("Usage: %s file\n", argv[0]); if (argc == 3) { /* Child process */ string = argv[1]; size = strlen(string); fprintf(stderr, "%d: the string is %s\n", (int)getpid(), string); if (size &lt;= 2) { int bitCounter[2]; bitCounter[0] = 0; bitCounter[1] = 0; for (size_t i = 0; i &lt; size; i++) { if (string[i] == '0') bitCounter[0]++; else if (string[i] == '1') bitCounter[1]++; } if (write(STDOUT_FILENO, bitCounter, sizeof(int)*2) != sizeof(int)*2) err_exit("%d: failed to write on standard output\n", (int)getpid()); fprintf(stderr, "%d: read bits, sending back %d ones and %d zeroes\n", (int)getpid(), bitCounter[1], bitCounter[0]); exit(0); } fprintf(stderr, "%d: doing recursion - string too big (%zu)\n", (int)getpid(), size); } char *data = string; if (argc == 2) { FILE *filePointer; if ((filePointer = fopen(argv[1], "r")) == NULL) { perror("file didn't work"); exit(1); } fseek(filePointer, 0, SEEK_END); size = ftell(filePointer); fseek(filePointer, 0, SEEK_SET); data = malloc(size+1); fread(data, size, 1, filePointer); data[size] = '\0'; if (data[size-1] == '\n') data[--size] = '\0'; fclose(filePointer); fprintf(stderr, "%d: data &lt;&lt;%s&gt;&gt;\n", (int)getpid(), data); } size_t l_size = size/2; size_t r_size = size - l_size; char *left = malloc(l_size+1); char *right = malloc(r_size+1); memcpy(left, data, l_size); left[l_size] = '\0'; memcpy(right, data + l_size, r_size); right[r_size] = '\0'; int l_pid, r_pid; int l_pipe[2] = { -1, -1 }; int r_pipe[2] = { -1, -1 }; if (pipe(l_pipe) != 0 || pipe(r_pipe) != 0) err_exit("%d: Failed to create pipes\n", (int)getpid()); fprintf(stderr, "%d: forking (l_size = %zu, r_size = %zu)\n", (int)getpid(), l_size, r_size); l_pid = fork(); if (l_pid &lt; 0) err_exit("%d: Failed to fork() left child\n", (int)getpid()); else if (l_pid == 0) { dup2(l_pipe[1], STDOUT_FILENO); close(l_pipe[0]); close(l_pipe[1]); close(r_pipe[0]); close(r_pipe[1]); fprintf(stderr, "%d: left execing with string &lt;&lt;%s&gt;&gt;\n", (int)getpid(), left); execl(arg0, arg0, left, "y", NULL); err_exit("%d: failed to start recursion LEFT\n", (int)getpid()); } else if ((r_pid = fork()) &lt; 0) err_exit("%d: Failed to fork() right child\n", (int)getpid()); else if (r_pid == 0) { dup2(r_pipe[1], STDOUT_FILENO); close(l_pipe[0]); close(l_pipe[1]); close(r_pipe[0]); close(r_pipe[1]); fprintf(stderr, "%d: right execing with string &lt;&lt;%s&gt;&gt;\n", (int)getpid(), right); execl(arg0, arg0, right, "y", NULL); err_exit("%d: failed to start recursion RIGHT\n", (int)getpid()); } else { /* Parent process */ int nbytes; close(r_pipe[1]); close(l_pipe[1]); if ((nbytes = read(l_pipe[0], l_data, sizeof(int)*2)) != sizeof(int)*2) err_exit("%d: Read left pipe failed (%d)\n", (int)getpid(), nbytes); if ((nbytes = read(r_pipe[0], r_data, sizeof(int)*2)) != sizeof(int)*2) err_exit("%d: Read right pipe failed (%d)\n", (int)getpid(), nbytes); close(l_pipe[0]); close(r_pipe[0]); } int zeroes = l_data[0] + r_data[0]; int ones = l_data[1] + r_data[1]; if (argc == 3) { int data[2] = { zeroes, ones }; if (write(STDOUT_FILENO, data, sizeof(data)) != sizeof(data)) err_exit("%d: failed to read binary data from stdin\n", (int)getpid()); fprintf(stderr, "%d: binary write to stdout OK\n", (int)getpid()); } fprintf(stderr, "%d: 0's = %d, 1's = %d\n", (int)getpid(), zeroes, ones); return 0; } static void err_exit(char const *fmt, ...) { int errnum = errno; va_list args; va_start(args, fmt); vfprintf(stderr, fmt, args); va_end(args); if (errnum != 0) fprintf(stderr, "%d: %s\n", errnum, strerror(errnum)); exit(1); } </code></pre> <p>Given an input file:</p> <pre><code>0101010111111 </code></pre> <p>the output is:</p> <pre><code>11070: data &lt;&lt;0101010111111&gt;&gt; 11070: forking (l_size = 6, r_size = 7) 11073: right execing with string &lt;&lt;0111111&gt;&gt; 11072: left execing with string &lt;&lt;010101&gt;&gt; 11072: the string is 010101 11072: doing recursion - string too big (6) 11072: forking (l_size = 3, r_size = 3) 11073: the string is 0111111 11073: doing recursion - string too big (7) 11073: forking (l_size = 3, r_size = 4) 11074: left execing with string &lt;&lt;010&gt;&gt; 11075: right execing with string &lt;&lt;101&gt;&gt; 11076: left execing with string &lt;&lt;011&gt;&gt; 11077: right execing with string &lt;&lt;1111&gt;&gt; 11074: the string is 010 11074: doing recursion - string too big (3) 11074: forking (l_size = 1, r_size = 2) 11078: left execing with string &lt;&lt;0&gt;&gt; 11076: the string is 011 11076: doing recursion - string too big (3) 11076: forking (l_size = 1, r_size = 2) 11079: right execing with string &lt;&lt;10&gt;&gt; 11075: the string is 101 11075: doing recursion - string too big (3) 11075: forking (l_size = 1, r_size = 2) 11080: left execing with string &lt;&lt;0&gt;&gt; 11077: the string is 1111 11077: doing recursion - string too big (4) 11077: forking (l_size = 2, r_size = 2) 11082: right execing with string &lt;&lt;11&gt;&gt; 11081: left execing with string &lt;&lt;1&gt;&gt; 11083: right execing with string &lt;&lt;01&gt;&gt; 11084: left execing with string &lt;&lt;11&gt;&gt; 11085: right execing with string &lt;&lt;11&gt;&gt; 11079: the string is 10 11078: the string is 0 11079: read bits, sending back 1 ones and 1 zeroes 11078: read bits, sending back 0 ones and 1 zeroes 11074: binary write to stdout OK 11074: 0's = 2, 1's = 1 11082: the string is 11 11082: read bits, sending back 2 ones and 0 zeroes 11080: the string is 0 11080: read bits, sending back 0 ones and 1 zeroes 11076: binary write to stdout OK 11076: 0's = 1, 1's = 2 11081: the string is 1 11081: read bits, sending back 1 ones and 0 zeroes 11084: the string is 11 11084: read bits, sending back 2 ones and 0 zeroes 11083: the string is 01 11083: read bits, sending back 1 ones and 1 zeroes 11075: binary write to stdout OK 11075: 0's = 1, 1's = 2 11072: binary write to stdout OK 11072: 0's = 3, 1's = 3 11085: the string is 11 11085: read bits, sending back 2 ones and 0 zeroes 11077: binary write to stdout OK 11077: 0's = 0, 1's = 4 11073: binary write to stdout OK 11073: 0's = 1, 1's = 6 11070: 0's = 4, 1's = 9 </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.
 

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