1

I have dummy code with popen() call. I'm trying to obtain ntpq output. It works, but it sets errno to "No such file o directory"

#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>

int main(int argc, char *argv[]){
    if(access("/usr/bin/ntpq", X_OK) == 0){
        printf("binary found!\n");
    } else if(access("/usr/sbin/ntpq", X_OK) == 0) {
        printf("binary found!\n");
    } else {
        printf("no such binary found!\n");
    }

    char buffer[BUFSIZ+1] = {0};

    fcloseall();
    auto read_fp = popen("/usr/bin/ntpq -pn 2>&1", "r");
    auto fdn = fileno(read_fp);

    printf("fd number:%d, errno: %s\n", fdn, strerror(errno));

    if(read_fp != NULL){
        int chars_read = fread(buffer, sizeof(char), BUFSIZ, read_fp);
        int err_fread = ferror(read_fp);
        printf("errno: %s\n", strerror(errno));
        printf("fread code error: %d\n", err_fread);
        printf("chars_read:%d buffer:\n%s\n",chars_read, buffer);
    }
    auto res = pclose(read_fp);
    printf("pclose result: %d\n", res);
}

The output:

errno: No such file or directory
fread code error: 0
chars_read:1817 buffer:
     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
 0.debian.pool.n .POOL.          16 p    -   64    0    0.000    0.000   0.000
 1.debian.pool.n .POOL.          16 p    -   64    0    0.000    0.000   0.000
 2.debian.pool.n .POOL.          16 p    -   64    0    0.000    0.000   0.000
 3.debian.pool.n .POOL.          16 p    -   64    0    0.000    0.000   0.000
-194.190.168.1   .GPS.            1 u  429 1024   77   50.695  -11.531   2.685
+193.192.36.3    128.0.142.251    3 u  396 1024   77   28.064  -11.941   3.725
+91.209.94.10    194.190.168.1    2 u  374 1024   77   13.551  -10.077   3.143
+185.209.85.222  194.190.168.1    2 u  361 1024   77    5.546   -8.825   1.980
#89.110.32.178   83.143.51.50     2 u  419 1024   77   17.984  -12.670   8.617
#85.21.78.23     194.58.202.20    2 u  413 1024   77   24.850  -14.270   1.513
#89.169.75.105   88.147.254.228   2 u  368 1024   75   15.885   -9.821   2.040
#195.3.254.2     194.58.202.148   2 u  394 1024   77   21.267   -5.133   3.649
#89.221.207.113  194.58.204.148   2 u  391 1024   77   15.524  -13.023   2.140
+212.13.97.58    89.109.251.22    2 u  407 1024   77   14.036   -9.068   1.887
*195.210.189.106 .GPS.            1 u  456 1024   37   16.241   -9.656   2.837
#83.143.51.50    .PPS.            1 u  381 1024   77   46.082   -9.931   3.363
+195.91.239.8    .PPS.            1 u  533 1024   17   12.478   -9.804   2.495
-94.247.111.10   89.109.251.24    2 u  305 1024   77   57.922  -10.653   1.569
#85.21.78.8      192.36.144.22    2 u  415 1024   77   24.246  -13.495   1.828
+185.22.62.218   194.58.202.20    2 u  367 1024   77   15.070  -10.196   2.563
-188.93.104.2    89.109.251.21    2 u  399 1024   77   13.762   -9.195   2.818

pclose result: 0

I tried to close all file streams with fcloseall(). Also I tried fflush(NULL) to clear all streams. But nothing changed.

I use this invoke in production and I need to get success status with errno variable. What I could do wrong? What I could check? Can I replace popen() invoke?

Linux debian 4.19.0-17-amd64 #1 SMP Debian 4.19.194-3 (2021-07-18) x86_64 GNU/Linux

  • Most C library functions are allowed to set `errno` to a nonzero value *even if they succeed*. See the linked older answer for more detail. – zwol Aug 03 '21 at 12:46
  • We might be able to be more helpful if you explain why you think you "need to get success status with errno variable". Usually it doesn't matter what value errno has after a successful operation. – zwol Aug 03 '21 at 12:51
  • errno is likely not changed if there is no error. – stark Aug 03 '21 at 13:12
  • The use of `auto read_fp = popen("/usr/bin/ntpq -pn 2>&1", "r");` means this code is C++, not C. There'd be a type mismatch as well as 'implicit `int`' problems in C. – Jonathan Leffler Aug 03 '21 at 13:32
  • The right ways to "get success status" are slightly different. You want `if(read_fp == NULL) { /* error popening ntpq */ }`. And then maybe `if(chars_read <= 0) { /* error/EOF reading ntpq */ }`. You can get rid of `fdn` and `err_fread`, since they're not necessary and you don't use them. – Steve Summit Aug 03 '21 at 14:15
  • @JonathanLeffler I believe C++ also allows `errno` to be overwritten by library functions on success? – zwol Aug 03 '21 at 18:42
  • @stark No, that's not right. It is quite common for the value of `errno` to change as a side effect of a successful library call. (Under the hood, what's happening is the library call tries to do some low-level operation, and that fails, so then it tries to do its job a different way and succeeds.) – zwol Aug 03 '21 at 18:45
  • @zwol — I haven't checked the C++ standard today, but I'd expect that the standard allows the C++ library to modify `errno` even when the function reports success (except where that is explicitly disallowed). One reason is that the C++ library builds on the C library, and the C library allows that. – Jonathan Leffler Aug 03 '21 at 18:46
  • C11 [§7.5 Errors `` ¶3](http://port70.net/~/c/c11/n1570.html#7.5p3) says: _The value of `errno` in the initial thread is zero at program startup (the initial value of `errno` in other threads is an indeterminate value), but is never set to zero by any library function.202) The value of `errno` may be set to nonzero by a library function call whether or not there is an error, provided the use of `errno` is not documented in the description of the function in this International Standard._ […continued…] – Jonathan Leffler Aug 03 '21 at 18:52
  • […continuation…] Footnote 202 says: _Thus, a program that uses `errno` for error checking should set it to zero before a library function call, then inspect it before a subsequent library function call. Of course, a library function can save the value of `errno` on entry and then set it to zero, as long as the original value is restored if `errno`'s value is still zero just before the return._ – Jonathan Leffler Aug 03 '21 at 18:53

0 Answers0