Exemple #1
0
/* parses a plist file and returns a list of all files */
List *
parse_plist(Port *p, char *plistfile) {
   FILE *fd;
   char line[MAX_TOKEN];
   char path[MAX_PATH];
   List *l;

   if ((fd = fopen(plistfile, "r")) == NULL)
      return NULL; /* error */

   /* init */
   l = (List *)malloc(sizeof(List));
   l->head = NULL;
   l->tail = NULL;
   l->num_of_items = 0;

   while (fgets(line, MAX_TOKEN, fd) != NULL) {
      if ((line[0] != '\0') && (line[0] != ' ')
            && (line[0] != '@') && (line[0] != '%')) {
         /* valid path */
         Plist *pl = (Plist *)malloc(sizeof(Plist));
         line[strlen(line) - 1] = '\0';
         sprintf(path, "%s/%s", p->instpfx, line);
         pl->name = strdup(path);
         pl->exist = (access(path, F_OK) == 0) ? TRUE : FALSE; 
         add_list_item(l, pl);
      }
   }
   fclose(fd);

   return l;
}
Exemple #2
0
/* adds a port pointer to a category */
void
add_port_to_category(Category *cat, Port *p) {
   (cat->num_of_ports)++;
   if ((p->state == STATE_INSTALLED) ||
      (p->state == STATE_INSTALLED_OLDER) ||
      (p->state == STATE_INSTALLED_NEWER))
      (cat->num_of_inst_ports)++;
   add_list_item(cat->lprts, p);
}
// sort out invalid values by data copy
struct  dir_list_head_t* clean_up_dir_list(struct dir_list_head_t* o_dir ){
	struct dir_list_head_t* n_dir;
	int i;
	char *p;
	struct dir_list_t *pointer;


	n_dir = new_dir_list(o_dir->path_inode,o_dir->dir_inode," "," ");
	if (!n_dir) 
		return o_dir;

//change the allocatet names
	p = n_dir->pathname;
	n_dir->pathname = o_dir->pathname;
	o_dir->pathname = p;
	
	p = n_dir->dirname;
	n_dir->dirname = o_dir->dirname;
	o_dir->dirname = p;

//copy all practicable values
	pointer = o_dir->next;
	for (i = o_dir->count ; i>0 ; i-- , pointer = pointer->next ){
		if ( (!pointer->inode_nr) || (pointer->filename[0] == 0)  )
			continue;
		
		switch (pointer->entry){
		  case 	DIRENT_DOT_FILE:
//			 break;
		  case 	DIRENT_DOT_DOT_FILE:
			 break;
		  case	DIRENT_OTHER_FILE:
//			if (d_find_entry(n_dir , pointer->inode_nr , pointer->filename))
//			 	continue;
//			break;					
		  case	DIRENT_DELETED_FILE:
			if (d_find_entry(n_dir , pointer->inode_nr , pointer->filename)||
				(pointer->inode_nr < EXT2_GOOD_OLD_FIRST_INO))
			 	continue;
			break;
		  default:
			continue;
		}
		
		if(! add_list_item (n_dir, pointer->inode_nr , pointer->filename,0))
			fprintf(stderr, "ERROR by copy of dirlist");	
		
	}
clear_dir_list(o_dir);
return n_dir;
}	
Exemple #4
0
/* parses tokens, returns list pointer of token list */ 
List *
parse_tokenlist(char *toklist, char *delim) {
   char *tok;
   char *tlist = strdup(toklist);
   List *l = (List *)malloc(sizeof(List));

   /* init */
   l->head = NULL;
   l->tail = NULL;
   l->num_of_items = 0;

   tok = strtok(tlist, delim);
   while (tok != NULL) {
      add_list_item(l, strdup(tok));
      tok = strtok(NULL, delim);
   }
   free(tlist);

   return l;
}
Exemple #5
0
/* parses a file and returns a list, where each item is
   a line of the file */
