LinuxQuestions.org
Help answer threads with 0 replies.
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 01-22-2011, 05:09 PM   #1
magische_vogel
Member
 
Registered: Jun 2009
Posts: 42

Rep: Reputation: 0
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.
Old 01-22-2011, 07:22 PM   #2
cin_
Member
 
Registered: Dec 2010
Posts: 281

Rep: Reputation: 24
<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
 
Old 01-23-2011, 05:45 AM   #3
Nominal Animal
Senior Member
 
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
Blog Entries: 3

Rep: Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948
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.
Old 01-23-2011, 08:39 AM   #4
magische_vogel
Member
 
Registered: Jun 2009
Posts: 42

Original Poster
Rep: Reputation: 0
Quote:
Originally Posted by Nominal Animal View Post
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);
 
Old 01-23-2011, 10:59 AM   #5
Nominal Animal
Senior Member
 
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
Blog Entries: 3

Rep: Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948
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.
Old 01-23-2011, 11:34 AM   #6
Nominal Animal
Senior Member
 
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
Blog Entries: 3

Rep: Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948
Quote:
Originally Posted by magische_vogel View Post
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.
Old 01-23-2011, 02:39 PM   #7
magische_vogel
Member
 
Registered: Jun 2009
Posts: 42

Original Poster
Rep: Reputation: 0
Quote:
Originally Posted by Nominal Animal View Post
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.
 
Old 01-23-2011, 05:39 PM   #8
Nominal Animal
Senior Member
 
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
Blog Entries: 3

Rep: Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948
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.
Old 02-26-2011, 07:04 AM   #9
magische_vogel
Member
 
Registered: Jun 2009
Posts: 42

Original Poster
Rep: Reputation: 0
Quote:
Originally Posted by Nominal Animal View Post
[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 ???
 
Old 02-26-2011, 08:35 AM   #10
Nominal Animal
Senior Member
 
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
Blog Entries: 3

Rep: Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948
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.
Old 02-26-2011, 08:50 AM   #11
kurumi
Member
 
Registered: Apr 2010
Posts: 228

Rep: Reputation: 53
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
 
Old 02-26-2011, 04:38 PM   #12
magische_vogel
Member
 
Registered: Jun 2009
Posts: 42

Original Poster
Rep: Reputation: 0
Quote:
Originally Posted by Nominal Animal View Post
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.
 
Old 02-26-2011, 04:42 PM   #13
magische_vogel
Member
 
Registered: Jun 2009
Posts: 42

Original Poster
Rep: Reputation: 0
Quote:
Originally Posted by kurumi View Post
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.
 
Old 02-26-2011, 06:51 PM   #14
magische_vogel
Member
 
Registered: Jun 2009
Posts: 42

Original Poster
Rep: Reputation: 0
Quote:
Originally Posted by Nominal Animal View Post
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.
 
  


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
Cannot read text from text file and store it in a variable using shell script anurupr Linux - Newbie 2 03-03-2010 01:38 PM
text files contents jaepi Programming 5 06-18-2008 10:07 AM
Steps needed to convert multiple text files into one master text file jamtech Programming 5 10-07-2007 11:24 PM
How to read and change the contents of a text file? Bassam Linux - General 11 02-26-2004 04:08 AM
need a perlscript to read from a text file and transfer files via ftp cccc Linux - Networking 2 02-21-2004 06:18 PM

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

All times are GMT -5. The time now is 06:21 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