-1

I've been banging my head against my desk for a few hours now, trying to figure out why the following code is stalling at while(chars = read(fd, buff, BUFF_SZ)) > 0). The printf on the line directly following is not being called and the one directly above is. The file descriptor is returning 0, a valid value.

char *infile = argv[1];
int fd,chars;

if ((fd = open(infile, O_RDONLY) < 0)) {
    perror("open()");
    exit(1);
}
printf("%s - opened (fp: %d)\n", infile, fd);
while((chars = read(fd, buff, BUFF_SZ)) > 0){
    printf("%d\n", chars);
    for(i = 0; i < chars; i++){
        c = buff[i];
        total++;
        count[c]++;
    }
}

I don't even know how to debug this since nothing is being triggered following the line in question and everything looks fine before this line.

The full, compilable code:

#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>

#include <unistd.h>

#define BUFF_SZ 4096

int main(int argc, char *argv[])
{
        if(argc != 2)
                perror("Wrong number of arguments!");

        int fd;
        char *infile = argv[1];
        char buff[BUFF_SZ];
        int chars,c,c2,i;
        long long total = 0;
        long long count[256];
        char line[71];

        printf("zeroing count[]\n");
        for (c = 0; c < 256; c++) {
                count[c] = 0;
        }

        if ((fd = open(infile, O_RDONLY) < 0)) {
                perror("open()");
                exit(1);
        }
        printf("%s - opened (fp: %d)\n", infile, fd);
        while((chars = read(fd, buff, BUFF_SZ)) > 0){
                printf("%d\n", chars);
                for(i = 0; i < chars; i++){
                        c = buff[i];
                        total++;
                        count[c]++;
                }
        }
        close(fd);
        printf("%s closed\n", infile);

        if(chars < 0){
                perror("read()");
        }

        printf("outputting results\n");
        for (c = 0;c < 256; c++) {
                printf("\t%d of 256\n", c+1);
                snprintf(line, 70, "%.70lf\n",
                         ((float)count[c] / (float)total));
                for (c2 = 68; c2; c2--) {
                        if (line[c2] != '0'
                                && line[c2] != '.')
                                break;
                }
                line[++c2] = 0;
                printf("%s\n", line);
        }
        return 0;
}
Dan
  • 3,246
  • 1
  • 32
  • 52
  • 1
    What happens if, when the program hangs, you type a few words at it, then press RETURN, then control-D, then RETURN again? Also, please post a complete program that can be compiled and run. – zwol Sep 10 '12 at 01:55
  • It does what it's supposed to do with the infile. That makes sense... `stdin` in is zero. It's supposed to be reading from an infile on the commandline though... I'll post the full code now. – Dan Sep 10 '12 at 02:00
  • It was evident from the title alone that it was reading from a terminal (or maybe some other device, or a pipe). – Jim Balter Sep 10 '12 at 03:29
  • In retrospect, yes, @JimBalter. What does that add to this thread though? – Dan Sep 10 '12 at 09:49

2 Answers2

6

The problem is your assignment to fd.

if ((fd = open(infile, O_RDONLY) < 0)) {

should be:

if ((fd = open(infile, O_RDONLY)) < 0) {

The clue was when you said that fd is 0. That was unlikely, since fd 0 is stdin, and this shouldn't happen unless you closed stdin before opening infile.

You were assigning fd the result of comparing the return value of open with 0, instead of assigning the return value itself.

Barmar
  • 741,623
  • 53
  • 500
  • 612
  • Ugh! I can't believe I missed that. Was driving me insane. Thanks! – Dan Sep 10 '12 at 02:04
  • Don't beat yourself up. You aren't even close to the first, won't be the last; it's up there with using = when you mean ==, which I've done myself in the past week or so. But did you try linting it before posting? – Barmar Sep 10 '12 at 02:08
  • 1
    This is the third instance of a variant of this bug posted to [c] today. People should use good compilers and appropriate warning levels. They should also read the code they write ... when would (( expression )) ever be necessary? – Jim Balter Sep 10 '12 at 03:23
  • Good coding standard is also required to avoid such mistakes – Mine Sep 10 '12 at 07:45
1

You only need to rearrange the parenthesis

if ((fd = open(argv[1], O_RDONLY)) < 0) {
ziu
  • 2,634
  • 2
  • 24
  • 39