List *
parse_file(char *filepath) {
   FILE *fd;
   char line[MAX_COLS];
   List *l;

   if ((fd = fopen(filepath, "r")) == NULL)
      return NULL; /* error */

   /* init */
   l = (List *)malloc(sizeof(List));
   l->head = NULL;
   l->tail = NULL;
   l->num_of_items = 0;

   while (fgets(line, MAX_COLS, fd) != NULL) 
      add_list_item(l, create_line(line));

   fclose(fd);
 
   return l;
}
Exemple #6
0
/* creates all categories through the given ports list */
void
create_categories(int num_of_inst_ports) {
   extern List *lprts;
   extern List *lcats;
   extern List *lphycats;
   Iter pitr = lprts->head;
   Iter citr = lcats->head;
   Node *n;
   Port *p;
   Category *newcat = (Category *)malloc(sizeof(Category));

   /* initialize meta category "Installed" */
   newcat->type = CATEGORY;
   newcat->name = "Installed";
   newcat->meta = TRUE;
   newcat->num_of_marked_ports = 0;
   newcat->num_of_deinst_ports = 0;
   newcat->lprts = (List *)malloc(sizeof(List));
   newcat->lprts->num_of_items = 0;
   newcat->lprts->head = NULL;
   newcat->lprts->tail = NULL;


   while (pitr != NULL) {
      p = (Port *)pitr->item;
      citr = p->lcats->head;
      while (citr != NULL) {
         add_port_to_category((Category *)citr->item, p);
         citr = citr->next;
      }
      if (p->state >= STATE_INSTALLED) /* meta cat "Installed" */
         add_port_to_category(newcat, p);
      pitr = pitr->next;
   }

   /* reinitialize meta cat "Installed" */
   newcat->num_of_ports =
      newcat->num_of_inst_ports = newcat->lprts->num_of_items;
 
   /* linking meta category "Installed" */
   n = (Node *)malloc(sizeof(Node));
   n->item = newcat;
   n->next = lcats->head;
   lcats->head = n;
   lcats->num_of_items++;

   /* last but not least we add meta category "All" */
   /* this trick speeds up this parser about four times */
   newcat = (Category *)malloc(sizeof(Category));
   newcat->type = CATEGORY;
   newcat->name = "All"; 
   newcat->meta = TRUE;
   newcat->num_of_ports = lprts->num_of_items;
   newcat->num_of_inst_ports = num_of_inst_ports;
   newcat->num_of_marked_ports = 0;
   newcat->num_of_deinst_ports = 0;
   newcat->lprts = lprts;

   /* linking everything together */
   n = (Node *)malloc(sizeof(Node));
   n->item = newcat;
   n->next = lcats->head;
   lcats->head = n;
   lcats->num_of_items++;

   /* last build up list of all physical categories */
   citr = lcats->head;
   add_list_item(lphycats, (Category *)citr->item); /* All */
   citr = citr->next;
   add_list_item(lphycats, (Category *)citr->item); /* Installed */
   while (citr != NULL) {
      newcat = (Category *)citr->item;
      if (newcat->meta == FALSE) /* found physical category */
         add_list_item(lphycats, newcat);
      citr = citr->next;
   }
}
Exemple #7
0
/* parses portsmanrc file and resets config if needed,
   returns 0 if everything was ok, ERROR_NO_RC_FILE if
   file could not be opened or a positive int of the
   line number where ERROR_CORRUPT_RC_FILE succeeded or
   an unknown keyword exist */
