cmalloc

How to get result from popen?


I want to create a little patch for program. I don't know much about C.

When my function get_streamlink return buffer, the next code failed to fetch video via m3u8 url. When function return static url, video shows success. In both cases urls and the next code are the same. What's wrong?

UPD: Thanks for comments. Issue with \n from fgets.

static char *get_streamlink(const char *url) {
    char *template = "streamlink %s best --stream-url";
    char *buffer = (char *)malloc(5060);
    FILE *pPipe;

    struct dstr command = {0};
    dstr_catf(&command, template, url);
    pPipe = _popen(command.array, "rt");
    dstr_free(&command);

    while (fgets(buffer, 5060, pPipe)) {
        puts(buffer);
    }

    int endOfFileVal = feof(pPipe);
    int closeReturnVal = _pclose(pPipe);

    // failed
    return buffer;

    // OK
    // return "https://video-weaver.arn03.hls.ttvnw.net/v1/playlist/CvAEXGd8OH7.....m3u8";
}

static void add_file(struct vlc_source *c, media_file_array_t *new_files,
             const char *path, int network_caching, int track_index,
             int subtitle_index, bool subtitle_enable,
             const char *hw_value, bool skip_b_frames)
{
    struct media_file_data data;
    struct dstr new_path = {0};
    libvlc_media_t *new_media;
    bool is_url = path && strstr(path, "://") != NULL;

    dstr_copy(&new_path, path);
#ifdef _WIN32
    if (!is_url)
        dstr_replace(&new_path, "/", "\\");
#endif
    dstr_copy(&new_path, get_streamlink(new_path.array));
    path = new_path.array;
    new_media = get_media(&c->files, path);

    //...
}

enter image description here


Solution

  • You need to remove the trailing \n / \r\n.

    Since you are using a non-standard function, _popen, you could also make use of another non-standard extension in MSVC: The basic_ifstream constructor taking a FILE*. With that you can then use std::getline on the input stream.

    #include <cstdio>
    #include <fstream>
    #include <iostream>
    #include <string>
    
    std::ifstream Popen(const char* command) {
        auto fp = _popen(command, "rt");
        return std::ifstream(fp);         // construct the ifstream using a FILE*
    }
    
    int main() {
        auto is = Popen("dir");
        std::string line;
        while (std::getline(is, line)) {
            std::cout << line << '\n';
        }
    }