[SOLVED] Tried to write something "serious" and have failed once again
ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Introduction to Linux - A Hands on Guide
This guide was created as an overview of the Linux Operating System, geared toward new users as an exploration tour and getting started guide, with exercises at the end of each chapter.
For more advanced trainees it can be a desktop reference, and a collection of the base knowledge needed to proceed with system and network administration. This book contains many real life examples derived from the author's experience as a Linux system and network administrator, trainer and consultant. They hope these examples will help you to get a better understanding of the Linux system and that you feel encouraged to try out things on your own.
Click Here to receive this Complete Guide absolutely free.
// 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);
}
...
if ( (configfile = fopen("ffcliFront.conf", "r") ) == NULL ) {
Perhaps an incremental change you ought to consider is to actually use the program argument you have validated versus a hard-coded file name.
Test case #1 would be to pass in the name of your config file and verify that it continues to work.
Distribution: Currently: OpenMandriva. Previously: openSUSE, PCLinuxOS, CentOS, among others over the years.
Posts: 3,827
Original Poster
Rep:
I'm sorry, I'm not following you RT. The input file and the config file are two different things for two different purposes. The input file (argv[2]) is the filename that's passed to ffmpeg, the config file (ffcliFront.conf) is for the program to get the arguments from to pass to ffmpeg, AFTER the input filename.
Anyway, I've got good news and bad news. The good news is that, I managed to get my program to send the args to the function that executes ffmpeg and passes the args from the config file to ffmpeg. And execute ffmpeg from my program, with the args in the ffargs array. But it doesn't seem to passing them to ffmpeg properly. Basically ffmpeg complains about the same arguments from my program, but if I run ffmpeg directly at the command-line with exactly the same arguments, it does "see" them properly. Admittedly, I had a "presets" file from WinFF laying around, so I just copied and pasted some lines from that. So while the version of ffmpeg I have doesn't seem to have the "hq" preset, ffmpeg should be giving a different message complaining about that to the one it's giving. I've got a strong feeling the problem is related to the output file arg (argv[3]).
Also, I've been trying to figure out how to get my program to display an error message and quit, if say for example you were to only have the format_id (argv[1]) in the config file, but nothing after it, like for example just "test, ", and that's it (no args to be passed to ffmpeg), but I cannot get anything I try to work - it either doesn't make any difference and uploads the line into the array anyway, or it issues the error message even when the line is a valid one. I ended up giving up, but it would be nice for my program to be able to detect lines that only have a string for the format_id (argv[1]), but nothing after it, and be able to issue an error and quit.
On the upside, I've added some code to hopefully deal with comments - so they should be ignored.
Anyway, this is what happens when I use my program to launch ffmpeg;
When you run strtok, make sure that you're also using space and \n as delimiters. It looks like your "-threads" "0" was actually a "-threads" "0\n" there because of the \n on the end of the line and that is likely upsetting ffmpeg.
fgets() doesn't strip \n from the input.
Try:
strtok(NULL, ", \n")
Note: there is a space character in there, it's not very obvious when posted on LQ.
You might want to change that on all strtoks.
Also, though the above will fix it:
-acodec libmp3lame, isn't one arg, it's two.
Distribution: Currently: OpenMandriva. Previously: openSUSE, PCLinuxOS, CentOS, among others over the years.
Posts: 3,827
Original Poster
Rep:
I tried what you said, but I'm still having the same problem. The args printed out by the for loop look better as you'll see in my output below, but even if I copy a video into the same folder as my program, ffmpeg still complains with the same error message anyway. But interesingly if I specify my empty text file (testinput) as the input file for ffmpeg, it sees that it isn't a valid video/audio file and complains with the relevant message (as you'll see below). Also, if I put a comma after every single arg in the first in my config file, like "-threads, 0", it complains "thread" isn't a valid option, and therefore misses the "s 0" after the word thread. But just having for example "-threads 0" (and the same for every other option, <-option_name_here> <value_here> then it does include all of the options in the array passed to ffmpeg.
The only code I've changed in my program is what you said above for strtok, so;
(and the bash cursor goes red as well - but then changes back to it's normal color after I hit enter/enter in another command. As the very last line/error message from ffmpeg in the output above is in red)
Here's what happens with my dummy "testinput" file (which is just an empty text file);
by doing so, the '-i' becomes the argv[0] of the ffmpeg execv() and gets ignored as an argument by ffmpeg.
I'd also recommend not using ',' as a field separator in your config file as some ffmpeg options do use it. It's not a problem with your existing config lines but it might catch you out in the future.
Using a ':' as terminator for your label (but not the arguments) might be a good idea, as that's a pretty common way of writing config files, so I'll suggest that also.
Finally, some of your ffmpeg options are old syntax. -acodec -vcodec rather than -c:a -c:v. You might want to update them to use the more modern ffmpeg options. I'd recommend searching for examples on ffmpeg.org.
Distribution: Currently: OpenMandriva. Previously: openSUSE, PCLinuxOS, CentOS, among others over the years.
Posts: 3,827
Original Poster
Rep:
Well, I've got some good news - it's passing the args to ffmpeg correctly!!! And it works, it f***ing works!!!!
Thanks you so much GazL!!! I couldn't have done without you guys!!
So before I post the updated code and the WORKING output; I'll just try and explain what I done... I uncommented the line you were talking about above GazL, so that was the first "breakthrough moment". Then I changed the delimiter (I think that's the right name for it - the comma that separates the args for ffmpeg with a semi-colon), and I also removed the newline character from the first strtok() call in the readConfigFile() function. I was reading the main() function for 0ad, and remembered seeing the code where it checks if you are trying to run it as root, so I added a check for that too. I figured since geteuid() gets the "effective user ID", that sounded like the way to go (yes, I did read it's very short man page too ). As we don't want it run as root!
Now I was wondering how I would get it to actually check that there is actually some args specified after the format_id string? So in the updated ffcliFront.conf below, you'll notice that the last line just has "test3;", and that's it - meaning no args would be passed to ffmpeg if you run my program as ffcliFront test3 <input file> <output file>
Also, while it might be a little off-topic (I'll take the blame for that in advance mod's ); I've been meaning to ask, when you guys first started out programming; how did ya's get to the point of being able to read code for complex stuff, like say ffmpeg itself, and be able to follow it? Because I've tried, but I just end up getting completely overwhelmed, then lose track of where I'm even up to - if ya's know what I mean.
And one more thing; since I've got it working now, I wouldn't mind seeing how you done it GazL (if you still have that code of course)
Here's what the config file (ffcliFront.conf) looks like now (the args at least for the first arg line do work, and are correct - I checked);
Yes, no problem, I've still got it. I'll upload mine as a diff against an empty directory so you can extract it to an empty directory easily with patch < ffclifront.diff.txt or view it as is.
I wouldn't have normally used a static for the array or configLine, and I would have used getline() instead of fgets(), but I was trying to keep close to the way you were working knowing that you've not got into using heap memory (mallocs and suchlike) yet.
There's not a whole lot of difference between our approaches. The main one being that in mine the functions are both called from main rather than chaining one from the other and I make more use of function returns because of that.
Oh, and I've included my enhanced strtok_q functions that can handle basic quoting in case that interests you for later. It's a first draft so there might be better ways to do it, but it seems to work.
As for reading other people's code, it depends on who's written it. There's stuff out there that I simply can't fathom, but it comes with practice.
I didn't worry about the empty config line case on mine as ffmpeg -i infile outfile is actually a valid command, but you could just check the number of args after you've assembled the array if you want to stop that from happening.
Anyway, congrats on your progress, and enjoy.
edit: and just to be a good example, I'll cop to missing something and admit that I should have included this just in case someone plays silly buggers.
I avoided strdup() and getline() specifically because jsb has been avoiding anything involving dynamic allocation so far, but certainly a nicer way to do it.
Distribution: Currently: OpenMandriva. Previously: openSUSE, PCLinuxOS, CentOS, among others over the years.
Posts: 3,827
Original Poster
Rep:
Thanks NevemTeve, but I couldn't figure out how to incorporate your code into even just the little program I wrote to figure out how to use strtok(), etc (without using any command-line args, etc). I'm not sure I even understand exactly what your code is doing beyond the obvious. Everything I tried just ended in a stack of errors. But thanks again for your help tho.
Quote:
Originally Posted by GazL
I avoided strdup() and getline() specifically because jsb has been avoiding anything involving dynamic allocation so far, but certainly a nicer way to do it.
I do want to learn how to do "dynamic memory allocation" - so I'll try and "dynamically allocate" the ffargs array in my program above (and have a look at the strdup() and getline() functions).
I had a look at your code attached above, but while it wasn't too bad trying to understand it; I think some of it is probably beyond my skill level at this point. But thanks again for all of your help though GazL!
Distribution: Currently: OpenMandriva. Previously: openSUSE, PCLinuxOS, CentOS, among others over the years.
Posts: 3,827
Original Poster
Rep:
So I was playing with calloc(), and while I was able to dynamically allocate memory; I cannot figure out how to get it to check if the array size needs to be reallocated with realloc(). Basically, if I set the array size to 10, then depending on whether I use the greater than or less than operator, it either doesn't change the size from the original size or it changes the size even if the contents of the input file doesn't change/it's still uploading the same thing into the array. But if I set the array size to 1, calloc() goes crazy and I see what looks like an infinite loop. I wrote a separate program just to try and figure out calloc before I modify ffcliFront. I really don't understand what's going on here.
...
Line from file:
Line from file:
Line from file:
Line from file:
Line from file:
Line from file:
Line from file:
Line from file:
Line from file:
Line from file:
Line from file:
^C
Distribution: Currently: OpenMandriva. Previously: openSUSE, PCLinuxOS, CentOS, among others over the years.
Posts: 3,827
Original Poster
Rep:
Quote:
Originally Posted by rtmistler
Have you used gdb to debug that code?
Yes, but other than it's reporting nothing in the array, and what I've already said; I'm no closer to knowing what's going on. And yes RT, I did read the man page, I even looked at the example jpollard gave me from my other thread in this particular forum, and I cannot see where I'm going wrong. The only other thing I've discovered is that it's happening as soon as it gets to the while loop (which I suspected before anyway) - as I commented out the if statement that run realloc(), and it still goes crazy on me.
Quote:
Have you verified you're using all library functions correctly and are properly qualifying return values?
Honestly RT, I don't know nor have a clue if I am or not at this point. I haven't used the dynamic memory allocation functions much before this attempt - I even went back and read what Hazel said earlier on in this thread about "dynamic memory allocation".
So any insight you can give me will be appreciated. Thanks in advance if you would be so kind.
Distribution: Currently: OpenMandriva. Previously: openSUSE, PCLinuxOS, CentOS, among others over the years.
Posts: 3,827
Original Poster
Rep:
Thank you RT. Your comment caused me to look elsewhere in my code, and I noticed the array size was 1, so I changed that, and it stopped the infinite loop. So I assume that was upsetting fgets() ? In any case, I was trying to resize the array with realloc(), so I could try and figure out how to do dynamic memory allocation in ffcliFront above, before making any changes to ffcliFront before I'd figured it out.
Anyways, I've adjusted, and added to my code, and realloc() just increases the size of the array anyway. Even if I have less that 10 elements in the file the code looks at. So how do I get it to only change the array size IF, and ONLY IF there is more than 10 elements (whatever is specified in the arraySize variable) ? As this isn't making sense to me, and nothing I seem to do seems to work.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.