int
parse_rc_file(char *filepath) {
   FILE *fd;
   extern Config config;
   bool readyKey = FALSE;
   bool validKey = FALSE;
   bool readyValue = FALSE;
   bool comment = FALSE;
   char tok[MAX_TOKEN];
   char arg[MAX_TOKEN];
   char *key;
   char *val;
   int i = 0, c = 0, line = 0;
   short sh = 0;
   
   if ((fd = fopen(filepath, "r")) == NULL)
      return ERROR_NO_RC_FILE; /* not present */

   while (feof(fd) == 0) {
      c = fgetc(fd); /* get next char */
      switch (c) {
         case '\t': 
            break;
         case '#':
            comment = TRUE; /* until eol */
            if (validKey && (i > 0)) /* ready value */
               readyValue = TRUE;
            break;
         case '\n': /* eol */
            line++;
            comment = FALSE;
            /* ready value */
            if (validKey && (i > 0))  /* ready value */
               readyValue = TRUE;
            else {
               validKey = FALSE;
               readyKey = FALSE;
            }
            break;
         case '=':
            if (!comment) {
               if (i > 0)
                  readyKey = TRUE;
               else
                  return line;
            }
            break;
         default: /* else it's a alphanum char */
            if (!comment) 
               if ((c != ' ') || ((c == ' ') && validKey))
                  tok[i++] = (char)c;
            break;
      }

      if (readyKey) {
         tok[i] = '\0'; /* terminate key token */
         key = strdup(tok);
         i = 0;
         readyKey = FALSE;
         validKey = TRUE;
      } else if (readyValue) {
         tok[i] = '\0'; /* terminate value token */
         val = tok;

         if (strcmp(key, "use.metacats") == 0) {
            sh = str_to_state(val);
            if (sh == ERROR_CORRUPT_RC_FILE) {
               return (line); /* error */
            } else {
               config.use_metacats = (sh == STATE_SELECTED) ?
                  TRUE : FALSE;
            }
         } else if (strcmp(key, "titlebar.fcolor") == 0) {
            sh = str_to_color(val);
            if (sh == ERROR_CORRUPT_RC_FILE) {
               return (line); /* error */
            } else {
               config.fcolors[CLR_TITLE] = sh;
            }
         } else if (strcmp(key, "titlebar.bcolor") == 0) {
            sh = str_to_color(val);
            if (sh == ERROR_CORRUPT_RC_FILE) {
               return (line); /* error */
            } else {
               config.bcolors[CLR_TITLE] = sh;
            }
         } else if (strcmp(key, "browser.fcolor") == 0) {
            sh = str_to_color(val);
            if (sh == ERROR_CORRUPT_RC_FILE) {
               return (line); /* error */
            } else {
               config.fcolors[CLR_BROWSE] = sh;
            }
         } else if (strcmp(key, "browser.bcolor") == 0) {
            sh = str_to_color(val);
            if (sh == ERROR_CORRUPT_RC_FILE) {
               return (line); /* error */
            } else {
               config.bcolors[CLR_BROWSE] = sh;
            }
         } else if (strcmp(key, "statusbar.fcolor") == 0) {
            sh = str_to_color(val);
            if (sh == ERROR_CORRUPT_RC_FILE) {
               return (line); /* error */
            } else {
               config.fcolors[CLR_STATUS] = sh;
            }
         } else if (strcmp(key, "statusbar.bcolor") == 0) {
            sh = str_to_color(val);
            if (sh == ERROR_CORRUPT_RC_FILE) {
               return (line); /* error */
            } else {
               config.bcolors[CLR_STATUS] = sh;
            }
         } else if (strcmp(key, "cmdbar.fcolor") == 0) {
            sh = str_to_color(val);
            if (sh == ERROR_CORRUPT_RC_FILE) {
               return (line); /* error */
            } else {
               config.fcolors[CLR_CMD] = sh;
            }
         } else if (strcmp(key, "cmdbar.bcolor") == 0) {
            sh = str_to_color(val);
            if (sh == ERROR_CORRUPT_RC_FILE) {
               return (line); /* error */
            } else {
               config.bcolors[CLR_CMD] = sh;
            }
         } else if (strcmp(key, "selector.fcolor") == 0) {
            sh = str_to_color(val);
            if (sh == ERROR_CORRUPT_RC_FILE) {
               return (line); /* error */
            } else {
               config.fcolors[CLR_SELECTOR] = sh;
            }
         } else if (strcmp(key, "selector.bcolor") == 0) {
            sh = str_to_color(val);
            if (sh == ERROR_CORRUPT_RC_FILE) {
               return (line); /* error */
            } else {
               config.bcolors[CLR_SELECTOR] = sh;
            }
         } else if (strcmp(key, "indexfile") == 0) {
            config.index_file = strdup(val);
         } else if (strcmp(key, "pkgdir") == 0) {
            config.inst_pkg_dir = strdup(val);
         } else if (strcmp(key, "portsdir") == 0) {
            config.ports_dir = strdup(val);
         } else if (strcmp(key, "make.cmd") == 0) {
            config.make_cmd = strdup(val);
         } else if (strcmp(key, "make.target.inst") == 0) {
            config.make_target[MK_TARGET_INST] = strdup(val);
         } else if (strcmp(key, "make.target.deinst") == 0) {
            config.make_target[MK_TARGET_DEINST] = strdup(val);
         } else if (strcmp(key, "make.target.update") == 0) {
            config.make_target[MK_TARGET_UPDATE] = strdup(val);
         } else if (strcmp(key, "make.option.force") == 0) {
            sh = str_to_state(val);
            if (sh == ERROR_CORRUPT_RC_FILE) {
               return (line); /* error */
            } else {
               config.make_option[MK_OPTION_FORCE] = sh;
            }
         } else if (strcmp(key, "make.option.pkg") == 0) {
            sh = str_to_state(val);
            if (sh == ERROR_CORRUPT_RC_FILE) {
               return (line); /* error */
            } else {
               config.make_option[MK_OPTION_PKG] = sh;
            }
         } else if (strcmp(key, "make.option.clean") == 0) {
            sh = str_to_state(val);
            if (sh == ERROR_CORRUPT_RC_FILE) {
               return (line); /* error */
            } else {
               config.make_option[MK_OPTION_CLEAN] = sh;
            }
         } else if (strcmp(key, "make.option.nochksum") == 0) {
            sh = str_to_state(val);
            if (sh == ERROR_CORRUPT_RC_FILE) {
               return (line); /* error */
            } else {
               config.make_option[MK_OPTION_NOCHKSUM] = sh;
            }
         } else if (strcmp(key, "make.option.nodeps") == 0) {
            sh = str_to_state(val);
            if (sh == ERROR_CORRUPT_RC_FILE) {
               return (line); /* error */
            } else {
               config.make_option[MK_OPTION_NODEPS] = sh;
            }
         } else if (strcmp(key, "make.option.forcepkgreg") == 0) {
            sh = str_to_state(val);
            if (sh == ERROR_CORRUPT_RC_FILE) {
               return (line); /* error */
            } else {
               config.make_option[MK_OPTION_FORCEPKGREG] = sh;
            }
         } else if (strcmp(key, "make.option.nopkgreg") == 0) {
            sh = str_to_state(val);
            if (sh == ERROR_CORRUPT_RC_FILE) {
               return (line); /* error */
            } else {
               config.make_option[MK_OPTION_NOPKGREG] = sh;
            }
         } else if (strcmp(key, "make.option.force.arg") == 0) {
            sprintf(arg, "%s=yes", val);
            config.make_option_arg[MK_OPTION_FORCE] = strdup(arg);
         } else if (strcmp(key, "make.option.pkg.arg") == 0) {
            sprintf(arg, "%s=yes", val);
            config.make_option_arg[MK_OPTION_PKG] = strdup(arg);
         } else if (strcmp(key, "make.option.clean.arg") == 0) {
            sprintf(arg, "%s=yes", val);
            config.make_option_arg[MK_OPTION_CLEAN] = strdup(arg);
         } else if (strcmp(key, "make.option.nochksum.arg") == 0) {
            sprintf(arg, "%s=yes", val);
            config.make_option_arg[MK_OPTION_NOCHKSUM] = strdup(arg);
         } else if (strcmp(key, "make.option.nodeps.arg") == 0) {
            sprintf(arg, "%s=yes", val);
            config.make_option_arg[MK_OPTION_NODEPS] = strdup(arg);
         } else if (strcmp(key, "make.option.forcepkgreg.arg") == 0) {
            sprintf(arg, "%s=yes", val);
            config.make_option_arg[MK_OPTION_FORCEPKGREG] = strdup(arg);
         } else if (strcmp(key, "make.option.nopkgreg.arg") == 0) {
            sprintf(arg, "%s=yes", val);
            config.make_option_arg[MK_OPTION_NOPKGREG] = strdup(arg);
         } else if (strcmp(key, "rsync.cmd") == 0) {
            config.rsync_cmd = strdup(val);
         } else if (strcmp(key, "rsync.hostname") == 0) {
            if (!has_item(config.lrsynchosts, val, cmp_str))
               add_list_item(config.lrsynchosts, strdup(val));
         } else {
            return line; /* also error: unknown key */
         }

         readyValue = FALSE;
         validKey = FALSE;
         free(key);
         i = 0;
     }

   }
   fclose(fd);

   return (0);
}
Exemple #8
0
/* parses the FreeBSD ports INDEX file and creates a
   list of categories with dedicated ports, it also creates
   a meta-category "all", all lists and categories are
   sorted ascending. */
