LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 08-07-2019, 04:51 AM   #106
GazL
LQ Veteran
 
Registered: May 2008
Posts: 5,789

Rep: Reputation: 3705Reputation: 3705Reputation: 3705Reputation: 3705Reputation: 3705Reputation: 3705Reputation: 3705Reputation: 3705Reputation: 3705Reputation: 3705Reputation: 3705

Congrats on getting the partial match sorted.


Quote:
Originally Posted by jsbjsb001 View Post
I've been reading the man page about the access() function, and while it does seem to make some sense to me; I'm not clear about the value of F_OK or the part about the "mask" following that. What is the value of F_OK ? Because I'm not sure what I'm supposed to put for the int mode part in the SYNOPSIS section of the man page. And what's the "mask" part in the DESCRIPTION section of the man page mean? Also, am I right in thinking that you guys are saying I should use access() to check if the input file exists (argv[2]) ?
Yes, In this case though, because it's going to be used as an input file I'd check that it is readable instead of just exists -- there's no point continuing your program if you can't read your input file -- so use R_OK.
I'd suggest you do a little background reading on bit masks to fully understand what's going on here. They're used frequently in library functions, so they're an important concept to understand.


Quote:
Originally Posted by jsbjsb001 View Post
I was thinking about passing the ffargs array to the execFfmpeg() function of my program below, then somehow copying ffargs[] into a pointer array since execv() expects a pointer array, then tacking the value of argv[3] (for the output file name) on the end of the pointer array in the execFfmpeg() function. But I'm not quite sure exactly how to do that part of it though, or even if that idea is the best way to go?
You're on the right track, but let me ask: why use ffargs as an intermediary when your readconfig function is already finding all the pointers for you using strtok() within the loop, At the moment you're breaking the config line into pieces with strtok() only to reassemble them with strcat(), which is kind of pointless when you think about it.

If I were you, I'd split your function in two. The first to find the matching line of the config file, and the second to convert it into an array of pointers. As mentioned above, your strtok() loop is already finding those pointers for you, you just need to stick them in an array ready to be used by execv() instead of using strcat() on them.
 
1 members found this post helpful.
Old 08-07-2019, 06:59 AM   #107
jsbjsb001
Senior Member
 
Registered: Mar 2009
Location: Earth, unfortunately...
Distribution: Currently: OpenMandriva. Previously: openSUSE, PCLinuxOS, CentOS, among others over the years.
Posts: 3,827

Original Poster
Rep: Reputation: 2020Reputation: 2020Reputation: 2020Reputation: 2020Reputation: 2020Reputation: 2020Reputation: 2020Reputation: 2020Reputation: 2020Reputation: 2020Reputation: 2020
Thanks GazL!

I tried to do what you said about splitting the readConfigFile() function into two, but I'm having trouble getting what I've done to compile. I'm not sure what gcc is trying to tell me in the errors from it below. I think it's something to do with the buildFfCmdline() function's I created arguments/parameters, but I'm just not sure exactly what the problem is. I've still gotta change the fopen() for the input file to the access() function instead, so I am planning on doing that - I was just trying to split the readConfigFile() function into two like you said first.

Here's what I've got now;

Code:
// includes
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdbool.h>

char readConfigFile(char *argv[]);
char buildFfCmdline(char *tokenPtr, *argv[]);
//char execFfmpeg(char ffargs[]);

// main function
int main(int argc, char *argv[]) {
  
    if  ( argc < 4 ) {
       fprintf (stderr, "Missing option or filename\nUSAGE: ffcliFront <format_id> <input_file> <output_file>\n");
       return 1;
    }
    
    // check if input file exists
    FILE *inputfile;
        
    if  ( (inputfile = fopen(argv[2], "r")) == NULL ) {
       fprintf(stderr, "Input file not found, exiting.\n");
       return 1;        
    }
    fclose(inputfile);
          
    readConfigFile(argv);
    //readConfigFile(argv[1], argv[2]);

    return 0;
    
}

char readConfigFile(char *argv[]) {

    char configLine[128];
    char *tokenPtr;
    bool foundStr = false;
                  
    // read config file
    FILE *configfile;
      
    if  ( (configfile = fopen("ffcliFront.conf", "r")) == NULL )  {
       fprintf(stderr, "Configuration file not found, exiting.\n");
       return 1;        
    }
    
    printf("argv[1] = %s\n", argv[1]);
       
    while( fgets(configLine, 128, configfile ) != NULL) {
          printf("Line from config file: %s\n", configLine);
          tokenPtr = strtok(configLine, ","); 
          int result = strcasecmp(tokenPtr, argv[1]);
          if ( result == 0)  {
             foundStr = true;
             printf("Found string: %s\ntokenPtr = %s\n", configLine, tokenPtr);
             buildFfCmdline(tokenPtr, argv);                    
          }
          else if (foundStr == false) {
                  fprintf(stderr, "\"%s\" format_id not found in configuration file, exiting.\nCheck ffcliFront.conf for a valid format_id or specify a format_id that exists.\n", argv[1]);
                  return 1;
          }
    }
    return 0;
}
                   
