1

My very simple C program just hangs and I don’t know why.

I am trying to make a simple executable to handle multiple monotonous actions for me every time I start a new programming session.

So I decided with something simple (below) yet every time I run it, the app just hangs, never returns. So I have to Ctrl-C out of it. I have added printf commands to see if it goes anywhere, but those never appear.

My build command returns no error messages:

gcc -o tail tail.c

Just curious what I am missing.

#include <stdio.h>
#include <unistd.h>
int main() {

    chdir("\\var\\www");
    return 0;
}
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Bartender1382
  • 195
  • 1
  • 10
  • 2
    Try `./tail` ;) tail is a default program that will be pulled out of the system path first. See `man tail` – Max Apr 20 '22 at 21:07
  • Search for [`[c] chdir`](https://stackoverflow.com/search?q=%5Bc%5D+chdir), maybe one of the results helps, e.g. https://stackoverflow.com/q/18277177/1741542 – Olaf Dietsche Apr 20 '22 at 21:07
  • Secondly, chdir() will not modify the parent process (eg, the shell). Maybe try a shell alias for this. – Max Apr 20 '22 at 21:08
  • 4
    There are multiple issues with your program. First of all, on Unix the path separator character is `/`, not ``\``. Then, each program has its own current directory. Your program starts, changes its current directory (let's assume that it succeeds) then exits. It cannot change the current directory of the shell. No program can do that. – axiac Apr 20 '22 at 21:09
  • 1
    There is no obvious reason why your program would hang. If the `chdir()` call fails, it should do so promptly. In the unlikely event that it succeeds, it should likewise do so promptly. One of the few possibilities is that the `/var/www` directory is on a network file system and will be automounted, but there is some problem making that a slow process (the remote machine is not available, or is horribly overloaded, or …). – Jonathan Leffler Apr 20 '22 at 21:27
  • Incidentally, if `printf()` statements don't appear to execute, there can be several problems. One is that the statements aren't executed, of course. But if you don't include a newline at the end of the message, the output may not appear immediately. Remember to add newlines. And if you pipe the standard output, or redirect to file, then even with newlines, the output may be buffered up. You can add `fflush(stdout)` after the `printf()` statements to force it out. – Jonathan Leffler Apr 20 '22 at 22:32
  • 1
    @JonathanLeffler It's almost assuredly hanging because he's running /usr/bin/tail, which waits for input on stdin without arguments. – Max Apr 20 '22 at 22:50
  • Oh, of course, @Max. – Jonathan Leffler Apr 20 '22 at 23:30

3 Answers3

5

There are at least two problems with the source code:

  1. It is unlikely that you have a sub-directory called \var\www in your current directory — Ubuntu uses / and not \ for path separators.

  2. Even if there was a sub-directory with the right name, your program would change directory to it but that wouldn't affect the calling program.

You should check the return value from chdir() — at minimum:

if (chdir("/var/www") != 0)
{
    perror("chdir");
    exit(EXIT_FAILURE);
}

And, as Max pointed out, calling your program by the name of a well-known utility such as tail is likely to lead to confusion. Use a different name.

Incidentally, don't use test as a program name either. That, too, will lead to confusion as it is a shell built-in as well as an executable in either /bin or /usr/bin. There is also a program /bin/cd or /usr/bin/cd on your machine — it will check that it can change directory, but won't affect the current directory of your shell. You have to invoke it explicitly by the full pathname to get it to run at all because cd is another shell built-in.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • 5
    A third is that OP is probably typing a bare `tail` and getting /usr/bin/tail or a shell built in. – Max Apr 20 '22 at 21:10
  • Re: your edit: When I was a new C programmer, I definitely made that mistake of using `test` as compiler output and being flummoxed when it didn’t do anything at all. – Max Apr 20 '22 at 21:15
  • @JonathanLeffler you mean _don't use **tail** as a program name ..._ instead of _**test**_ – David Ranieri Apr 20 '22 at 21:26
  • No, @DavidRanieri, I don't mean that. Or rather, I said that in the previous paragraph ('As Max pointed out'). The last paragraph is some tangential commentary — one is a comment about not using ***`test`*** as a program name, and the other about the fact that there is a binary for the `cd` utility in one of the standard directories (`/bin` and/or `/usr/bin`), but using it doesn't usually lead to satisfactory results. – Jonathan Leffler Apr 20 '22 at 21:30
  • Oops, sorry, I didn't pay atention to the previous paragraph :( – David Ranieri Apr 20 '22 at 21:32
  • Wow @Max, I just didn't even think of that. That was it! – Bartender1382 Apr 21 '22 at 17:28
  • @Max Could you put your comment as an answer so I may mark it correct? Or should I just close this question? – Bartender1382 Apr 21 '22 at 17:36
  • @Bartender1382 Sure, will do. – Max Apr 21 '22 at 17:36
1

Two things:

  • First, that's not what Linux paths look like

  • Second, check the return value from chdir()

ie

 if (chdir("/var/www") != 0)
     printf("failed to change directory");

Finally, the effect of chdir() lasts for the duration of the program. It will not change the current directory of your shell once this program finishes.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
pm100
  • 48,078
  • 23
  • 82
  • 145
0

The other answers adequately cover the issues in your C code. However, the reason you are seeing it hang is because you chose the name tail for your program.

In Linux, tail is a command in /usr/bin in most setups, and if you just type tail at the command line, the shell searches the $PATH first, and runs this. Without any parameters, it waits for input on its stdin. You can end it by pressing control-d to mark the end of file.

You can bypass the $PATH lookup by typing ./tail instead.

$ tail
[system tail]
$ ./tail
[tail in your current directory]

It is a good idea to use ./ as a habit, but you can also avoid confusion by not naming your program the same as common commands. Another name to avoid is test which is a shell built-in for testing various aspects of files, but appears to do nothing as it reports results in its system return code.

Max
  • 10,701
  • 2
  • 24
  • 48