int
parse_index()
{
   FILE *fd;
   int c, i, readyToken;
   int pipes = 0;
   char tok[MAX_TOKEN];
   extern Config config;
   extern List *lprts;
   extern List *lcats;
   extern void *exists;
   extern TNode *tcat;
   TNode *tdirs;
   TNode *tprt = NULL;
   List *lpdir = (List *)malloc(sizeof(List));
   Port *p, *dprt;
   int num_of_inst_ports = 0;

   /* init */
   p = NULL;
   tcat = NULL;
   lpdir->num_of_items = 0;
   lpdir->head = NULL;
   lpdir->tail = NULL;

   if ((fd = fopen(config.index_file, "r")) == NULL)
      return ERROR_OPEN_INDEX; /* error */

   /* parse installed pkgs */
   tdirs = parse_dir(config.inst_pkg_dir);
   /* parse ports dir and create list */
   create_inorder_list(lpdir, parse_dir(config.ports_dir));

   i = 0;
   readyToken = 0; /* token not ready */
   while (feof(fd) == 0) {
      c = fgetc(fd); /* get next char */
      switch (c) {
         case '|': /* next token */
            readyToken = 1; /* ready token */
            break;
         case '\n': /* end of port */
#if defined(__FreeBSD__)
            if (pipes != PORT_URL) /* seems to be some strange INDEX */ 
               return ERROR_CORRUPT_INDEX;
#endif
            readyToken = 1; /* tail token of port ready */
            break;
         default:
            if ((pipes != PORT_CATEGORY) && (pipes != PORT_BUILD_DEPENDENCY)
                  && (pipes != PORT_RUN_DEPENDENCY))
               /* default, no port category, build dep or run dep modus */
               tok[i++] = (char)c;
            break;
      }

      /* to speed up the parsing, we also parse categories here,
         I guessed if it'll be senseful to also parse BDEP and RDEP,
         but this makes no sense until there aren't all entries
         scanned */
      if (pipes == PORT_CATEGORY) { /* port category mode */
         if ((c == ' ') || (c == '|')) {
            if (i > 0) { /* maybe there're ports without a category */
               tok[i] = '\0'; /* terminate current cat token */
               add_list_item(p->lcats, add_category(tok, lpdir));
               i = 0; /* reset i */
            }
         } else { /* inside a token */
            tok[i++] = (char)c;
         }
      } else if ((pipes == PORT_BUILD_DEPENDENCY) ||
            (pipes == PORT_RUN_DEPENDENCY)) { /* port build/run dep mode */
         if ((c == ' ') || (c == '|')) {
            if (i > 0) { /* maybe there're ports without a build dep */
               tok[i] = '\0';
               dprt = create_port(tok, tdirs);
               exists = NULL;
               tprt = add_tree_item(tprt, dprt, cmp_name);
               if (exists != NULL) {
                  free_port(dprt);
                  dprt = (Port *)((TNode *)exists)->item;
               } else {
                  if (dprt->state >= STATE_INSTALLED)
                     num_of_inst_ports++;
               }
               if (pipes == PORT_BUILD_DEPENDENCY) {
                  add_list_item(p->lbdep, dprt);
               } else if (pipes == PORT_RUN_DEPENDENCY) {
                  add_list_item(p->lrdep, dprt);
               }
               /* add also p to dprt->ldep, so that dprt knows
                  the port for which dprt is a dependency, this
                  helps seeking for unused ports */
               add_list_item(dprt->ldep, p);
               i = 0; /* reset i */
            }
         } else { /* inside a token */
            tok[i++] = (char)c;
         }
      }

      if (readyToken == 1) { /* a new token is ready */
         tok[i] = '\0'; /* terminate current token */
         switch (pipes) {
            case PORT_NAME_VERSION:
               p = create_port(tok, tdirs);
               /* add the port */
               exists = NULL;
               tprt = add_tree_item(tprt, p, cmp_name);
               if (exists != NULL) {
                  free_port(p);
                  p = (Port *)((TNode *)exists)->item;
               } else {
                  if (p->state >= STATE_INSTALLED)
                     num_of_inst_ports++;
               }
               break;
            case PORT_PATH:
               p->path = strdup(tok);
               break;
#if defined(__FreeBSD__)
            case PORT_INSTALL_PREFIX:
               p->instpfx = strdup(tok);
               break;
#endif
            case PORT_DESCR:
               p->descr = strdup(tok);
               break;
            case PORT_PKGDESCR:
               p->pathpkgdesc = strdup(tok);
               break;
            case PORT_MAINTAINER:
               p->maintainer = strdup(tok);
               break;
#if defined(__FreeBSD__)
            case PORT_URL:
               p->url = strdup(tok);
               pipes = -1;
               break;
#endif
         }
         readyToken = i = 0; /* token processed, not ready token anymore */
         pipes++;
      }
   }
   fclose(fd); /* close INDEX file */

   create_inorder_list(lcats, tcat);
   create_inorder_list(lprts, tprt);
   create_categories(num_of_inst_ports);
   free_tree(tdirs);

   /* finished */
   return (0);
}
Exemple #9
0
/* insert new node into config tree and return a pointer to it
 * if *tree is NULL, it will be set to point to the root node */