char buildFfCmdline(char *tokenPtr, *argv[])  {
    
    char *ffargs[128];
    int i = 0;
       	                
    strcpy(ffargs, "-i ");
    strcat(ffargs, argv[2]);
		 
    while( tokenPtr != NULL ) {
           tokenPtr = strtok(NULL, ","); 
           printf("Token: %s\n", tokenPtr);
           if (tokenPtr) {
              ++i;
              printf("tokenPtr = %s\n", tokenPtr);
              tokenPtr = *ffargs[i];
              //strcat(ffargs, tokenPtr);
           }
           break;
    }
    //strcat(ffargs, argv[3]); 
    fclose(configfile);
            
    printf("ffargs = %s\n", ffargs);
        
    // pass char array with ffmpeg args & call execFfmpeg() fuction with args from config file
   // execFfmpeg(ffargs);
 
    return 0;
}      

//char execFfmpeg(char ffargs[]) {
  
    //char *ffcmdline[128];  
     
    //printf("%s\n", ffargs); 
    // run fmpeg with args from config file & filename supplied to this program. 
    // execv ("ffmpeg", ffcmdline);
	
    //return 0;
//}
This is the error gcc gives me;

Code:
james@jamespc: ffcliFront> gcc -g -Wall -Werror ffcliFront.c -o ffcliFront
ffcliFront.c:9:37: error: expected declaration specifiers or ‘...’ before ‘*’ token
    9 | char buildFfCmdline(char *tokenPtr, *argv[]);
      |                                     ^
ffcliFront.c: In function ‘readConfigFile’:
ffcliFront.c:59:21: error: implicit declaration of function ‘buildFfCmdline’ [-Werror=implicit-function-declaration]
   59 |                     buildFfCmdline(tokenPtr, argv);
      |                     ^~~~~~~~~~~~~~
