[Tux4kids-commits] [SCM] tuxhistory - Educational history game branch, master, updated. 37626108d1d6843bc7cb0a0439dd7ff3618f984d

julio (none) julio at julio-desktop.
Tue May 25 19:37:39 UTC 2010


The following commit has been merged in the master branch:
commit 37626108d1d6843bc7cb0a0439dd7ff3618f984d
Author: julio <julio at julio-desktop.(none)>
Date:   Tue May 25 14:35:55 2010 -0500

    Changing the executable name, and deleting some files.

diff --git a/src/tuxmathadmin.c b/src/tuxmathadmin.c
deleted file mode 100644
index d26c934..0000000
--- a/src/tuxmathadmin.c
+++ /dev/null
@@ -1,907 +0,0 @@
-/*
-  tuxmathadmin.c
-
-  Administer user tuxmath accounts: create accounts, clear gold stars, etc.
-
-  by Tim Holy
-  holy at wustl.edu
-
-  Part of "Tux4Kids" Project
-  http://www.tux4kids.com/
-  Subversion repository:
-  https://svn.debian.alioth.org/tux4kids/tuxmath/
-
- 
-  December 3, 2007
-*/
-
-#include "config.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-
-// error.h not always available - e.g. MacOSX, BeOS:
-#ifdef HAVE_ERROR_H
-#include <error.h>
-#else
-#define error(status, errnum, rest...) \
-  fsync(stdout); fprintf(stderr, ## rest); exit(status)
-#endif
-
-// The next two are for mkdir and umask
-#include <sys/types.h>
-#include <sys/stat.h>
-// The next is needed for opendir
-#include <dirent.h>
-// The next is for isspace
-#include <ctype.h>
-// The next is for fsync
-#include <unistd.h>
-
-
-#ifdef BUILD_MINGW32
-#define USER_MENU_ENTRIES_FILENAME "user_menu_entries.txt"
-#define HIGHSCORE_FILENAME "highscores.txt"
-#define GOLDSTAR_FILENAME "goldstars.txt"
-#else
-#define USER_MENU_ENTRIES_FILENAME "user_menu_entries"
-#define HIGHSCORE_FILENAME "highscores"
-#define GOLDSTAR_FILENAME "goldstars"
-#endif
-
-#define PATH_MAX 4096
-#define MAX_USERS 100000
-#define ADMINVERSION "0.1.1"
-
-void display_help(void);
-void usage(int err, char * cmd);
-int extract_variable(FILE *fp, const char *varname, char** value);
-int directory_crawl(const char *path);
-void free_directories(int n);
-void create_homedirs(const char *path,const char *file);
-void config_highscores(const char *path,int level);
-void unconfig_highscores(const char *path);
-void clear_highscores(const char *path);
-void clear_goldstars(const char *path);
-void consolidate_logs(const char *path);
-void clear_logs(const char *path);
-void clear_file(const char *path,const char *filename,const char *invoke_name);
-char* eatwhite(char *buf);
-
-char *directory[MAX_USERS];
-int directory_level[MAX_USERS];
-
-int main(int argc, char *argv[])
-{
-  int i;
-  FILE *fp;
-  DIR *dir;
-
-  int is_creatinghomedirs = 0;
-  int is_confighighscores = 0;
-  int is_unconfighighscores = 0;
-  int is_clearinggoldstars = 0;
-  int is_clearinghighscores = 0;
-  int is_consolidatinglogs = 0;
-  int is_clearinglogs = 0;
-  char *path = NULL;
-  char *file = NULL;
-  int level = 0;
-  int success;
-
-  // Null-out global directory pointers
-  for (i = 0; i < MAX_USERS; i++)
-    directory[i] = NULL;
-
-  if (argc < 2) {
-    display_help();
-    exit(EXIT_FAILURE);
-  }
-
-  // Check global config file for a homedir path (must be uncommented)
-  fp = fopen(DATA_PREFIX "/missions/options", "r");
-  if (fp) {
-    extract_variable(fp,"homedir",&path);
-    free(path);
-    fclose(fp);
-  }
-
-  // Parse the command line options
-  for (i = 1; i < argc; i++) {
-    if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0) {
-      display_help();
-      exit(EXIT_SUCCESS);
-    }
-    else if (strcmp(argv[i], "--copyright") == 0 ||
-             strcmp(argv[i], "-c") == 0)
-    {
-      printf(
-        "\ntuxmathadmin version " ADMINVERSION ", Copyright (C) 2007 Tim Holy\n"
-        "This program is free software; you can redistribute it and/or\n"
-        "modify it under the terms of the GNU General Public License\n"
-        "as published by the Free Software Foundation.  See COPYING.txt\n"
-        "\n"
-        "This program is distributed in the hope that it will be useful,\n"
-        "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
-        "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
-        "\n");
-      exit(EXIT_SUCCESS);
-    }
-    else if (strcmp(argv[i], "--usage") == 0 ||
-             strcmp(argv[i], "-u") == 0) {
-      usage(0, argv[0]);
-      exit(EXIT_SUCCESS);
-    }
-    else if (strcmp(argv[i], "--path") == 0) {
-      if (i+1 > argc) {
-        fprintf(stderr, "%s option requires an argument (a directory name)\n", argv[i]);
-        usage(EXIT_FAILURE, argv[0]);
-      }
-      else {
-        path = argv[i+1];
-        dir = opendir(path);  // determine whether directory exists
-        if (dir == NULL)
-          error(EXIT_FAILURE,errno,"path:\n  %s",path);
-        closedir(dir);
-        i++; // increment so further processing skips over the argument
-      }
-    }
-    else if (strcmp(argv[i], "--level") == 0) {
-      if (i+1 > argc) {
-        fprintf(stderr, "%s option requires an argument (a level number)\n", argv[i]);
-        usage(EXIT_FAILURE, argv[0]);
-      }
-      else {
-        success = sscanf(argv[i+1],"%d",&level);
-        if (!success) {
-          fprintf(stderr,"level: %s is not a number\n",argv[i+1]);
-          exit(EXIT_FAILURE);
-        }
-        i++; // increment so further processing skips over the argument
-      }
-    }
-    else if (strcmp(argv[i], "--createhomedirs") == 0) {
-      is_creatinghomedirs = 1;
-      if (i+1 > argc) {
-        fprintf(stderr, "%s option requires an argument (a file name)\n", argv[i]);
-        usage(EXIT_FAILURE, argv[0]);
-      }
-      else {
-        file = argv[i+1];
-        fp = fopen(file,"r");   // determine whether the file exists
-        if (fp == NULL)
-          error(EXIT_FAILURE,errno,"createhomedirs using:\n  %s",file);
-        fclose(fp);  // don't read it yet, do that elsewhere
-        i++; // increment so further processing skips over the argument
-      }
-    }
-    else if (strcmp(argv[i], "--confighighscores") == 0) {
-      is_confighighscores = 1;
-    }
-    else if (strcmp(argv[i], "--unconfighighscores") == 0) {
-      is_unconfighighscores = 1;
-    }
-    else if (strcmp(argv[i], "--clearhighscores") == 0) {
-      is_clearinghighscores = 1;
-    }
-    else if (strcmp(argv[i], "--cleargoldstars") == 0) {
-      is_clearinggoldstars = 1;
-    }
-    else if (strcmp(argv[i], "--consolidatelogs") == 0) {
-      is_consolidatinglogs = 1;
-    }
-    else if (strcmp(argv[i], "--clearlogs") == 0) {
-      is_clearinglogs = 1;
-    }
-    else {
-      fprintf(stderr,"Error: option %s not recognized.\n",argv[i]);
-      exit(EXIT_FAILURE);
-    }
-  }
-
-  // All operations require a valid path, so check that now
-  if (path == NULL) {
-    fprintf(stderr,"Must have a valid path (either with --path or in the global configuration)\n");
-    usage(EXIT_FAILURE, argv[0]);
-  }
-
-  // Create homedirs
-  if (is_creatinghomedirs) {
-    if (file == NULL) {
-      fprintf(stderr,"Must specify a filename when creating homedirs\n");
-      usage(EXIT_FAILURE, argv[0]);
-    }
-    create_homedirs(path,file);
-  }
-
-  // Configure high scores
-  if (is_confighighscores) {
-    if (level == 0) {
-      fprintf(stderr,"Must specify a level when configuring highscores\n");
-      usage(EXIT_FAILURE, argv[0]);
-    }
-    config_highscores(path,level);
-  }
-
-  // Unconfigure high scores
-  if (is_unconfighighscores) {
-    unconfig_highscores(path);
-  }
-
-  // Clear high scores
-  if (is_clearinghighscores) {
-    clear_highscores(path);
-  }
-
-  // Clear gold stars
-  if (is_clearinggoldstars) {
-    clear_goldstars(path);
-  }
-   
-  // Consolidate logs
-  if (is_consolidatinglogs) {
-    consolidate_logs(path);
-  }
-
-  // Clear logs
-  if (is_clearinglogs) {
-    clear_logs(path);
-  }
-
-  return EXIT_SUCCESS;
-}
-
-
-void usage(int err, char * cmd)
-{
-  FILE * f;
-
-  if (err == 0)
-    f = stdout;
-  else
-    f = stderr;
-
-  fprintf(f,
-   "\nUsage: %s {--help | --usage | --copyright}\n"
-   "       %s [--path <directory>] --createhomedirs <file>\n"
-   "       %s [--level <levelnum>] --confighighscores\n"
-   "       %s [--path <directory>] [--clearhighscores] [--cleargoldstars] [--consolidatelogs] [--clearlogs]\n"
-    "\n", cmd, cmd, cmd, cmd);
-
-  exit (err);
-}
-
-void display_help(void)
-{
-  printf("\ntuxmathadmin\n"
-         "This program facilitates administering tuxmath, and is particularly\n"
-         "useful for schools and the like that may have many users.\n\n"
-         "Examples:\n"
-         "  tuxmathadmin --path /servervolume/tuxmath_users --createhomedirs users.csv\n"
-         "  tuxmathadmin --createhomedirs users.csv\n"
-         "    Creates a user directory tree in location /servervolume/tuxmath_users,\n"
-         "    according to the structure specified in users.csv.  See configure.pdf\n"
-         "    for details.  The second syntax is applicable if you've defined the\n"
-         "    homedir path in the global configuration file.\n\n"
-         "  tuxmathadmin --confighighscores --level 3\n"
-         "    Sets up sharing of high scores at level 3 of the hierarchy (top is\n"
-         "    level 1).  If students logging in are presented with a choice of grade,\n"
-         "    then classroom, and then user, then level 1 is the school, level 2 is the\n"
-         "    grade, level 3 is the classroom, and level 4 is the individual student.\n"
-         "    So level 3 would set it up so that all kids in the same classroom would\n"
-         "    compete for high scores.\n\n"
-         "  tuxmathadmin --unconfighighscores\n"
-         "    Removes any existing highscores configuration.\n\n"
-         "  tuxmathadmin --clearhighscores\n"
-         "    Clears high scores for all users in the location specified by the homedir\n"
-         "    setting in the global configuration file.\n\n"
-         "  tuxmathadmin --path /servervolume/tuxmath_users/2ndgrade --clearhighscores\n"
-         "    Clears the high scores for all users inside the 2ndgrade hierarchy.\n\n"
-         "  tuxmathadmin --cleargoldstars\n"
-         "    Clears the gold stars for all users.\n\n"
-         "  tuxmathadmin --path /servervolume/tuxmath_users/1st\\ grade/Mrs.\\ Smith --cleargoldstars\n"
-         "    Clears the gold stars for all users in Mrs. Smith's first grade class.\n\n"
-         "  tuxmathadmin --consolidatelogs\n"
-         "    Creates consolidated_log.csv files at one level above the lowest level\n"
-         "    of the directory hierarchy. These files can be opened with a spreadsheet\n"
-         "    program. This may be useful for tracking student progress.\n"
-         "    Note also that each student has a personal log.csv file in his/her own\n"
-         "    directory.\n\n"
-         "  tuxmathadmin --clearlogs\n"
-         "    Deletes all log.csv files in the directory hierarchy.\n\n"
-         );
-}
-
-// This function does the work of creating the user directory tree,
-// given the structure specified in the CSV (comma separated value)
-// file "file".  "path" is the base directory in which this tree is
-// created.
-void create_homedirs(const char *path,const char *file)
-{
-  FILE *fp,*fpue;
-  char buf[PATH_MAX];
-  char *line_begin;
-  char *line_cur;
-  char *line_cur_end;
-  char *copy_start;
-  char fullpath[PATH_MAX];
-  char **current_dirtree = NULL;
-  int current_depth;
-  int max_depth = 0;
-  int this_line_total_depth;
-  int stop_blanking;
-  int i;
-  int len;
-  mode_t mask;
-
-  fp = fopen(file,"r");
-  if (!fp)
-    error(EXIT_FAILURE,errno,"Error: couldn't open:\n  %s for reading",file);
-
-  mask = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH | S_IXUSR | S_IXGRP | S_IXOTH;
-  umask(0x0);  // make dirs read/write for everyone
-  while (fgets (buf, PATH_MAX, fp)) {
-    // Skip leading & trailing whitespace
-    line_begin = eatwhite(buf);
-    // Skip comments
-    if ((*line_begin == ';') || (*line_begin == '#'))
-      continue;
-    // Make sure this line isn't blank
-    if (strlen(line_begin) == 0)
-      continue;
-    //printf("Read the line %s\n",line_begin);
-
-    // Count the number of levels by counting the commas + 1
-    this_line_total_depth = 1;
-    line_cur = line_begin;
-    while (!(*line_cur == '\r' || *line_cur == '\n' || *line_cur == '\0')) {
-      if (*line_cur == ',')
-        this_line_total_depth++;
-      line_cur++;
-    }
-
-    // If this is our first time, set up the tree structure
-    if (max_depth == 0) {
-      max_depth = this_line_total_depth;
-      current_dirtree = (char **) malloc(max_depth * sizeof(char*));
-      if (current_dirtree == NULL) {
-        fprintf(stderr,"Error: couldn't allocate memory for directory tree.\n");
-        exit(EXIT_FAILURE);
-      }
-      for (i = 0; i < max_depth; i++) {
-        current_dirtree[i] = (char *) malloc(PATH_MAX * sizeof(char));
-        if (current_dirtree[i] == NULL){
-          fprintf(stderr,"Error: couldn't allocate memory for directory tree.\n");
-          exit(EXIT_FAILURE);
-        } else
-          *(current_dirtree[i]) = '\0';  // initialize with blank string
-      }
-    }
-    else {
-      // Check that this line doesn't change the size of the directory hierarchy
-      if (this_line_total_depth != max_depth) {
-        fprintf(stderr,"Error: line\n  '%s'\ncontains a different number of depths to the hierarchy than the previous setting (%d).\n",buf,max_depth);
-        exit(EXIT_FAILURE);
-      }
-    }
-    
-    // Parse the pathname from back to front.  Blank fields at the end
-    // indicate a lack of subdirectories; blank fields at the
-    // beginning indicate that the higher levels of the hierarchy are
-    // not to be changed (just copied "down").  So these have to be
-    // treated differently.
-    *line_cur = '\0';  // replace linefeed with terminal \0
-    line_cur_end = line_cur;
-    current_depth = max_depth-1;
-    stop_blanking = 0;
-    while (current_depth >= 0) {
-      // Back up to the previous comma
-      // Note that line_cur+1 points to the first "real character" of
-      // the string, so don't be bothered that line_cur could get to be
-      // one less than line_begin.
-      while (line_cur >= line_begin && *line_cur != ',')
-        line_cur--;
-      // Determine whether we have a new directory name
-      if (line_cur+1 < line_cur_end) {
-        // We do, copy it over including the terminal \0
-        copy_start = line_cur+1;
-        if (*copy_start == '\"')
-          copy_start++;
-        if (line_cur_end[-1] == '\"') {
-          line_cur_end--;
-          *line_cur_end = '\0';
-        }
-        memcpy(current_dirtree[current_depth],copy_start,line_cur_end-copy_start+1);
-        stop_blanking = 1;  // don't clear blank fields in the future
-      }
-      else {
-        // Blank this particular field, because we don't want old
-        // subdirectories hanging around
-        if (!stop_blanking)
-          *(current_dirtree[current_depth]) = '\0';
-      }
-      current_depth--;
-      if (line_cur >= line_begin)
-        *line_cur = '\0'; // end the processing at the comma
-      line_cur_end = line_cur;
-    }
-
-    // Create the full path
-    strncpy(fullpath, path, PATH_MAX);
-    len = strlen(fullpath);
-    if (fullpath[len-1] != '/' && len+1 < PATH_MAX) {
-      fullpath[len] = '/';  // append a slash, if need be
-      fullpath[len+1] = '\0';
-    }
-    for (i = 0; i < max_depth; i++) {
-      len = strlen(fullpath);
-      strncpy(fullpath+len,current_dirtree[i],PATH_MAX-len);
-      len = strlen(fullpath);
-      if (fullpath[len-1] != '/' && len+1 < PATH_MAX) {
-        fullpath[len] = '/';  // append a slash, if need be
-        fullpath[len+1] = '\0';
-      }
-    }
-
-    // Create the directory
-    if (strlen(fullpath) < PATH_MAX) {
-      if (mkdir(fullpath,mask) < 0) {
-        // There was some kind of error, figure out what happened.
-        // Be a little more verbose than the standard library errors.
-        if (errno == EEXIST) {
-          fprintf(stderr,"Warning: %s already exists, continuing.\n",fullpath);
-        }
-        else if (errno == ENAMETOOLONG) {
-          fprintf(stderr,"Error: the directory name:\n  %s\nwas too long.\n",fullpath);
-          exit(EXIT_FAILURE);
-        }
-        else if (errno == ENOENT) {
-          fprintf(stderr,"Error: One of the upper-level directories in:\n  %s\ndoesn't exist.  Check the syntax of your configuration file.\n",fullpath);
-          exit(EXIT_FAILURE);
-        }
-        else if (errno == ENOSPC) {
-          fprintf(stderr,"Error: the device has no room available.\n");
-          exit(EXIT_FAILURE);
-        }
-        else {
-          // Fall back on the standard library for the remaining error
-          // handling
-          fprintf(stderr,"Error: couldn't make directory %s:\nDo you have write permission for this location?\nDo you need to be root/administrator?\n",fullpath);
-          error(EXIT_FAILURE,errno,"error");
-        }
-      }
-      else {
-        fsync(fileno(stderr));
-        fprintf(stdout,"Creating %s\n",fullpath);
-        fsync(fileno(stdout));
-
-        // Append the name to the user_menu_entries file
-        // First we split off the last item in fullpath
-        line_begin = fullpath;
-        len = strlen(line_begin);
-        line_begin[len-1] = '\0';  // replace terminal '/' with \0
-        line_cur = line_begin + len-1;
-        while (line_cur > line_begin && *line_cur != '/')
-          line_cur--;
-        if (line_cur > line_begin) { // as long as not making in the root directory...a bad idea anyway!
-          *line_cur = '\0';  // Split into two strings
-        }
-        else {
-          line_begin = "/";
-        }
-        line_cur++;   // line_cur now points to beginning of newest directory
-        strncpy(buf,line_begin,PATH_MAX);  // we don't need buf anymore
-        buf[strlen(buf)] = '/';  // append directory separator
-        len = strlen(buf);
-        strncpy(buf+len,USER_MENU_ENTRIES_FILENAME,PATH_MAX-len-strlen(USER_MENU_ENTRIES_FILENAME));
-        // Now do the appending
-        fpue = fopen(buf,"a");
-        if (!fpue) {
-          fprintf(stderr,"Error: can't open file %s for writing.\n",buf);
-          exit(EXIT_FAILURE);
-        }
-        len = fprintf(fpue,"%s\n",line_cur);
-        if (len != strlen(line_cur)+1) {
-          error(EXIT_FAILURE,errno,"Error writing %s to file %s.\n",line_cur,buf);
-        }
-        fclose(fpue);
-      }
-    }
-    else {
-      // The path name was truncated, don't make a corrupt directory
-      fprintf(stderr,"Error: the directory name:\n  %s\nwas too long, quitting.\n",fullpath);
-      exit(EXIT_FAILURE);
-    }
-  }
-  
-  // Free memory
-  for (i = 0; i < max_depth; i++)
-    free(current_dirtree[i]);
-  if (current_dirtree != NULL)
-    free(current_dirtree);
-}
-
-
-// Creates blank highscores files at the specified level of the
-// directory hierarchy.  This will be the level at which highscore
-// competition will occur.
-void config_highscores(const char *path,int level)
-{
-  FILE *fp;
-  char buf[PATH_MAX];
-  int n_dirs;
-  int i;
-  int success;
-
-  n_dirs = directory_crawl(path);
-  success = 0;  // This will change to 1 if we find a directory of the
-                // right level
-  for (i = 0; i < n_dirs; i++) {
-    if (directory_level[i] == level) {
-      // Create a blank highscores file in this directory
-      strncpy(buf,directory[i],PATH_MAX);
-      strncat(buf,HIGHSCORE_FILENAME,PATH_MAX-strlen(buf)-1);
-      if (strlen(buf) >= PATH_MAX-1) {
-        fprintf(stderr,"confighighscores: pathname %s truncated, exiting.\n",buf);
-        exit(EXIT_FAILURE);
-      }
-      fp = fopen(buf,"w");
-      if (!fp)
-        error(EXIT_FAILURE,errno,"confighighscores: file:\n  %s",buf);
-      // That creates a blank file, which is all we have to do
-      fclose(fp);
-      success = 1;
-    }
-  }
-  if (!success) {
-    fprintf(stderr,"Error: no directories of level %d found!",level);
-    exit(EXIT_FAILURE);
-  }
-
-  free_directories(n_dirs);
-}
-
-// Delete all highscores files in the directory hierarchy
-void unconfig_highscores(const char *path)
-{
-  clear_file(path,HIGHSCORE_FILENAME,"unconfighighscores");
-}
-
-// Replaces all highscores files with blank files anywhere in the
-// directory hierarchy.  Replacing it with a blank file, rather than
-// just deleting it, insures that the highscores configuration (in
-// terms of the level at which highscore competition occurs) is not
-// altered.
-void clear_highscores(const char *path)
-{
-  FILE *fp;
-  char buf[PATH_MAX];
-  int n_dirs;
-  int i;
-
-  n_dirs = directory_crawl(path);
-  for (i = 0; i < n_dirs; i++) {
-    // Search for a highscores file in this directory
-    strncpy(buf,directory[i],PATH_MAX);
-    strncat(buf,HIGHSCORE_FILENAME,PATH_MAX-strlen(buf)-1);
-    if (strlen(buf) >= PATH_MAX-1) {
-      fprintf(stderr,"clearhighscores: pathname %s truncated, exiting.\n",buf);
-      exit(EXIT_FAILURE);
-    }
-    fp = fopen(buf,"r");
-    if (fp) {
-      // We found such a file, replace it with a blank one
-      fclose(fp);
-      fp = fopen(buf,"w");
-      if (!fp)
-        error(EXIT_FAILURE,errno,"clearhighscores: file:\n  %s",buf);
-      // That creates a blank file, which is all we have to do
-      fclose(fp);
-    }
-  }
-
-  free_directories(n_dirs);
-}
-
-// Delete all goldstars files in the directory hierarchy
-void clear_goldstars(const char *path)
-{
-  clear_file(path,GOLDSTAR_FILENAME,"cleargoldstars");
-}
-
-// Create consolidated log files at the next-to-lowest level of the
-// hierarchy.  This is basically performing a "cat" operation on all
-// the log.csv files that are below a given point in a directory
-// hierarchy.
-void consolidate_logs(const char *path)
-{
-  int n_dirs;
-  int max_level;
-  int i;
-  int column_names_written = 0;
-  FILE *fplogwrite, *fplogread, *fpusersread;
-  char buf[PATH_MAX], buf2[PATH_MAX], buf3[PATH_MAX];
-  char *line_begin;
-  
-  // Determine the maximum level
-  n_dirs = directory_crawl(path);
-  max_level = 0;
-  for (i = 0; i < n_dirs; i++)
-    if (directory_level[i] > max_level)
-      max_level = directory_level[i];
-
-  // For every directory on the next-to-maximum level,...
-  for (i = 0; i < n_dirs; i++) {
-    if (directory_level[i] != max_level-1)
-      continue;
-
-    // Open the user_menu_entries file, so that we can cycle through
-    // all subdirectories
-    strncpy(buf,directory[i],PATH_MAX);
-    strncat(buf,USER_MENU_ENTRIES_FILENAME,PATH_MAX-strlen(buf)-1);
-    if (strlen(buf) >= PATH_MAX-1) {
-      error(EXIT_FAILURE,0,"consolidatelogs: pathname %s is truncated, exiting.\n",buf);
-    }
-    fpusersread = fopen(buf,"r");
-    if (!fpusersread)
-      error(EXIT_FAILURE,errno,"consolidatelogs: file:\n %s",buf);
-
-    // Create a blank consolidated_log.csv file
-    strncpy(buf,directory[i],PATH_MAX);
-    strncat(buf,"consolidated_log.csv",PATH_MAX-strlen(buf)-1);
-    if (strlen(buf) >= PATH_MAX-1) {
-      error(EXIT_FAILURE,0,"consolidatelogs: pathname %s is truncated, exiting.\n",buf);
-    }
-    fplogwrite = fopen(buf,"w");
-    if (!fplogwrite)
-      error(EXIT_FAILURE,errno,"consolidatelogs: file:\n  %s",buf);
-
-    // Loop over different users
-    while (fgets(buf, PATH_MAX, fpusersread)) {
-      // Skip over white space, and especially blank lines
-      line_begin = eatwhite(buf);
-      if (strlen(line_begin) == 0)
-        continue;
-      // Create the full path & filename of the user's log.csv file
-      strncpy(buf2,directory[i],PATH_MAX);
-      strncat(buf2,line_begin,PATH_MAX-strlen(buf2)-1);
-      strncat(buf2,"/log.csv",PATH_MAX-strlen(buf2)-1);
-      fplogread = fopen(buf2,"r");
-      if (fplogread) {
-        // Copy the relevant lines from the user's log.csv file to the
-        // consolidated log file.  Make sure only one copy of the
-        // column names is written.
-        while(fgets(buf3, PATH_MAX, fplogread)) {
-          line_begin = eatwhite(buf3);
-          if (strlen(line_begin) == 0)
-            continue;
-          if (strncmp(line_begin,"\"User",5) == 0) {
-            if (!column_names_written) {
-              fprintf(fplogwrite,"%s\n",line_begin);
-              column_names_written = 1;
-            }
-          } else {
-            fprintf(fplogwrite,"%s\n",line_begin);
-          }
-        }
-        fclose(fplogread);
-      }
-    }
-    fclose(fpusersread);
-    fclose(fplogwrite);
-  }
-
-  free_directories(n_dirs);
-}
-
-// Delete all log.csv files in the directory hierarchy
-void clear_logs(const char *path)
-{
-  clear_file(path,"log.csv","clearlogs");
-}
-
-// Deletes a named filetype in the directory hierarchy
-void clear_file(const char *path,const char *filename,const char *invoke_name)
-{
-  FILE *fp;
-  char buf[PATH_MAX];
-  int n_dirs;
-  int i;
-
-  n_dirs = directory_crawl(path);
-  for (i = 0; i < n_dirs; i++) {
-    // Search for a goldstars file in this directory
-    strncpy(buf,directory[i],PATH_MAX);
-    strncat(buf,filename,PATH_MAX-strlen(buf)-1);
-    if (strlen(buf) >= PATH_MAX-1) {
-      fprintf(stderr,"%s: pathname %s truncated, exiting.\n",invoke_name,buf);
-      exit(EXIT_FAILURE);
-    }
-    fp = fopen(buf,"r");
-    if (fp != NULL) {
-      // We found such a file, delete it
-      fclose(fp);
-      if (remove(buf) < 0)
-        error(EXIT_FAILURE,errno,"%s: file:\n  %s",invoke_name,buf);
-    }
-  }
-
-  free_directories(n_dirs);
-}
-
-
-// Extracts a single variable from a configuration file and puts the
-// string in the variable "value". Returns 1 on success and 0 on
-// failure.
-int extract_variable(FILE *fp, const char *varname, char** value)
-{
-  char buf[PATH_MAX];
-  char *param_begin;
-  char *tmpvalue;
-
-  rewind(fp);  // start at the beginning of the file
-
-  // Read in a line at a time:
-  while (fgets (buf, PATH_MAX, fp)) {
-    param_begin = buf;
-    // Skip leading whitespace
-    while (isspace(*param_begin))
-      param_begin++;
-    // Skip comments
-    if ((*param_begin == ';') || (*param_begin == '#'))
-      continue;
-    // Test whether it matches the variable name
-    if (strncmp(param_begin,varname,strlen(varname)) == 0) {
-      // Find the "=" sign
-      tmpvalue = strchr(param_begin+strlen(varname), '=');
-      if (tmpvalue == NULL)
-        continue;
-      // Skip over the "=" sign
-      tmpvalue++;
-      // Skip whitespace
-      while (isspace(*tmpvalue))
-        tmpvalue++;
-      // Eliminate any whitespace at end
-      param_begin = tmpvalue;
-      tmpvalue = param_begin + strlen(param_begin) - 1;
-      while (tmpvalue > param_begin && isspace(*tmpvalue)) {
-        *tmpvalue = '\0';
-        tmpvalue--;
-      }
-      // Abort if empty
-      if (strlen(param_begin) == 0)
-        continue;
-      // Successful, copy the result
-      *value = strdup(param_begin);
-      return 1;
-    }
-  }
-  return 0;
-}
-
-// Recursively generates a list of all subdirectories listed in
-// user_menu_entries starting from the given path.  It populates the
-// global variables "directory" and "directory_level", and returns the
-// total number found.  Note this function allocated memory with
-// malloc, so after you're done using these directories you should
-// call free_directories.
-//
-// This function checks to make sure that each directory exists, and
-// exits if not, so you can be sure that all listed directories exist.
-//
-// Note this puts the top level directory (assigned in path) as the
-// first entry (which "main" verifies to be valid), so this function
-// is guaranteed to return at least one directory.
-int directory_crawl(const char *path)
-{
-  int current_length;
-  int previous_length;
-  int current_level;
-  FILE *fp;
-  char buf[PATH_MAX];
-  char fullpath[PATH_MAX];
-  int isdone;
-  int i;
-  char *line_begin;
-  DIR *dir;
-  
-  current_length = 1;
-  directory[0] = (char*) malloc((strlen(path)+2)*sizeof(char));
-  if (directory[0] == NULL) {
-    fprintf(stderr,"Memory allocation error in directory_crawl.\n");
-    exit(EXIT_FAILURE);
-  }
-  strcpy(directory[0],path);
-  // Append '/' if necessary
-  if (directory[0][strlen(path)-1] != '/')
-    strcat(directory[0],"/");
-  current_level = 1;
-  directory_level[0] = current_level;
-
-  isdone = 0;
-  while (!isdone) {
-    previous_length = current_length;
-    isdone = 1;  // We'll be finished if we don't find any new user_menu_entries files
-    for (i = 0; i < previous_length; i++) {
-      // Just parse directories of the most recently-added level
-      // (we've already done the work for previous levels)
-      if (directory_level[i] == current_level) {
-        // Read the user_menu_entries file, if it exists
-        // Note that previous items already have "/" appended, no need
-        // to worry about that here.
-        strncpy(fullpath,directory[i],PATH_MAX);
-        strncat(fullpath,USER_MENU_ENTRIES_FILENAME,PATH_MAX-strlen(fullpath)-1);
-        fp = fopen(fullpath,"r");
-        if (fp != NULL) {
-          // We found the user_menu_entries file, read it and add directories
-          while (fgets (buf, PATH_MAX, fp)) {
-            if (current_length >= MAX_USERS) {
-              fprintf(stderr,"Error: maximum number of users exceeded.");
-              exit(EXIT_FAILURE);
-            }
-            // Skip over leading & trailing white space, and
-            // especially blank lines
-            line_begin = eatwhite(buf);
-            if (strlen(line_begin) == 0)
-              continue;
-
-            directory[current_length] = (char *) malloc((strlen(directory[i])+strlen(line_begin)+2)*sizeof(char));
-            if (directory[current_length] == NULL) {
-              fprintf(stderr,"Memory allocation error in directory_crawl.\n");
-              exit(EXIT_FAILURE);
-            }
-            // Append each new directory to the list
-            strcpy(directory[current_length],directory[i]);
-            strcat(directory[current_length],line_begin);
-            strcat(directory[current_length],"/");
-            directory_level[current_length] = current_level+1;
-            // Check to make sure it's valid
-            dir = opendir(directory[current_length]);
-            if (dir == NULL)
-              error(EXIT_FAILURE,errno,"directory:\n %s",directory[current_length]);
-            closedir(dir);
-            current_length++;
-          }
-          isdone = 0;  // We know we need to check the subdirectories
-          fclose(fp);
-        }  // end of: if (fp != NULL)
-      } // end of: if (directory_level[i] == current_level)
-    } // end of: loop over previous directories
-    current_level++;  // We're all done parsing this level, move on
-  } // end of: while (!isdone)
-  
-  return current_length;
-}
-
-void free_directories(int n)
-{
-  int i;
-
-  for (i = 0; i < n; i++) {
-    free(directory[i]);
-    directory[i] = NULL;
-  }
-}
-
-// Modify a string to eliminate leading and trailing
-// whitespace. Returns a pointer to the first non-space character.
-// Note the input string is modified in-place!
-char* eatwhite(char *buf)
-{
-  char *line_begin, *line_end;
-
-  // Eliminate leading whitespace
-  line_begin = buf;
-  while (isspace(*line_begin))
-    line_begin++;
-  // Eliminate trailing whitespace, especially the \n at the end of the line
-  line_end = line_begin+strlen(line_begin)-1;
-  while (line_end >= line_begin && isspace(*line_end)) {
-    *line_end = '\0';
-    line_end--;
-  }
-
-  return line_begin;
-}

-- 
tuxhistory - Educational history game



More information about the Tux4kids-commits mailing list