conf_node *add_keyword(conf_node **tree, const char *keyword, const void *data, ssize_t size) {
	conf_node	*new_node, *cur_node;
	char		*key, *subkey;

	cur_node	= *tree;
	new_node	= NULL;
	key		= NULL;
	subkey		= NULL;


	if (!keyword) {
		logmsg(LOG_WARN, 1, "Warning - Unable to extend configuration tree: No keyword given.\n");
		return(*tree);
	}

	// check whether a prefix does already exist and if not, add it recursively
	if ((key = strdup(keyword)) ==  NULL) {
		logmsg(LOG_ERR, 1, "Error - Unable to allocate memory: %m.\n");
		return(NULL);
	}

	/* add recursively */
	if ((cur_node = check_keyword(*tree, key)) == NULL) {
		if ((subkey = strrchr(key, '.')) != NULL) {
			subkey[0] = 0;		// zero-terminate first half
			subkey++;		// pointer to second half
			if (isdigit(subkey[0])) {
				if ((cur_node = check_keyword(*tree, key)) == NULL)
					if ((cur_node = add_keyword(tree, key, NULL, 0)) == NULL) return(NULL);
				if (add_list_item(cur_node, data, size) == NULL) {
					fprintf(stderr, "  Error - Unable to add list item for %s.\n", key);
					return(NULL);
				}
				return(cur_node);
			}
			if ((cur_node = add_keyword(tree, key, NULL, 0)) == NULL) return(NULL);
		}
	} else return(cur_node);

	// create new node and insert it into tree
	if ((new_node = malloc(sizeof(conf_node))) == NULL) {
		logmsg(LOG_ERR, 1, "Error - Unable to allocate memory: %m.\n");
		free(key);
		return(NULL);
	}
	memset(new_node, 0, sizeof(conf_node));
	// if keyword is a toplevel key, add it, else add subkey
	if ((new_node->keyword = strdup(subkey ? subkey : key)) == NULL) {
		logmsg(LOG_ERR, 1, "Error - Unable to allocate memory: %m.\n");
		free(key);
		return(NULL);
	}
	free(key);

	if (size) {
		if (add_list_item(new_node, data, size) == NULL) {
			fprintf(stderr, "  Error - Unable to add list item for %s.\n", keyword);
			return(NULL);
		}
	}

	/* insert new node into tree */
	if (cur_node) {
		/* it's an internal node */
		if (cur_node->first_leaf) {
			cur_node = cur_node->first_leaf;
			while (cur_node->next) cur_node = cur_node->next;
			cur_node->next = new_node;
		} else cur_node->first_leaf = new_node;
	} else {
		/* it's a top level node */
		if (!(*tree)) (*tree) = new_node;
		/* it's a root's neighbor */
		else {
			cur_node = *tree;
			while (cur_node->next) cur_node = cur_node->next;
			cur_node->next = new_node;
		}
	}
	if (*tree == NULL) *tree = cur_node;

	return(new_node);
}
Exemple #10
0
/* init_global_config_store()
Initialize the global configuration store by parsing command line arguments.

This function must only be called from the main thread.
For now there is only one configuration store implemented and it's a global store (G->config).
'G->config' depends on the global program (G->prog) store.
*/
void init_global_config_store( void )
{
	int i = 0;
	unsigned arf = 0;
	char *debugstr = NULL;
	
	FAIL_IF( !G );   // The global store must exist.
	
	FAIL_IF( G->config->init_time );   // Fail if this store has already been initialized.
	
	FAIL_IF( !G->prog->init_time );   // The program store must be initialized.
	
	FAIL_IF( GetCurrentThreadId() != G->prog->dwMainThreadId );   // main thread only
	
	
	debugstr = getenv( "GETHOOKS_DEBUG" );
	if( debugstr && ( debugstr[ 0 ] == '1' ) && !debugstr[ 1 ] )
		G->config->flags |= CFG_DEBUG;
	
	G->config->polling = POLLING_DEFAULT;
	G->config->verbose = VERBOSE_DEFAULT;
	G->config->max_threads = MAX_THREADS_DEFAULT;
	
	/* parse command line arguments */
	i = 0;
	while( arf != END )
	{
		if( arf != OPT ) /* attempt to get an option from the command line arguments */
			arf = get_next_arg( &i, OPT );
		
		if( arf != OPT )
			continue;
		
		/* option found */
		
		switch( G->prog->argv[ i ][ 1 ] )
		{
			case '?':
			case 'h':
			case 'H':
			{
				/* show help */
				print_usage_and_exit();
			}
			
			
			/**
			desktop include option
			*/
			case 'd':
			case 'D':
			{
				G->config->desklist->type = LIST_INCLUDE_DESK;
				
				/* since this option may or may not have an associated argument, 
				test for both an option's argument(optarg) or the next option
				*/
				arf = get_next_arg( &i, OPT | OPTARG );
				
				if( arf != OPTARG )
					continue;
				
				while( arf == OPTARG ) /* option argument found */
				{
					WCHAR *name = NULL;
					
					
					/* make the desktop name as a wide character string */
					if( !get_wstr_from_mbstr( &name, G->prog->argv[ i ] ) )
					{
						MSG_FATAL( "get_wstr_from_mbstr() failed." );
						printf( "desktop: %s\n", G->prog->argv[ i ] );
						exit( 1 );
					}
					
					/* append to the linked list */
					if( !add_list_item( G->config->desklist, 0, name ) )
					{
						MSG_FATAL( "add_list_item() failed." );
						printf( "desktop: %s\n", G->prog->argv[ i ] );
						exit( 1 );
					}
					
					/* if add_list_item() was successful then it made a duplicate of the 
					wide string pointed to by name. in any case name should now be freed.
					*/
					free( name );
					name = NULL;
					
					/* get the option's next argument, which is optional */
					arf = get_next_arg( &i, OPT | OPTARG );
				}
				
				continue;
			}
			
			
			
			/** 
			monitor option
			*/
			case 'm':
			case 'M':
			{
				if( G->config->polling != POLLING_DEFAULT )
				{
					MSG_FATAL( "Option 'm': this option has already been specified." );
					printf( "sec: %d\n", G->config->polling );
					exit( 1 );
				}
				
				G->config->polling = POLLING_ENABLED_DEFAULT;
				
				/* since this option may or may not have an associated argument, 
				test for both an option's argument(optarg) or the next option
				*/
				arf = get_next_arg( &i, OPT | OPTARG );
				
				if( arf != OPTARG )
					continue;
				
				/* option argument found */
				
				if( !str_to_int( &G->config->polling, G->prog->argv[ i ] ) )
				{
					MSG_FATAL( "Option 'm': the string is not an integer representation." );
					printf( "sec: %s\n", G->prog->argv[ i ] );
					exit( 1 );
				}
				
				if( G->config->polling == 0 )
				{
					MSG_WARNING( "Option 'm': an interval of 0 uses too much CPU time." );
					printf( "sec: %s\n", G->prog->argv[ i ] );
				}
				
				if( G->config->polling > 86400 ) // number of seconds in a day
				{
					MSG_WARNING( "Option 'm': more seconds than in a day (86400)." );
					printf( "sec: %s\n", G->prog->argv[ i ] );
				}
				
				if( G->config->polling < POLLING_MIN )
				{
					MSG_FATAL( "Option 'm': less seconds than the minimum allowed." );
					printf( "sec: %s\n", G->prog->argv[ i ] );
					printf( "POLLING_MIN: %d\n", POLLING_MIN );
					exit( 1 );
				}
				else if( G->config->polling > POLLING_MAX )
				{
					MSG_FATAL( "Option 'm': more seconds than the maximum allowed." );
					printf( "sec: %s\n", G->prog->argv[ i ] );
					printf( "POLLING_MAX: %d\n", POLLING_MAX );
					exit( 1 );
				}
				
				continue;
			}
			
			
			
			/**
			hook include/exclude options
			i: include list for hooks
			x: exclude list for hooks
			*/
			case 'i':
			case 'I':
			{
				if( G->config->hooklist->type == LIST_EXCLUDE_HOOK )
				{
					MSG_FATAL( "Options 'i' and 'x' are mutually exclusive." );
					exit( 1 );
				}
				
				G->config->hooklist->type = LIST_INCLUDE_HOOK;
			}
			/* pass through to the exclude code. 
			the exclude code can handle either type of list, include or exclude.
			*/
			case 'x':
			case 'X':
			{
				if( G->config->hooklist->type != LIST_INCLUDE_HOOK )
				{
					G->config->hooklist->type = LIST_EXCLUDE_HOOK;
				}
				else if( ( G->prog->argv[ i ][ 1 ] == 'x' ) || ( G->prog->argv[ i ][ 1 ] == 'X' ) )
				{
					MSG_FATAL( "Options 'i' and 'x' are mutually exclusive." );
					exit( 1 );
				}
				
				/* the 'i' or 'x' option requires at least one associated argument (optarg).
				if an optarg is not found get_next_arg() will exit(1)
				*/
				arf = get_next_arg( &i, OPTARG );
				
				while( arf == OPTARG ) /* option argument found */
				{
					__int64 id = 0;
					WCHAR *name = NULL;
					
					/* if the string is not an integer then it's a hook name not an id */
					if( !str_to_int64( &id, G->prog->argv[ i ] ) )
					{
						id = 0;
						
						/* make the hook name as a wide character string */
						if( !get_wstr_from_mbstr( &name, G->prog->argv[ i ] ) )
						{
							MSG_FATAL( "get_wstr_from_mbstr() failed." );
							printf( "hook: %s\n", G->prog->argv[ i ] );
							exit( 1 );
						}
						
						_wcsupr( name ); /* convert hook name to uppercase */
					}
					
					/* append to the linked list */
					if( !add_list_item( G->config->hooklist, id, name ) )
					{
						MSG_FATAL( "add_list_item() failed." );
						printf( "hook: %s\n", G->prog->argv[ i ] );
						exit( 1 );
					}
					
					/* if add_list_item() was successful then it made a duplicate of the 
					wide string pointed to by name. in any case name should now be freed.
					*/
					free( name );
					name = NULL;
					
					/* get the option's next argument, which is optional */
					arf = get_next_arg( &i, OPT | OPTARG );
				}
				
				continue;
			}
			
			
			
			/**
			program include/exclude options
			p: include list for programs
			r: exclude list for programs
			*/
			case 'p':
			case 'P':
			{
				if( G->config->proglist->type == LIST_EXCLUDE_PROG )
				{
					MSG_FATAL( "Options 'p' and 'r' are mutually exclusive." );
					exit( 1 );
				}
				
				G->config->proglist->type = LIST_INCLUDE_PROG;
			}
			/* pass through to the exclude code. 
			the exclude code can handle either type of list, include or exclude.
			*/
			case 'r':
			case 'R':
			{
				if( G->config->proglist->type != LIST_INCLUDE_PROG )
				{
					G->config->proglist->type = LIST_EXCLUDE_PROG;
				}
				else if( ( G->prog->argv[ i ][ 1 ] == 'r' ) || ( G->prog->argv[ i ][ 1 ] == 'R' ) )
				{
					MSG_FATAL( "Options 'p' and 'r' are mutually exclusive." );
					exit( 1 );
				}
				
				
				/* the 'p' or 'r' option requires at least one associated argument (optarg).
				if an optarg is not found get_next_arg() will exit(1)
				*/
				arf = get_next_arg( &i, OPTARG );
				
				while( arf == OPTARG ) /* option argument found */
				{
					__int64 id = 0;
					WCHAR *name = NULL;
					const char *p = G->prog->argv[ i ];
					
					
					/* a colon is used as the escape character. 
					if the first character is a colon then a program name 
					is specified, not a PID/TID. this is only necessary 
					in cases where a program name can be mistaken by 
					the parser for an option or a PID/TID.
					*/
					if( *p == ':' )
						++p;
					
					/* if the first character is a colon, or the string is not an integer, 
					or it is and the integer is negative, then assume program name
					*/
					if( ( p != G->prog->argv[ i ] ) 
						|| ( str_to_int64( &id, G->prog->argv[ i ] ) != NUM_POS )
					)
					{
						/* make the program name as a wide character string */
						if( !get_wstr_from_mbstr( &name, p ) )
						{
							MSG_FATAL( "get_wstr_from_mbstr() failed." );
							printf( "prog: %s\n", G->prog->argv[ i ] );
							exit( 1 );
						}
						
						//_wcslwr( name ); /* convert program name to lowercase */
						
						/* program name and id are mutually exclusive. 
						elsewhere in the code if a list item's name != NULL 
						then its id is ignored.
						*/
					}
					/* else the id is valid and name remains NULL*/
					
					/* append to the linked list */
					if( !add_list_item( G->config->proglist, id, name ) )
					{
						MSG_FATAL( "add_list_item() failed." );
						printf( "prog: %s\n", G->prog->argv[ i ] );
						exit( 1 );
					}
					
					/* if add_list_item() was successful then it made a duplicate of the 
					wide string pointed to by name. in any case name should now be freed.
					*/
					free( name );
					name = NULL;
					
					/* get the option's next argument, which is optional */
					arf = get_next_arg( &i, OPT | OPTARG );
				}
				
				continue;
			}
			
			
			
			/** 
			verbosity option
			*/
			case 'v':
			case 'V':
			{
				if( G->config->verbose != VERBOSE_DEFAULT )
				{
					MSG_FATAL( "Option 'v': this option has already been specified." );
					printf( "verbosity level: %d\n", G->config->verbose );
					exit( 1 );
				}
				
				G->config->verbose = VERBOSE_ENABLED_DEFAULT;
				
				/* since this option may or may not have an associated argument, 
				test for both an option's argument(optarg) or the next option
				*/
				arf = get_next_arg( &i, OPT | OPTARG );
				
				if( arf != OPTARG )
					continue;
				
				/* option argument found */
				
				if( !str_to_int( &G->config->verbose, G->prog->argv[ i ] ) )
				{
					MSG_FATAL( "Option 'v': the string is not an integer representation." );
					printf( "num: %s\n", G->prog->argv[ i ] );
					exit( 1 );
				}
				
				if( G->config->verbose < VERBOSE_MIN )
				{
					MSG_FATAL( "Option 'v': less verbosity than the minimum allowed." );
					printf( "num: %s\n", G->prog->argv[ i ] );
					printf( "VERBOSE_MIN: %d\n", VERBOSE_MIN );
					exit( 1 );
				}
				else if( G->config->verbose > VERBOSE_MAX )
				{
					MSG_FATAL( "Option 'v': more verbosity than the maximum allowed." );
					printf( "num: %s\n", G->prog->argv[ i ] );
					printf( "VERBOSE_MAX: %d\n", VERBOSE_MAX );
					exit( 1 );
				}
				
				continue;
			}
			
			
			
			/**
			threads option (advanced)
			*/
			case 't':
			case 'T':
			{
				if( G->config->max_threads != MAX_THREADS_DEFAULT )
				{
					MSG_FATAL( "Option 't': this option has already been specified." );
					printf( "max threads: %u\n", G->config->max_threads );
					exit( 1 );
				}
				
				/* this option must have an associated argument (optarg). 
				if an optarg is not found get_next_arg() will exit(1)
				*/
				arf = get_next_arg( &i, OPTARG );
				
				/* option argument found */
				
				/* if the string is not a positive integer representation > 0 */
				if( ( str_to_uint( &G->config->max_threads, G->prog->argv[ i ] ) != NUM_POS ) 
					|| ( G->config->max_threads <= 0 ) 
				)
				{
					MSG_FATAL( "Option 't': maximum number of threads invalid." );
					printf( "num: %s\n", G->prog->argv[ i ] );
					exit( 1 );
				}
				
				continue;
			}
			
			
			
			/**
			test mode include option (advanced)
			*/
			case 'z':
			case 'Z':
			{
				unsigned __int64 id = 0;
				WCHAR *name = NULL;
				
				
				G->config->testlist->type = LIST_INCLUDE_TEST;
				
				/* the 'z' option requires one associated argument (optarg), and a second which is 
				optional.
				*/
				arf = get_next_arg( &i, OPT | OPTARG );
				if( arf != OPTARG )
				{
					print_testmode_usage();
					exit( 1 );
				}
				
				/* make the test name as a wide character string */
				if( !get_wstr_from_mbstr( &name, G->prog->argv[ i ] ) )
				{
					MSG_FATAL( "get_wstr_from_mbstr() failed." );
					printf( "name: %s\n", G->prog->argv[ i ] );
					exit( 1 );
				}
				
				arf = get_next_arg( &i, OPT | OPTARG ); // get the second optarg, which is optional
				
				/* at least one option argument (optarg) was found */
				
				/* if a second optarg was found it's the id. the value of id will be UI64_MAX if 
				the conversion fails or there's no second optarg.
				*/
				if( arf == OPTARG )
					str_to_uint64( &id, G->prog->argv[ i ] );
				else
					id = UI64_MAX;
				
				/* append to the linked list */
				if( !add_list_item( G->config->testlist, (__int64)id, name ) )
				{
					MSG_FATAL( "add_list_item() failed." );
					printf( "test id: 0x%I64X\n", id );
					printf( "test name: %ls\n", name );
					exit( 1 );
				}
				
				/* if add_list_item() was successful then it made a duplicate of the 
				wide string pointed to by name. in any case name should now be freed.
				*/
				free( name );
				name = NULL;
				
				continue;
			}
			
			
			
			/**
			option to ignore internal hooks (advanced)
			*/
			case 'e':
			case 'E':
			{
				G->config->flags |= CFG_IGNORE_INTERNAL_HOOKS;
				arf = get_next_arg( &i, OPT );
				continue;
			}
			
			
			
			/**
			option to ignore known hooks (advanced)
			*/
			case 'u':
			case 'U':
			{
				G->config->flags |= CFG_IGNORE_KNOWN_HOOKS;
				arf = get_next_arg( &i, OPT );
				continue;
			}
			
			
			
			/**
			option to ignore targeted hooks (advanced)
			*/
			case 'g':
			case 'G':
			{
				G->config->flags |= CFG_IGNORE_TARGETED_HOOKS;
				arf = get_next_arg( &i, OPT );
				continue;
			}
			
			
			
			/**
			option to ignore failed NtQuerySystemInformation() calls (advanced)
			*/
			case 'f':
			case 'F':
			{
				G->config->flags |= CFG_IGNORE_FAILED_QUERIES;
				arf = get_next_arg( &i, OPT );
				continue;
			}
			
			
			
			/**
			option to ignore hook lock count changes (advanced)
			*/
			case 'c':
			case 'C':
			{
				G->config->flags |= CFG_IGNORE_LOCK_COUNTS;
				arf = get_next_arg( &i, OPT );
				continue;
			}
			
			
			
			/**
			option to go completely passive (advanced)
			*/
			case 'y':
			case 'Y':
			{
				G->config->flags |= CFG_COMPLETELY_PASSIVE;
				arf = get_next_arg( &i, OPT );
				continue;
			}
			
			
			
			default:
			{
				MSG_FATAL( "Unknown option." );
				printf( "OPT: %s\n", G->prog->argv[ i ] );
				exit( 1 );
			}
		}
	}
	
	
	
	if( ( G->config->proglist->type == LIST_INCLUDE_PROG )
		|| ( G->config->proglist->type == LIST_EXCLUDE_PROG )
	)
		GetSystemTimeAsFileTime( (FILETIME *)&G->config->proglist->init_time );
	
	if( ( G->config->hooklist->type == LIST_INCLUDE_HOOK )
		|| ( G->config->hooklist->type == LIST_EXCLUDE_HOOK )
	)
		GetSystemTimeAsFileTime( (FILETIME *)&G->config->hooklist->init_time );
	
	if( ( G->config->desklist->type == LIST_INCLUDE_DESK ) )
		GetSystemTimeAsFileTime( (FILETIME *)&G->config->desklist->init_time );
	
	if( ( G->config->testlist->type == LIST_INCLUDE_TEST ) )
		GetSystemTimeAsFileTime( (FILETIME *)&G->config->testlist->init_time );
	
	
	/* G->config has been initialized */
	GetSystemTimeAsFileTime( (FILETIME *)&G->config->init_time );
	return;
}