0

I have a large directory of music which is listed in a file called op. I have been able to build a command which will randomly pick a song from the op file using some creative math with the nanosecond output from the date command. It works fine from the command line:

sed -n $((10#$(date +%N)%$(wc -l /shared/southpark/music/op|cut -d ' ' -f 1)))p /shared/southpark/music/op

I want to include this command in a c program and read the line in with popen.

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

int main (int argc, char *argv[])
{
        char command[201];
        char buf[501];
        FILE *fp;

        strcpy(command, "sed -n $((10#$(date +%N)%$(wc -l /shared/southpark/music/op|cut -d ' ' -f 1)))p /shared/southpark/music/op");

        if((fp = popen(command, "r")) == NULL)
        {
                fprintf(stderr, "music_player: popen failed\n");
                return(1);
        }

        if(fgets(buf, sizeof(buf), fp) == NULL)
        {
                fprintf(stderr, "music_player: fgets failed\n");
                return(1);
        }

        printf("%s\n", buf);
        pclose(fp);
        return(0);
}

But when I run it, I get the following error:

sh: 1: arithmetic expression: expecting EOF: "10#271445839%2278"
music_player: fgets failed

How can I do this? I'm not understanding the error message.

Cyclonecode
  • 29,115
  • 11
  • 72
  • 93
Deanie
  • 2,316
  • 2
  • 19
  • 35

2 Answers2

2

popen executes your command using

/bin/sh -c "command"

and your sh doesn't understand the 10# base-conversion prefix. You've been running the command in bash previously.

To fix, you have two options:

  1. Discard the unnecessary 10# prefix (it is the default) for sh compatibility
  2. Use bash:

    popen("bash -c 'command'", ...)
    
nneonneo
  • 171,345
  • 36
  • 312
  • 383
  • I have to use the decimal conversion, because the nanosecond option of date will include leading zeros which was messing with the earlier tries. – Deanie Jun 19 '15 at 05:51
  • And changing the command to `strcpy(command, "bash -c \"sed -n $((10#$(date +%N)%$(wc -l /shared/southpark/music/op|cut -d ' ' -f 1)))p /shared/southpark/music/op\"");` created the same error as above. – Deanie Jun 19 '15 at 05:55
  • Instead of using `date +%N`, then, consider using `(${RANDOM}<<15) + ${RANDOM}`, which uses `bash`'s built-in random number generator. – nneonneo Jun 19 '15 at 06:08
0

After trying and failing with both of nneonneo's options, I had to resort to placing the command in a bash script file and then I popen'ed the script. It gives me the desired results.

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

int main (int argc, char *argv[])
{
        char command[201];
        char buf[501];
        FILE *fp;

        strcpy(command, "/dea/testing/popen/get_file");

        if((fp = popen(command, "r")) == NULL)
        {
                fprintf(stderr, "music_player: popen failed\n");
                return(1);
        }

        if(fgets(buf, sizeof(buf), fp) == NULL)
        {
                fprintf(stderr, "music_player: fgets failed\n");
                return(1);
        }

        printf("%s", buf);
        pclose(fp);
        return(0);
}
Deanie
  • 2,316
  • 2
  • 19
  • 35