ffcliFront.c: At top level:
ffcliFront.c:69:37: error: expected declaration specifiers or ‘...’ before ‘*’ token
   69 | char buildFfCmdline(char *tokenPtr, *argv[])  {
      |                                     ^
cc1: all warnings being treated as errors
Thanks for any help.
 
Old 08-07-2019, 07:11 AM   #108
GazL
LQ Veteran
 
Registered: May 2008
Posts: 5,789

Rep: Reputation: 3705Reputation: 3705Reputation: 3705Reputation: 3705Reputation: 3705Reputation: 3705Reputation: 3705Reputation: 3705Reputation: 3705Reputation: 3705Reputation: 3705
9 and 69 are the same error: You forgot to specify a type for argv, i.e. char.

59 is caused by 9. Fix 9 and it will go away.

Last edited by GazL; 08-07-2019 at 07:16 AM.
 
1 members found this post helpful.
Old 08-07-2019, 08:08 AM   #109
jsbjsb001
Senior Member
 
Registered: Mar 2009
Location: Earth, unfortunately...
Distribution: Currently: OpenMandriva. Previously: openSUSE, PCLinuxOS, CentOS, among others over the years.
Posts: 3,827

Original Poster
Rep: Reputation: 2020Reputation: 2020Reputation: 2020Reputation: 2020Reputation: 2020Reputation: 2020Reputation: 2020Reputation: 2020Reputation: 2020Reputation: 2020Reputation: 2020
Thanks again GazL. That got it compiling, but I discovered a few more problems as a result, I think I've fixed one or two of them, but as soon as it gets into the buildFfCmdline() function, it's segfault's straight away. I tried to debug it with gdb, but because of the arguments it has, that makes it diffcult and I don't know how to do it with the arguments. As you can see, I tried an if statement for if tokenPtr was NULL, but it still segfaulted.

Code:
// includes
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdbool.h>

char readConfigFile(char *argv[]);
char buildFfCmdline(char *tokenPtr, char *argv[]);
//char execFfmpeg(char ffargs[]);

// main function
int main(int argc, char *argv[]) {
  
    if ( argc < 4 ) {
       fprintf (stderr, "Missing option or filename\nUSAGE: ffcliFront <format_id> <input_file> <output_file>\n");
       return 1;
    }
    
    // check if input file exists
    FILE *inputfile;
        
    if ( (inputfile = fopen(argv[2], "r")) == NULL ) {
       fprintf(stderr, "Input file not found, exiting.\n");
       return 1;        
    }
    fclose(inputfile);
          
    readConfigFile(argv);
    //readConfigFile(argv[1], argv[2]);

    return 0;
    
}

char readConfigFile(char *argv[]) {

    char configLine[128];
    char *tokenPtr;
    bool foundStr = false;
                  
    // read config file
    FILE *configfile;
      
    if ( (configfile = fopen("ffcliFront.conf", "r")) == NULL )  {
       fprintf(stderr, "Configuration file not found, exiting.\n");
       return 1;        
    }
    
    printf("argv[1] = %s\n", argv[1]);
       
    while( fgets(configLine, 128, configfile ) != NULL) {
          printf("Line from config file: %s\n", configLine);
          tokenPtr = strtok(configLine, ","); 
          int result = strcasecmp(tokenPtr, argv[1]);
          if ( result == 0)  {
             foundStr = true;
             printf("Found string: %s\ntokenPtr = %s\n", configLine, tokenPtr);
             buildFfCmdline(tokenPtr, argv);                    
          }
               
    }
    if (foundStr == false) {
       fprintf(stderr, "\"%s\" format_id not found in configuration file, exiting.\nCheck ffcliFront.conf for a valid format_id or specify a format_id that exists.\n", argv[1]);
       return 1;
    }
                
    fclose(configfile);
    return 0;
}
                   
char buildFfCmdline(char *tokenPtr, char *argv[]) {
    
    char *ffargs[128] = {0};
    int i = 0;
    
    strcpy(*ffargs, "-i ");
    strcat(*ffargs, argv[2]);
    printf("ffargs = %s\n", *ffargs);
    
    while( tokenPtr != NULL ) {
          tokenPtr = strtok(NULL, ","); 
          printf("Token: %s\n", tokenPtr);
          if (tokenPtr) {
             printf("tokenPtr = %s\n", tokenPtr);
             ++i;
             tokenPtr = ffargs[i];
             //strcat(ffargs, tokenPtr);
             //if (tokenPtr == NULL) {
                //break;
             //}
          }
          break;       
    }
    //strcat(ffargs, argv[3]); 
            
    printf("ffargs = %s\n", *ffargs);
        
   // pass char array with ffmpeg args & call execFfmpeg() fuction with args from config file
   // execFfmpeg(ffargs);
 
    return 0;
}      

//char execFfmpeg(char ffargs[]) {
  
    //char *ffcmdline[128];  
     
    //printf("%s\n", ffargs); 
    // run fmpeg with args from config file & filename supplied to this program. 
    // execv ("ffmpeg", ffcmdline);
	
    //return 0;
//}
This is what happens when I run the program;

Code:
james@jamespc: ffcliFront> ./ffcliFront test2 testinput out
argv[1] = test2
Line from config file: test, ffmpeg, ehe, te, teyeyyes, y, eye, yeh, eyh, eeee, eyeye, e, ey

Line from config file: test1, ffmpeg, ehe1, te, teyeyyes, y, eye, yeh, eyh, eeee, eyeye, e, ey

Line from config file: test2, ffmpeg, ehe2, te, teyeyyes, y, eye, yeh, eyh, eeee, eyeye, e, ey

Found string: test2
tokenPtr = test2
Segmentation fault (core dumped)
Thanks again for any help.
 
Old 08-07-2019, 08:17 AM   #110
rtmistler
Moderator
 
Registered: Mar 2011
Location: USA
Distribution: MINT Debian, Angstrom, SUSE, Ubuntu, Debian
Posts: 9,257
Blog Entries: 13

Rep: Reputation: 4350Reputation: 4350Reputation: 4350Reputation: 4350Reputation: 4350Reputation: 4350Reputation: 4350Reputation: 4350Reputation: 4350Reputation: 4350Reputation: 4350
Quote:
Originally Posted by jsbjsb001 View Post
Thanks again GazL. That got it compiling, but I discovered a few more problems as a result, I think I've fixed one or two of them, but as soon as it gets into the buildFfCmdline() function, it's segfault's straight away. I tried to debug it with gdb, but because of the arguments it has, that makes it diffcult and I don't know how to do it with the arguments. As you can see, I tried an if statement for if tokenPtr was NULL, but it still segfaulted.
You can use either of these forms:
Code:
$gdb --args <execute-file> <arg1> <arg2> ...
Or enter gdb using the execute file name as usual
Use the command "set args <arg> <arg> <arg>" at the gdb prompt

For either case, at the gdb prompt, you can also type "show args" to show the arguments
 
1 members found this post helpful.
Old 08-07-2019, 09:14 AM   #111
jsbjsb001
Senior Member
 
Registered: Mar 2009
Location: Earth, unfortunately...
Distribution: Currently: OpenMandriva. Previously: openSUSE, PCLinuxOS, CentOS, among others over the years.
Posts: 3,827

Original Poster
Rep: Reputation: 2020Reputation: 2020Reputation: 2020Reputation: 2020Reputation: 2020Reputation: 2020Reputation: 2020Reputation: 2020Reputation: 2020Reputation: 2020Reputation: 2020
Thank you RT, that was just the ticket.

So I run gdb a few times while playing around with the code in buildFfCmdline(), and it appears it's losing the line from the config file and it's just looping the value of argv[1] over and over again. Which I think explains the segfault, but I don't know how I'm supposed to fix the code though. Any ideas?

Code:
Reading symbols from ffcliFront...done.
(gdb) set args test2 testinput out
(gdb) b 79
Breakpoint 1 at 0x400a22: file ffcliFront.c, line 79.
(gdb) run
Starting program: /home/james/devel/ffcliFront/ffcliFront test2 testinput out
argv[1] = test2
Line from config file: test, ffmpeg, ehe, te, teyeyyes, y, eye, yeh, eyh, eeee, eyeye, e, ey

Line from config file: test1, ffmpeg, ehe1, te, teyeyyes, y, eye, yeh, eyh, eeee, eyeye, e, ey

Line from config file: test2, ffmpeg, ehe2, te, teyeyyes, y, eye, yeh, eyh, eeee, eyeye, e, ey

Found string: test2
tokenPtr = test2

Breakpoint 1, buildFfCmdline (tokenPtr=0x7fffffffe010 "test2", argv=0x7fffffffe1c8)
    at ffcliFront.c:79
79          printf("ffargs = %s\n", *ffargs);
(gdb) p tokenPtr
$1 = 0x7fffffffe010 "test2"
(gdb) n
ffargs = (null)
81          while( tokenPtr != NULL ) {
(gdb) p tokenPtr
$2 = 0x7fffffffe010 "test2"
(gdb) n
82                      strcpy(*ffargs, "-i ");
(gdb) p tokenPtr
$3 = 0x7fffffffe010 "test2"
(gdb) n

Program received signal SIGSEGV, Segmentation fault.
0x0000000000400a50 in buildFfCmdline (tokenPtr=0x7fffffffe010 "test2", argv=0x7fffffffe1c8)
    at ffcliFront.c:82
82                      strcpy(*ffargs, "-i ");
(gdb) q
A debugging session is active.

        Inferior 1 [process 15115] will be killed.

Quit anyway? (y or n) n
Not confirmed.
(gdb) n

Program terminated with signal SIGSEGV, Segmentation fault.
The program no longer exists.
Thanks in advance.
 
Old 08-07-2019, 09:29 AM   #112
rtmistler
Moderator
 
Registered: Mar 2011
Location: USA
Distribution: MINT Debian, Angstrom, SUSE, Ubuntu, Debian
Posts: 9,257
Blog Entries: 13

Rep: Reputation: 4350Reputation: 4350Reputation: 4350Reputation: 4350Reputation: 4350Reputation: 4350Reputation: 4350Reputation: 4350Reputation: 4350Reputation: 4350Reputation: 4350
Remove the * from the front of ffargs when you call it as part of string functions.

INCORRECT:
Code:
    strcpy(*ffargs, "-i ");
    strcat(*ffargs, argv[2]);
    printf("ffargs = %s\n", *ffargs);
CORRECT:
Code:
    strcpy(ffargs, "-i ");
    strcat(ffargs, argv[2]);
    printf("ffargs = %s\n", ffargs);
 
Old 08-07-2019, 09:45 AM   #113
jsbjsb001
Senior Member
 
Registered: Mar 2009
Location: Earth, unfortunately...
Distribution: Currently: OpenMandriva. Previously: openSUSE, PCLinuxOS, CentOS, among others over the years.
Posts: 3,827

Original Poster
Rep: Reputation: 2020Reputation: 2020Reputation: 2020Reputation: 2020Reputation: 2020Reputation: 2020Reputation: 2020Reputation: 2020Reputation: 2020Reputation: 2020Reputation: 2020
I tried what you said, but gcc keeps giving me a stack of warnings/errors every time I try to compile it.

Here's my code as it stands;

Code:
// includes
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdbool.h>

char readConfigFile(char *argv[]);
char buildFfCmdline(char *tokenPtr, char *argv[]);
//char execFfmpeg(char ffargs[]);

// main function
int main(int argc, char *argv[]) {
  
    if ( argc < 4 ) {
       fprintf (stderr, "Missing option or filename\nUSAGE: ffcliFront <format_id> <input_file> <output_file>\n");
       return 1;
    }
    
    // check if input file exists
    FILE *inputfile;
        
    if ( (inputfile = fopen(argv[2], "r")) == NULL ) {
       fprintf(stderr, "Input file not found, exiting.\n");
       return 1;        
    }
    fclose(inputfile);
          
    readConfigFile(argv);
    //readConfigFile(argv[1], argv[2]);

    return 0;
    
}

char readConfigFile(char *argv[]) {

    char configLine[128];
    char *tokenPtr;
    bool foundStr = false;
                  
    // read config file
    FILE *configfile;
      
    if ( (configfile = fopen("ffcliFront.conf", "r")) == NULL )  {
       fprintf(stderr, "Configuration file not found, exiting.\n");
       return 1;        
    }
    
    printf("argv[1] = %s\n", argv[1]);
       
    while( fgets(configLine, 128, configfile ) != NULL) {
           printf("Line from config file: %s\n", configLine);
           tokenPtr = strtok(configLine, ","); 
           int result = strcasecmp(tokenPtr, argv[1]);
           if ( result == 0)  {
              foundStr = true;
              printf("Found string: %s\ntokenPtr = %s\n", configLine, tokenPtr);
              buildFfCmdline(tokenPtr, argv);                    
           }
               
    }
    if (foundStr == false) {
       fprintf(stderr, "\"%s\" format_id not found in configuration file, exiting.\nCheck ffcliFront.conf for a valid format_id or specify a format_id that exists.\n", argv[1]);
       return 1;
    }
                
    fclose(configfile);
    return 0;
}
                   
char buildFfCmdline(char *tokenPtr, char *argv[]) {
    
    char *ffargs[128] = {0};
    int i = 0;
    
    strcpy(ffargs, "-i ");
    strcat(ffargs, argv[2]);
    printf("ffargs = %s\n", ffargs);
    
    while( tokenPtr != NULL ) {
           tokenPtr = strtok(NULL, ","); 
           printf("Token: %s\n", tokenPtr);
           if (tokenPtr) {
              printf("tokenPtr = %s\n", tokenPtr);
              ++i;
              tokenPtr = ffargs[i];
           }
                    
    }
    //strcat(ffargs, argv[3]); 
            
    printf("ffargs = %s\n", *ffargs);
        
    // pass char array with ffmpeg args & call execFfmpeg() fuction with args from config file
    // execFfmpeg(ffargs);
 
    return 0;
}      

//char execFfmpeg(char ffargs[]) {
  
    //char *ffcmdline[128];  
     
    //printf("%s\n", ffargs); 
    // run fmpeg with args from config file & filename supplied to this program. 
    // execv ("ffmpeg", ffcmdline);
	
    //return 0;
//}
Here's the errors from gcc when I try and compile;

Code:
james@jamespc: ffcliFront> gcc -g -Wall -Werror ffcliFront.c -o ffcliFront
ffcliFront.c: In function ‘buildFfCmdline’:
ffcliFront.c:78:12: error: passing argument 1 of ‘strcpy’ from incompatible pointer type [-Werror=incompatible-pointer-types]
   78 |     strcpy(ffargs, "-i ");
      |            ^~~~~~
      |            |
      |            char **
In file included from ffcliFront.c:4:
/usr/include/string.h:121:14: note: expected ‘char * restrict’ but argument is of type ‘char **’
  121 | extern char *strcpy (char *__restrict __dest, const char *__restrict __src)
      |              ^~~~~~
ffcliFront.c:79:12: error: passing argument 1 of ‘strcat’ from incompatible pointer type [-Werror=incompatible-pointer-types]
   79 |     strcat(ffargs, argv[2]);
      |            ^~~~~~
      |            |
      |            char **
In file included from ffcliFront.c:4:
/usr/include/string.h:129:14: note: expected ‘char * restrict’ but argument is of type ‘char **’
  129 | extern char *strcat (char *__restrict __dest, const char *__restrict __src)
      |              ^~~~~~
ffcliFront.c:80:23: error: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘char **’ [-Werror=format=]
   80 |     printf("ffargs = %s\n", ffargs);
      |                      ~^     ~~~~~~
      |                       |     |
      |                       |     char **
      |                       char *
cc1: all warnings being treated as errors
 
Old 08-07-2019, 10:11 AM   #114
GazL
LQ Veteran
 
Registered: May 2008
Posts: 5,789

Rep: Reputation: 3705Reputation: 3705Reputation: 3705Reputation: 3705Reputation: 3705Reputation: 3705Reputation: 3705Reputation: 3705Reputation: 3705Reputation: 3705Reputation: 3705
ffargs is an array of pointers. You can't strcpy into it because it only has enough space for a pointer and no memory allocated to store a string in. What you should be doing is something like ffargs[i++] = tokenPtr; where i is the item number of the array. The idea is that instead of copying the string, you make the pointer in the array point to the original.

To prepend your extra bits to the start of it, just point them to string literal/constant like this:
Code:
size_t i = 0;
ffargs[i++] = "/usr/bin/ffmpeg";
ffargs[i++] = "-i";
ffargs[i++] = argv[2];
Oh, and make ffargs[] 'static' or it's going to get put on the stack and then overwritten when your function exits.

Last edited by GazL; 08-07-2019 at 10:32 AM.
 
1 members found this post helpful.
Old 08-07-2019, 11:36 AM   #115
jsbjsb001
Senior Member
 
Registered: Mar 2009
Location: Earth, unfortunately...
Distribution: Currently: OpenMandriva. Previously: openSUSE, PCLinuxOS, CentOS, among others over the years.
Posts: 3,827

Original Poster
Rep: Reputation: 2020Reputation: 2020Reputation: 2020Reputation: 2020Reputation: 2020Reputation: 2020Reputation: 2020Reputation: 2020Reputation: 2020Reputation: 2020Reputation: 2020
I tried what you said, but I'm not sure I've done it right. As, I'm only getting the first string in ffargs[], and that's it.

Here's the code I've got now;

Code:
// includes
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdbool.h>

char readConfigFile(char *argv[]);
char buildFfCmdline(char *tokenPtr, char *argv[]);
//char execFfmpeg(char ffargs[]);

// main function
int main(int argc, char *argv[]) {
  
    if ( argc < 4 ) {
       fprintf (stderr, "Missing option or filename\nUSAGE: ffcliFront <format_id> <input_file> <output_file>\n");
       return 1;
    }
    
    // check if input file exists
    FILE *inputfile;
        
    if ( (inputfile = fopen(argv[2], "r")) == NULL ) {
       fprintf(stderr, "Input file not found, exiting.\n");
       return 1;        
    }
    fclose(inputfile);
          
    readConfigFile(argv);
   
    return 0;
    
}

char readConfigFile(char *argv[]) {

    char configLine[128];
    char *tokenPtr;
    bool foundStr = false;
                  
    // read config file
    FILE *configfile;
      
    if ( (configfile = fopen("ffcliFront.conf", "r")) == NULL )  {
       fprintf(stderr, "Configuration file not found, exiting.\n");
       return 1;        
    }
    
    printf("argv[1] = %s\n", argv[1]);
       
    while( fgets(configLine, 128, configfile ) != NULL) {
           printf("Line from config file: %s\n", configLine);
           tokenPtr = strtok(configLine, ","); 
           int result = strcasecmp(tokenPtr, argv[1]);
           if ( result == 0)  {
              foundStr = true;
              printf("Found string: %s\ntokenPtr = %s\n", configLine, tokenPtr);
              buildFfCmdline(tokenPtr, argv);                    
           }
               
    }
    if (foundStr == false) {
       fprintf(stderr, "\"%s\" format_id not found in configuration file, exiting.\nCheck ffcliFront.conf for a valid format_id or specify a format_id that exists.\n", argv[1]);
       return 1;
    }
                
    fclose(configfile);
    return 0;
}
                   
char buildFfCmdline(char *tokenPtr, char *argv[]) {
    
    static char *ffargs[128] = {0};
    size_t i = 0;
    
    ffargs[i++] = "/usr/bin/ffmpeg";
    ffargs[i++] = "-i ";
    ffargs[i++] = argv[2];
    printf("ffargs = %s\n", *ffargs);
    
    while( tokenPtr != NULL ) {
          tokenPtr = strtok(NULL, ","); 
          printf("Token: %s\n", tokenPtr);
          if  (tokenPtr) {
              printf("tokenPtr = %s\n", tokenPtr);
              ffargs[i++] = tokenPtr;
          }                
    }    
    printf("ffargs = %s\n", *ffargs);          
    // pass char array with ffmpeg args & call execFfmpeg() fuction with args from config file
    //execFfmpeg(ffargs);
 
    return 0;
}      

//char execFfmpeg(char ffcmdline[]) {
           
    //printf("ffargs = %s\n", *ffcmdline); 
    // run fmpeg with args from config file & filename supplied to this program. 
   // execv ("ffmpeg", *ffcmdline);
	
   // return 0;
//}
This is what I get;

Code:
james@jamespc: ffcliFront> ./ffcliFront test2 testinput out               
argv[1] = test2
Line from config file: test, ffmpeg, ehe, te, teyeyyes, y, eye, yeh, eyh, eeee, eyeye, e, ey

Line from config file: test1, ffmpeg, ehe1, te, teyeyyes, y, eye, yeh, eyh, eeee, eyeye, e, ey

Line from config file: test2, ffmpeg, ehe2, te, teyeyyes, y, eye, yeh, eyh, eeee, eyeye, e, ey

Found string: test2
tokenPtr = test2
ffargs = /usr/bin/ffmpeg
Token:  ffmpeg
tokenPtr =  ffmpeg
Token:  ehe2
tokenPtr =  ehe2
Token:  te
tokenPtr =  te
Token:  teyeyyes
tokenPtr =  teyeyyes
Token:  y
tokenPtr =  y
Token:  eye
tokenPtr =  eye
Token:  yeh
tokenPtr =  yeh
Token:  eyh
tokenPtr =  eyh
Token:  eeee
tokenPtr =  eeee
Token:  eyeye
tokenPtr =  eyeye
Token:  e
tokenPtr =  e
Token:  ey

tokenPtr =  ey

Token: (null)
ffargs = /usr/bin/ffmpeg
Line from config file: 

Line from config file: 

Line from config file:
 
Old 08-07-2019, 12:39 PM   #116
rtmistler
Moderator
 
Registered: Mar 2011
Location: USA
Distribution: MINT Debian, Angstrom, SUSE, Ubuntu, Debian
Posts: 9,257
Blog Entries: 13

Rep: Reputation: 4350Reputation: 4350Reputation: 4350Reputation: 4350Reputation: 4350Reputation: 4350Reputation: 4350Reputation: 4350Reputation: 4350Reputation: 4350Reputation: 4350
Inaccurate advice.

ffargs should not be "declared" as a pointer, because it already is when you declare it as an array.
Code:
char *ffargs[128];
Should instead be:
Code:
char ffargs[128];

Last edited by rtmistler; 08-07-2019 at 01:19 PM.
 
Old 08-07-2019, 12:42 PM   #117
rtmistler
Moderator
 
Registered: Mar 2011
Location: USA
Distribution: MINT Debian, Angstrom, SUSE, Ubuntu, Debian
Posts: 9,257
Blog Entries: 13

Rep: Reputation: 4350Reputation: 4350Reputation: 4350Reputation: 4350Reputation: 4350Reputation: 4350Reputation: 4350Reputation: 4350Reputation: 4350Reputation: 4350Reputation: 4350
Inaccurate advice Please follow what Gazl has recommended.

What you've coded there was "a pointer to an array of size 128 characters".

What instead ffargs should be is "an array of size 128 characters".

The huge difference there is the way I'm telling you to change it to, means you will have actual memory reserved for this array.

The way you have it declared, you only have memory allocated for a pointer to it.

If you wish an actual pointer that you can increment, you can do the following:
Code:
char anArray[128], *pArray = anArray;

or char anArray[128], *pArray = &anArray[0];  // same result, different notation

// Meanwhile you also can us anArray as a pointer, for the strcat/strcpy calls.

char anArray[128];

strcpy(anArray, "test string");
strcat(anArray, " this is added text.");

// Result: anArray[] contains "test string this is added text."
Code:
// Oddly you can get away with some weird notations that may confuse you, but are legal in the syntax:

char anArray[128], *pArray = anArray;

if(pArray[5] == 'b')   // You can use an index on that pointer, this is absolutely the same as
if(anArray[5] == 'b')  // PROVIDED that pArray still points to the start of anArray
Generally you should keep with the classical notations as opposed to trying to be fancy. There are times when you are working with multiple declarations for variables and you end up using a short cut for convenience, but mainly this can be avoided. As always, better to write clear code versus cute code.

Last edited by rtmistler; 08-07-2019 at 01:18 PM.
 
Old 08-07-2019, 01:02 PM   #118
GazL
LQ Veteran
 
Registered: May 2008
Posts: 5,789

Rep: Reputation: 3705Reputation: 3705Reputation: 3705Reputation: 3705Reputation: 3705Reputation: 3705Reputation: 3705Reputation: 3705Reputation: 3705Reputation: 3705Reputation: 3705
Quote:
Originally Posted by rtmistler View Post
ffargs should not be "declared" as a pointer, because it already is when you declare it as an array.
Code:
char *ffargs[128];
Should instead be:
Code:
char ffargs[128];
No. it's an array of pointers (just like argv). so char *ffargs[] is correct.
The problem is the printf that tries to access it as *ffargs when a loop is required. Something like this should do the trick:
Code:
for ( char **p = ffargs ; *p ; p++ )
            printf("arg: %s\n", *p);
or you can access individual elements with *ffargs[i]
 
2 members found this post helpful.
Old 08-07-2019, 01:17 PM   #119
rtmistler
Moderator
 
Registered: Mar 2011
Location: USA
Distribution: MINT Debian, Angstrom, SUSE, Ubuntu, Debian
Posts: 9,257
Blog Entries: 13

Rep: Reputation: 4350Reputation: 4350Reputation: 4350Reputation: 4350Reputation: 4350Reputation: 4350Reputation: 4350Reputation: 4350Reputation: 4350Reputation: 4350Reputation: 4350
Quote:
Originally Posted by GazL View Post
No. it's an array of pointers (just like argv). so char *ffargs[] is correct.
Missed that the first time you said it.
++
 
1 members found this post helpful.
Old 08-08-2019, 12:49 AM   #120
jsbjsb001
Senior Member
 
Registered: Mar 2009
Location: Earth, unfortunately...
Distribution: Currently: OpenMandriva. Previously: openSUSE, PCLinuxOS, CentOS, among others over the years.
Posts: 3,827

Original Poster
Rep: Reputation: 2020Reputation: 2020Reputation: 2020Reputation: 2020Reputation: 2020Reputation: 2020Reputation: 2020Reputation: 2020Reputation: 2020Reputation: 2020Reputation: 2020
Thanks guys!

So I've added the for loop, and it's looking good. I've also got rid of some of the other printf debugging statements, as the for loop verifies that we have what we need in ffargs[]. I've also replaced the fopen() for the input file with the access() function as well, and that seems to be working as intended. So now I guess it's just the final piece of the puzzle to finish my little program off, execute ffmpeg with the args from the relevant line in it's config file.

Here's what the code looks like now;

Code:
// includes
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdbool.h>

char readConfigFile(char *argv[]);
char buildFfCmdline(char *tokenPtr, char *argv[]);
//char execFfmpeg(char ffargs[]);

// main function
int main(int argc, char *argv[]) {
  
    if ( argc < 4 ) {
       fprintf (stderr, "Missing option or filename\nUSAGE: ffcliFront <format_id> <input_file> <output_file>\n");
       return 1;
    }
    
    // check if input file can be read, and if not, abort program execution - no point in continuing execution in that case...
    int access_return = access(argv[2], R_OK);
    if ( access_return == -1) {
       fprintf(stderr, "Input file cannot be read, aborting.\nDoes it exist?\n");
       exit (1);
    }
          
    readConfigFile(argv);
   
    return 0;    
}

char readConfigFile(char *argv[]) {

    char configLine[128];
    char *tokenPtr;
    bool foundStr = false;
                  
    // read config file
    FILE *configfile;
      
    if ( (configfile = fopen("ffcliFront.conf", "r") ) == NULL )  {
       fprintf(stderr, "Configuration file not found, exiting.\n");
       return 1;        
    }
    
    printf("argv[1] = %s\n", argv[1]);
       
    while( fgets(configLine, 128, configfile ) != NULL) {
          printf("Line from config file: %s\n", configLine);
          tokenPtr = strtok(configLine, ","); 
          int result = strcasecmp(tokenPtr, argv[1]);
          if ( result == 0 ) {
             foundStr = true;
             printf("Found string: %s\ntokenPtr = %s\n", configLine, tokenPtr);
             buildFfCmdline(tokenPtr, argv);                    
          }
               
    }
    if (foundStr == false) {
       fprintf(stderr, "\"%s\" format_id not found in configuration file, exiting.\nCheck ffcliFront.conf for a valid format_id or specify a format_id that exists.\n", argv[1]);
       return 1;
    }
                
    fclose(configfile);
    return 0;
}
                   
char buildFfCmdline(char *tokenPtr, char *argv[]) {
    
    static char *ffargs[128] = {0};
    size_t i = 0;
    
    ffargs[i++] = "/usr/bin/ffmpeg";
    ffargs[i++] = "-i ";
    ffargs[i++] = argv[2];
        
    while( tokenPtr != NULL ) {
          tokenPtr = strtok(NULL, ","); 
          if (tokenPtr) {
             ffargs[i++] = tokenPtr;
          }                
    }
    
    for ( char **p = ffargs ; *p ; p++ ) {
        printf("arg: %s\n", *p);
    }
               
    //pass char array with ffmpeg args & call execFfmpeg() fuction with args from config file
    //execFfmpeg(ffargs);
 
    return 0;
}      

//char execFfmpeg(char ffcmdline[]) {
           
    //printf("ffargs = %s\n", *ffcmdline); 
    //run fmpeg with args from config file & filename supplied to this program. 
    //execv ("ffmpeg", *ffcmdline);
	
    //return 0;
//}
So if I don't specify a input file that actually exists;

Code:
james@jamespc: ffcliFront> ./ffcliFront test2 testinpu out
Input file cannot be read, aborting.
Does it exist?
If I specify a format_id that doesn't exist in the config file;

Code:
james@jamespc: ffcliFront> ./ffcliFront tes testinput out
argv[1] = tes
Line from config file: test, ffmpeg, ehe, te, teyeyyes, y, eye, yeh, eyh, eeee, eyeye, e, ey

Line from config file: test1, ffmpeg, ehe1, te, teyeyyes, y, eye, yeh, eyh, eeee, eyeye, e, ey

Line from config file: test2, ffmpeg, ehe2, te, teyeyyes, y, eye, yeh, eyh, eeee, eyeye, e, ey

Line from config file: 

Line from config file: 

Line from config file: 

"tes" format_id not found in configuration file, exiting.
Check ffcliFront.conf for a valid format_id or specify a format_id that exists.
And finally, if we specify the correct args;

Code:
james@jamespc: ffcliFront> ./ffcliFront test2 testinput out
argv[1] = test2
Line from config file: test, ffmpeg, ehe, te, teyeyyes, y, eye, yeh, eyh, eeee, eyeye, e, ey

Line from config file: test1, ffmpeg, ehe1, te, teyeyyes, y, eye, yeh, eyh, eeee, eyeye, e, ey

Line from config file: test2, ffmpeg, ehe2, te, teyeyyes, y, eye, yeh, eyh, eeee, eyeye, e, ey

Found string: test2
tokenPtr = test2
arg: /usr/bin/ffmpeg
arg: -i 
arg: testinput
arg:  ffmpeg
arg:  ehe2
arg:  te
arg:  teyeyyes
arg:  y
arg:  eye
arg:  yeh
arg:  eyh
arg:  eeee
arg:  eyeye
arg:  e
arg:  ey

Line from config file: 

Line from config file: 

Line from config file:
So looking good!

Thanks again guys!
 
1 members found this post helpful.
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
[SOLVED] virtualbox installs pcbsd again and again and again straffetoebak Linux - Virtualization and Cloud 4 11-21-2014 07:14 PM
LXer: Do you want a serious—I mean serious—developer laptop? Then Dell and Ubuntu have the system fo LXer Syndicated Linux News 0 11-29-2012 03:30 PM
Firefox...I have tried and tried... Basslord1124 Fedora 4 10-29-2004 11:51 PM
my ps/2's wheel doesn't work. tried and tried but failed. Choey Linux - Hardware 5 09-17-2003 06:47 PM
I have tried and tried, I really have! Ewen Linux - General 13 01-14-2003 11:31 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 02:55 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration