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 |
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.
Are you new to LinuxQuestions.org? Visit the following links:
Site Howto |
Site FAQ |
Sitemap |
Register Now
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.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
|
 |
01-22-2011, 05:09 PM
|
#1
|
Member
Registered: Jun 2009
Posts: 42
Rep:
|
read a text file distrubute its contents on different text files
Hello,
How can read the file /var/etc/allInOne.cfg and distribute its contents on multiple cfg files using C language. /var/etc/allInOne.cfg contain the data and the path of each text file.
the source file "/var/etc/allInOne.cfg "look like this:
line1
line2
...
line10
filePath:/var/etc/file1.cfg
line12
line13
...
line14
filePath:/var/etc/file2.cfg
linen
..
filePath:/var/etc/filen.cfg
the result will be :
the expected result is :
/var/etc/file1.cfg will contain line1 to line10
/var/etc/file2.cfg will contain line 12 to line13
/var/etc/filen.cfg will contain linen to linen-1
best regards
|
|
|
Click here to see the post LQ members have rated as the most helpful post in this thread.
|
01-22-2011, 07:22 PM
|
#2
|
Member
Registered: Dec 2010
Posts: 281
Rep:
|
<stdio.h>
Your loop will have to be based on how you determine the splits.
Ask yourself:
How many lines between each split? Or will there be a flag... be it a specific character or string or some other variable...
Look into all that <stdio.h> can do for you...
http://www.acm.uiuc.edu/webmonkeys/b...uide/2.12.html
http://www.lix.polytechnique.fr/~lib...NS/funcref.htm
Most of the work can be done using fscanf() and fprintf().
Last edited by cin_; 01-22-2011 at 07:24 PM.
Reason: gramm'err
|
|
|
01-23-2011, 05:45 AM
|
#3
|
Senior Member
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
|
You'll need fopen, getline (or fgets and realloc), sscanf, fputs, fclose, rename, and remove from the standard I/O library stdio.h header file, to do this robustly and without undue limitations on e.g. line length. (Do not try to use fscanf for this, though; you'll just mangle the input.)
It would be more robust to use strncmp or strncasecmp and strspn and strcspn functions from the string.h header file, instead of the sscanf function.
For proper error handling, use ferror from the stdio.h header, strerror from the string.h header, and errno from the errno.h header.
Since your target file is defined after the related lines, you'd best read the lines one by one, and output them into a temporary file, unless the line is a target file directive. When such lines are read, just move (rename) the temporary file to the desired location. Remember to close the old file, and create a new temporary file for future lines. Also remember to close and remove the last temporary file after processing all input; it'll most likely be empty, but it might contain one or more empty lines.
(Normally, the target file is defined before the lines. In that case, you could open and write to the target file first, and not need to use any temporary files.)
Nominal Animal
Last edited by Nominal Animal; 03-21-2011 at 05:59 AM.
|
|
2 members found this post helpful.
|
01-23-2011, 08:39 AM
|
#4
|
Member
Registered: Jun 2009
Posts: 42
Original Poster
Rep:
|
Quote:
Originally Posted by Nominal Animal
You'll need fopen, getline (or fgets and realloc), sscanf, fputs, fclose, rename, and remove from the standard I/O library stdio.h header file, to do this robustly and without undue limitations on e.g. line length. (Do not try to use fscanf for this, though; you'll just mangle the input.)
It would be more robust to use strncmp or strncasecmp and strspn and strcspn functions from the string.h header file, instead of the sscanf function.
For proper error handling, use ferror from the stdio.h header, strerror from the string.h header, and errno from the errno.h header.
Since your target file is defined after the related lines, you'd best read the lines one by one, and output them into a temporary file, unless the line is a target file directive. When such lines are read, just move (rename) the temporary file to the desired location. Remember to close the old file, and create a new temporary file for future lines. Also remember to close and remove the last temporary file after processing all input; it'll most likely be empty, but it might contain one or more empty lines.
(Normally, the target file is defined before the lines. In that case, you could open and write to the target file first, and not need to use any temporary files.)
Nominal Animal
|
I apreciate a lot your hints.
I can define the target file before the lines, this is not a big issue.
Here is a snipet code :
Code:
FILE *fsp,*fdp;
char *line = NULL;
size_t len = 0;
ssize_t read;
fsp = fopen("/var/tmp/source.cfg", "r");
fdp = fopen("/var/tmp/temp.cfg", "w");
if (fsp == NULL)
exit(EXIT_FAILURE);
if (fdp == NULL)
exit(EXIT_FAILURE);
while ((read = getline(&line, &len, fsp)) != -1) {
//printf("Retrieved line of length %zu :\n", read);
//printf("%s", line);
if (strstr(line, "/var/")) {
//Close the fdp file
fclose(fdp);
//get the path from line here
//how can i extract the path here and pass it to the rename function
//Move the temp file
rename("/var/tmp/temp.cfg", myNewPath); //problem here
//Delete the temp file
remove("/var/tmp/temp.cfg");
//open the temp file
fdp = fopen("/var/tmp/temp.cfg", "w");
if (fdp == NULL)
exit(EXIT_FAILURE);
}
else {
fprintf(fdp,"%s",line); /*writes data to the file*/
}
}
//close the source file
fclose(fsp);
fclose(fdp);
//free the pointer line
free(line);
|
|
|
01-23-2011, 10:59 AM
|
#5
|
Senior Member
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
|
A nice start, magische_vogel. I especially like how you're using getline() to avoid line length limits.
In the inner loop, it is better to try to parse the line (non-destructively) to see if it contains a directive to write to a new file.
Here's a snippet of my own you might find helpful:
Code:
FILE *in; /* Handle to source configuration file */
FILE *out = NULL; /* Handle to new configuration file */
char *name = NULL; /* Dynamically allocated file name */
char *line = NULL;
size_t len = 0;
ssize_t read;
int noff, nend, errors;
char dummy;
...
while (1) {
read = getline(&line, &len, in);
if (read == (ssize_t)-1)
break;
noff = nend = -1;
if (sscanf(line, "configfile: %n%*s%n%c", &noff, &nend, &dummy) > 0 ||
sscanf(line, "configfile: '%n%*[^']%n'%c", &noff, &nend, &dummy) > 0 ||
sscanf(line, "configfile: \"%n%*[^\"]%n\"%c", &noff, &nend, &dummy) > 0) {
if (nend > noff && noff >= 0) {
/* Close old output file, if open. */
if (out) {
errors = 0;
if (ferror(out)) errors++;
if (fclose(out)) errors++;
if (errors) {
fprintf(stderr, "%s: Error closing file.\n", (name) ? name: "(null)");
exit(1);
}
}
/* Release old dynamically allocated file name. */
if (name) {
free(name);
name = NULL;
}
/* Copy new file name. */
dummy = line[nend];
line[nend] = 0;
name = strdup(line + noff);
line[nend] = dummy;
if (!name || !*name) {
fprintf(stderr, "Cannot parse config file name!\n");
exit(1);
}
if (access(name, F_OK) == 0) {
fprintf(stderr, "%s: File already exists.\n", name);
exit(1);
}
out = fopen(name, "wb");
if (!out) {
fprintf(stderr, "%s: Cannot create new config file.\n", name);
exit(1);
}
/* Okay, this line has been processed. */
continue;
}
}
/* Save line to out */
if (out) {
fputs(line, out);
continue;
}
/* No output file. Is the line empty? */
if (strspn(line, "\t\n\v\f\r ") == (size_t)read)
continue;
fprintf(stderr, "Hey! Input given, but no config file!\n");
exit(1);
}
if (out) {
errors = 0;
if (ferror(out)) errors++;
if (fclose(out)) errors++;
if (errors) {
fprintf(stderr, "%s: Error closing file.\n", (name) ? name : "(null)");
exit(1);
}
}
if (name) {
free(name);
name = NULL;
}
if (line) {
free(line);
len = 0;
}
The above also allows you to specify the filename quoted. It is a good practice to free all dynamically allocated memory, like I do after the loop. Also note how name is always dynamically allocated via strdup, so we need to remember to free it too.
I sometimes avoid using sscanf() for this kind of parsing, because for this to work, the line must contain a newline (or at least some other character after the file name), to match the trailing %c ("any single character"). Without it, sscanf() will return zero, and it's impossible to say whether it matched the final delimiter or not: stupid standard indicates %n is not counted. If it were counted, sscanf() would much more useful.
On the other hand, sscanf() is much easier to use, and much sorter, than parsing with strspn(), strcspn(), strpbrk() et al.
Nominal Animal
Last edited by Nominal Animal; 03-21-2011 at 05:53 AM.
|
|
1 members found this post helpful.
|
01-23-2011, 11:34 AM
|
#6
|
Senior Member
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
|
Quote:
Originally Posted by magische_vogel
Code:
//how can i extract the path here and pass it to the rename function
|
The way I did it in my example uses sscanf to get the offsets where the path starts and ends; the dummy variable is needed to make sure sscanf() returns a positive value if a match has occurred:
Code:
int noff, int nend;
char dummy;
noff = nend = -1;
if (sscanf(line, "configfile: %n%*s%n%c", &noff, &nend, &dummy) > 0) {
if (nend > noff && noff >= 0) {
/* name starts at (line + noff), ends at (line + nend);
* character line[nend] is after the name, and not a part of it.
*/
}
}
My snippet tries three different sscanf() commands: Normal (space-delimited), single-quoted, and double-quoted. In the sscanf pattern: - %n saves the current offset from the start of the string, but is not counted.
- %*s matches a single word, but does not save it, and is not counted.
- %c matches and saves a single character, and is counted if it matches.
- %*[^'] matches anything except a single quote, but does not save it, and is not counted.
- Normal text is matched exactly, but is not counted.
- Spaces mean optional whitespace of any length; you don't have to put whitespace after the colon in the configuration file.
Due to the above rules, if line is "blah\n", then sscanf(line, "b l a h%c", &dummy) will match fully and return 1, saving the newline in dummy.
Yes, sscanf is a bit weird, but you get used to it.
Since line is reused when the next line is read, it's best to use strdup() to get a dynamically allocated copy, instead of using the one embedded in line. But remember to set line[nend] temporarily to 0, or you'll duplicate the rest of the line. Or use name = strndup(line + noff, nend - noff);
Nominal Animal
Last edited by Nominal Animal; 03-21-2011 at 07:41 AM.
|
|
1 members found this post helpful.
|
01-23-2011, 02:39 PM
|
#7
|
Member
Registered: Jun 2009
Posts: 42
Original Poster
Rep:
|
Quote:
Originally Posted by Nominal Animal
The way I did it in my example uses sscanf to get the offsets where the path starts and ends; the dummy variable is needed to make sure sscanf() returns a positive value if a match has occurred:
Code:
int noff, int nend;
char dummy;
noff = nend = -1;
if (sscanf(line, "configfile: %n%*s%n%c", &noff, &nend, &dummy) > 0) {
if (nend > noff && noff >= 0) {
/* name starts at (line + noff), ends at (line + nend);
* character line[nend] is after the name, and not a part of it. */
}
}
My snippet tries three different sscanf() commands: Normal (space-delimited), single-quoted, and double-quoted. In the sscanf pattern: - %n saves the current offset from the start of the string, but is not counted.
- %*s matches a single word, but does not save it, and is not counted.
- %c matches and saves a single character, and is counted if it matches.
- %*[^'] matches anything except a single quote, but does not save it, and is not counted.
- Normal text is matched exactly, but is not counted.
- Spaces mean optional whitespace of any length; you don't have to put whitespace after the colon in the configuration file.
Due to the above rules, if line is "blah\n", then sscanf(line, "b l a h%c", &dummy) will match fully and return 1, saving the newline in dummy.
Yes, sscanf is a bit weird, but you get used to it.
Since line is reused when the next line is read, it's best to use strdup() to get a dynamically allocated copy, instead of using the one embedded in line. But remember to set line[nend] temporarily to 0, or you'll duplicate the rest of the line. Or use name = strndup(line + noff, nend - noff);
Nominal Animal
|
Here is a sample source (the in file is "/tmp/allInOne.cfg") file:
configfile:"/tmp/db.cfg"
[db]
label = server01
protocol = tcp
device = xxx.xxx.net,5813
account = bla1,bla1
group = 1
priv = 1
dbdversion = 0.1.5
dbdbuild = 3265
dbdmaxcon = 1
[db]
label = server03
protocol = tcp
device = xxx.xxx.biz,5714
account = bla3,bla3
group = 1
priv = 0
dbdversion = 0.1.5
dbdbuild = 3265
dbdmaxcon = 1
[db]
label = server01
protocol = tcp
device = xxx.xxx.com,5615
account = bla,bla
group = 1
priv = 0
dbdversion = 0.1.5
dbdbuild = 3265
dbdmaxcon = 1
configfile:"/tmp/global.cfg"
[account]
user = user
group = 1
ac = server01
[account]
user = user
group = 1
au = server03
[account]
user = user
group = 1
ac = server05
the expected result in this case is 2 output files :
the 1st output file should be created in : /tmp/db.cfg
and the 2nd output file should be created in : /tmb/global.cfg
Code:
FILE *in; /* Handle to source configuration file */
FILE *out = NULL; /* Handle to new configuration file */
char *name = NULL; /* Dynamically allocated file name */
char *line = NULL;
size_t len = 0;
ssize_t read;
int noff, nend, errors;
char dummy;
in = fopen("/tmp/allInOne.cfg","rt");
while (1) {
read = getline(&line, &len, in);
if (read == (ssize_t)-1) break;
noff = nend = -1;
if (sscanf(line, "configfile: %n%*s%n%c", &noff, &nend, &dummy) > 0 ||
sscanf(line, "configfile: '%n%*[^']%n'%c", &noff, &nend, &dummy) > 0 ||
sscanf(line, "configfile: \"%n%*[^\"]%n\"%c", &noff, &nend, &dummy) > 0) {
if (nend > noff && noff >= 0) {
/* Close old output file, if open. */
if (out) {
errors = 0;
if (ferror(out)) errors++;
if (fclose(out)) errors++;
if (errors) {
fprintf(stderr, "%s: Error closing file.\n", (name) ? name: "(null)");
exit(1);
}
}
/* Release old dynamically allocated file name. */
if (name) { free(name); name = NULL; }
/* Copy new file name. */
dummy = line[nend];
line[nend] = 0;
name = strdup(line + noff);
line[nend] = dummy;
if ( !name || !*name) { fprintf(stderr, "Cannot parse config file name!\n"); exit(1); }
if (access(name, F_OK) == 0) { fprintf(stderr, "%s: File already exists.\n", name); exit(1); }
out = fopen(name, "wt");
if (!out) { fprintf(stderr, "%s: Cannot create new config file.\n", name); exit(1); }
/* Okay, this line has been processed. */
continue;
}
}
/* Save line to out */
if (out) { fputs(line, out); continue; }
/* No output file. Is the line empty? */
if (strspn(line, "\t\n\v\f\r ") == (size_t)read) continue;
fprintf(stderr, "Hey! Input given, but no config file!\n"); exit(1);
}
//if (in) { errors = 0; if (ferror(in)) errors++; if (fclose(in)) errors++; if (errors) { fprintf(stderr, "%s: Error closing file.\n", (name) ? name : "(null)"); exit(1); } }
if (out) { errors = 0; if (ferror(out)) errors++; if (fclose(out)) errors++; if (errors) { fprintf(stderr, "%s: Error closing file.\n", (name) ? name : "(null)"); exit(1); } }
if (name) { free(name); name = NULL; }
if (line) { free(line); len = 0; }
unfortunately it is not working for me.
ps:The target file is defined before the lines now.
Thanks again for the help.
|
|
|
01-23-2011, 05:39 PM
|
#8
|
Senior Member
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
|
Try this, then:
Code:
#define _GNU_C_SOURCE
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
int split(FILE *const in_handle, const char *const in_name)
{
FILE *out_handle = NULL;
char *out_name = NULL;
char *line = NULL;
size_t size = 0;
ssize_t length;
int noff, nend, errors;
char dummy;
if (!in_handle || !in_name)
return EINVAL;
while (1) {
length = getline(&line, &size, in_handle);
if (length == (ssize_t)-1)
break;
/* Check if configuration file directive. */
noff = nend = -1;
if (sscanf(line, "configfile: '%n%*[^']%n'%c", &noff, &nend, &dummy) > 0 ||
sscanf(line, "configfile: \"%n%*[^\"]%n\"%c", &noff, &nend, &dummy) > 0 ||
sscanf(line, "configfile: %n%*s%n%c", &noff, &nend, &dummy) > 0) {
/* Close output file. */
if (out_handle) {
errors = 0;
if (ferror(out_handle)) errors++;
if (fclose(out_handle)) errors++;
out_handle = NULL;
if (errors) {
if (out_name) {
remove(out_name);
fprintf(stderr, "%s: Error closing file.\n", out_name);
free(out_name);
} else {
fprintf(stderr, "Write error.\n");
}
if (line)
free(line);
return EIO;
}
}
/* Free dynamically allocated output file name. */
if (out_name) {
free(out_name);
out_name = NULL;
}
/* Invalid file name? */
if (noff < 0 || nend <= noff) {
fprintf(stderr, "%s: Invalid configfile file name.\n", in_name);
if (line)
free(line);
return EBADF;
}
/* Duplicate the file name. */
out_name = strndup(line + noff, (size_t)(nend - noff));
if (!out_name) {
fprintf(stderr, "%s: Not enough memory for file name.\n", in_name);
if (line)
free(line);
return ENOMEM;
}
/* Check if file exists. */
if (access(out_name, F_OK) == 0) {
fprintf(stderr, "%s: File exists.\n", out_name);
free(out_name);
if (line)
free(line);
return EEXIST;
}
/* Open file for writing. */
out_handle = fopen(out_name, "wb");
if (!out_handle) {
errors = errno;
fprintf(stderr, "%s: Cannot open file for writing.\n", out_name);
free(out_name);
if (line)
free(line);
return errors;
}
/* Tell about it. */
fprintf(stderr, "%s: Created new config file (by %s).\n", out_name, in_name);
/* This input line is done. */
continue;
}
/* If output file is open, save this line. */
if (out_handle) {
fputs(line, out_handle);
continue;
}
/* Find the first non-whitespace character. */
length = strcspn(line, "\t\n\v\f\r ");
if (line[length]) {
fprintf(stderr, "%s: Missing configfile directive!\n", in_name);
if (line)
free(line);
return EBADF;
}
/* We can ignore empty lines not going anywhere. */
continue;
}
/* Close output file. */
if (out_handle) {
errors = 0;
if (ferror(out_handle)) errors++;
if (fclose(out_handle)) errors++;
out_handle = NULL;
if (errors) {
if (out_name) {
remove(out_name);
fprintf(stderr, "%s: Error closing file.\n", out_name);
free(out_name);
} else {
fprintf(stderr, "Write error.\n");
}
if (line)
free(line);
return EIO;
}
}
/* Free dynamically allocated output file name. */
if (out_name) {
free(out_name);
out_name = NULL;
}
/* Read errors? */
if (ferror(in_handle)) {
fprintf(stderr, "%s: Read error.\n", in_name);
return EIO;
}
/* Success. */
return 0;
}
int main(int argc, char *argv[])
{
FILE *in;
int arg;
int status = 0;
if (argc < 2) {
fprintf(stderr, "Usage: %s configfile ...\n", argv[0]);
fprintf(stderr, "Start a line with\n");
fprintf(stderr, "\tconfigfile: path-to-target-file\n");
fprintf(stderr, "to redirect following lines to a file.\n");
return 1;
}
for (arg = 1; arg < argc; arg++) {
in = fopen(argv[arg], "rb");
if (!in) {
fprintf(stderr, "%s: %s.\n", argv[arg], strerror(errno));
status |= 1;
continue;
}
if (split(in, argv[arg]))
status |= 2;
else
if (ferror(in)) {
fprintf(stderr, "%s: %s.\n", argv[arg], strerror(errno));
status |= 2;
}
if (fclose(in)) {
fprintf(stderr, "%s: Error closing file.\n", argv[arg]);
status |= 4;
}
}
return status;
}
Note that stuff like this is better handled using shell or awk scripts. For example, near equivalent in Bash:
Code:
#!/bin/bash
if [ $# -lt 1 ] || [ "$1" == "-h" ] || [ "$1" == "--help" ]; then
echo "" >&2
echo "Usage: $0 configuration-file ..." >&2
echo "" >&2
echo "Lines of format" >&2
echo " configfile: /path/to/new/file" >&2
echo "define where any following content is saved." >&2
echo "" >&2
exit 0
fi
while [ $# -gt 0 ]; do
outfile="/dev/null"
exec >/dev/null
infile="$1"
shift 1
if ! exec < "$infile" ; then
echo "$infile: Cannot read file." >&2
continue
fi
while read line ; do
case "$line" in
configfile:*)
outfile="${line#*:}"
if [ "${outfile#'}" != "$outfile" ] && [ "${outfile%'}" != "$outfile" ]; then
outfile="${outfile#'}"
outfile="${outfile%'}"
elif [ "${outfile#\"}" != "$outfile" ] && [ "${outfile%\"}" != "$outfile" ]; then
outfile="${outfile#\"}"
outfile="${outfile%\"}"
fi
if [ -e "$outfile" ]; then
echo "$infile: $outfile: File already exists." >&2
exit 1
fi
if ! exec > "$outfile" ; then
echo "$infile: $outfile: Cannot write to file." >&2
exit 1
fi
echo "$infile: Saving to $outfile." >&2
;;
*) echo "$line" || exit $?
;;
esac
done
done
For me, both produce identical correct output files with your example input. Nominal Animal
Last edited by Nominal Animal; 03-21-2011 at 07:35 AM.
|
|
1 members found this post helpful.
|
02-26-2011, 07:04 AM
|
#9
|
Member
Registered: Jun 2009
Posts: 42
Original Poster
Rep:
|
Quote:
Originally Posted by Nominal Animal
[Deleted]
|
Hi Nominal Animal;
I found the bash script very useful 5/5; but the C code make me crazy, till now i'm trying to make it work without success.
Best regards.
PS: Why your posts are deleted ???
|
|
|
02-26-2011, 08:35 AM
|
#10
|
Senior Member
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
|
Like I wrote above, I made a stupid misjudgment. I deleted the posts myself; check my blog if you're interested.
Since I still had the Bash script and a C program that does the content distribution, I edited them back in above. Both seem to work fine for me for the /tmp/allInOne.cfg sample input file you listed a couple of posts earlier.
Let me know if you need help with the C code; I'd be happy to help.
|
|
1 members found this post helpful.
|
02-26-2011, 08:50 AM
|
#11
|
Member
Registered: Apr 2010
Posts: 228
Rep:
|
I don't know why you need to do it in C (or even Bash), but if you can choose between languages, any of them like Python, Perl or Ruby will do it easily.
Code:
#!/usr/bin/env ruby
s=[]
File.open("file").each do |line|
if line[/filePath/]
filename = line.split(":")[-1].chomp!
File.open(filename,"w").write ( s.join )
s=[]
else
s<<line
end
end
|
|
|
02-26-2011, 04:38 PM
|
#12
|
Member
Registered: Jun 2009
Posts: 42
Original Poster
Rep:
|
Quote:
Originally Posted by Nominal Animal
Like I wrote above, I made a stupid misjudgment. I deleted the posts myself; check my blog if you're interested.
Since I still had the Bash script and a C program that does the content distribution, I edited them back in above. Both seem to work fine for me for the /tmp/allInOne.cfg sample input file you listed a couple of posts earlier.
Let me know if you need help with the C code; I'd be happy to help.
|
Oh, if someone should say sorry it is me not you, you are a good person, sorry for the delay, i was very basy with the C code. I'm really sorry.
i will let you know about the prgoress of my work as soon as possible.
thanx a lot.
|
|
|
02-26-2011, 04:42 PM
|
#13
|
Member
Registered: Jun 2009
Posts: 42
Original Poster
Rep:
|
Quote:
Originally Posted by kurumi
I don't know why you need to do it in C (or even Bash), but if you can choose between languages, any of them like Python, Perl or Ruby will do it easily.
Code:
#!/usr/bin/env ruby
s=[]
File.open("file").each do |line|
if line[/filePath/]
filename = line.split(":")[-1].chomp!
File.open(filename,"w").write ( s.join )
s=[]
else
s<<line
end
end
|
Thanx for your suggestion. The enigma1 project is codded with C and C++, it's not possible to use any other language to code plugins.May be in future i will use python for Enigma2 API.
best regards.
|
|
|
02-26-2011, 06:51 PM
|
#14
|
Member
Registered: Jun 2009
Posts: 42
Original Poster
Rep:
|
Quote:
Originally Posted by Nominal Animal
I made a severe misjudgment and deleted this post; sorry.
However, here is a C program that should work:
Code:
#define _GNU_C_SOURCE
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
int split(FILE *const in_handle, const char *const in_name)
{
FILE *out_handle = NULL;
char *out_name = NULL;
char *line = NULL;
size_t size = 0;
ssize_t length;
int noff, nend, errors;
char dummy;
if (!in_handle || !in_name)
return EINVAL;
while (1) {
length = getline(&line, &size, in_handle);
if (length == (ssize_t)-1)
break;
/* Check if configuration file directive. */
noff = nend = -1;
if (sscanf(line, "configfile: '%n%*[^']%n'%c", &noff, &nend, &dummy) > 0 ||
sscanf(line, "configfile: \"%n%*[^\"]%n\"%c", &noff, &nend, &dummy) > 0 ||
sscanf(line, "configfile: %n%*s%n%c", &noff, &nend, &dummy) > 0) {
/* Close output file. */
if (out_handle) {
errors = 0;
if (ferror(out_handle)) errors++;
if (fclose(out_handle)) errors++;
out_handle = NULL;
if (errors) {
if (out_name) {
remove(out_name);
fprintf(stderr, "%s: Error closing file.\n", out_name);
free(out_name);
} else {
fprintf(stderr, "Write error.\n");
}
if (line)
free(line);
return EIO;
}
}
/* Free dynamically allocated output file name. */
if (out_name) {
free(out_name);
out_name = NULL;
}
/* Invalid file name? */
if (noff < 0 || nend <= noff) {
fprintf(stderr, "%s: Invalid configfile file name.\n", in_name);
if (line)
free(line);
return EBADF;
}
/* Duplicate the file name. */
out_name = strndup(line + noff, (size_t)(nend - noff));
if (!out_name) {
fprintf(stderr, "%s: Not enough memory for file name.\n", in_name);
if (line)
free(line);
return ENOMEM;
}
/* Check if file exists. */
if (access(out_name, F_OK) == 0) {
fprintf(stderr, "%s: File exists.\n", out_name);
free(out_name);
if (line)
free(line);
return EEXIST;
}
/* Open file for writing. */
out_handle = fopen(out_name, "wb");
if (!out_handle) {
errors = errno;
fprintf(stderr, "%s: Cannot open file for writing.\n", out_name);
free(out_name);
if (line)
free(line);
return errors;
}
/* Tell about it. */
fprintf(stderr, "%s: Created new config file (by %s).\n", out_name, in_name);
/* This input line is done. */
continue;
}
/* If output file is open, save this line. */
if (out_handle) {
fputs(line, out_handle);
continue;
}
/* Find the first non-whitespace character. */
length = strcspn(line, "\t\n\v\f\r ");
if (line[length]) {
fprintf(stderr, "%s: Missing configfile directive!\n", in_name);
if (line)
free(line);
return EBADF;
}
/* We can ignore empty lines not going anywhere. */
continue;
}
/* Close output file. */
if (out_handle) {
errors = 0;
if (ferror(out_handle)) errors++;
if (fclose(out_handle)) errors++;
out_handle = NULL;
if (errors) {
if (out_name) {
remove(out_name);
fprintf(stderr, "%s: Error closing file.\n", out_name);
free(out_name);
} else {
fprintf(stderr, "Write error.\n");
}
if (line)
free(line);
return EIO;
}
}
/* Free dynamically allocated output file name. */
if (out_name) {
free(out_name);
out_name = NULL;
}
/* Read errors? */
if (ferror(in_handle)) {
fprintf(stderr, "%s: Read error.\n", in_name);
return EIO;
}
/* Success. */
return 0;
}
int main(int argc, char *argv[])
{
FILE *in;
int arg;
int status = 0;
if (argc < 2) {
fprintf(stderr, "Usage: %s configfile ...\n", argv[0]);
fprintf(stderr, "Start a line with\n");
fprintf(stderr, "\tconfigfile: path-to-target-file\n");
fprintf(stderr, "to redirect following lines to a file.\n");
return 1;
}
for (arg = 1; arg < argc; arg++) {
in = fopen(argv[arg], "rb");
if (!in) {
fprintf(stderr, "%s: %s.\n", argv[arg], strerror(errno));
status |= 1;
continue;
}
if (split(in, argv[arg]))
status |= 2;
else
if (ferror(in)) {
fprintf(stderr, "%s: %s.\n", argv[arg], strerror(errno));
status |= 2;
}
if (fclose(in)) {
fprintf(stderr, "%s: Error closing file.\n", argv[arg]);
status |= 4;
}
}
return status;
}
A Bash script that does the same:
Code:
#!/bin/bash
if [ $# -lt 1 ] || [ "$1" == "-h" ] || [ "$1" == "--help" ]; then
echo "" >&2
echo "Usage: $0 configuration-file ..." >&2
echo "" >&2
echo "Lines of format" >&2
echo " configfile: /path/to/new/file" >&2
echo "define where any following content is saved." >&2
echo "" >&2
exit 0
fi
while [ $# -gt 0 ]; do
outfile="/dev/null"
exec >/dev/null
infile="$1"
shift 1
if ! exec < "$infile" ; then
echo "$infile: Cannot read file." >&2
continue
fi
while read line ; do
case "$line" in
configfile:*)
outfile="${line#*:}"
if [ "${outfile#'}" != "$outfile" ] && [ "${outfile%'}" != "$outfile" ]; then
outfile="${outfile#'}"
outfile="${outfile%'}"
elif [ "${outfile#\"}" != "$outfile" ] && [ "${outfile%\"}" != "$outfile" ]; then
outfile="${outfile#\"}"
outfile="${outfile%\"}"
fi
if [ -e "$outfile" ]; then
echo "$infile: $outfile: File already exists." >&2
exit 1
fi
if ! exec > "$outfile" ; then
echo "$infile: $outfile: Cannot write to file." >&2
exit 1
fi
echo "$infile: Saving to $outfile." >&2
;;
*) echo "$line" || exit $?
;;
esac
done
done
|
Hi Nominal Animal don't care about the misjudgment, you are the best, you solved all my C issues. Every things working 100% now. I apreciate a lot your help.
I give your bash script and C code 5 stars (*****).
best regards.
|
|
|
All times are GMT -5. The time now is 06:21 PM.
|
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.
|
Latest Threads
LQ News
|
|