source: trunk/src/reglookup.c @ 168

Last change on this file since 168 was 168, checked in by tim, 14 years ago

merged remaining smb_deps items into regfi

began formatting API comments for use with doxygen

  • Property svn:keywords set to Id
File size: 16.9 KB
RevLine 
[30]1/*
[135]2 * A utility to read a Windows NT and later registry files.
[30]3 *
[135]4 * Copyright (C) 2005-2009 Timothy D. Morgan
[42]5 * Copyright (C) 2002 Richard Sharpe, rsharpe@richardsharpe.com
[30]6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
[111]9 * the Free Software Foundation; version 3 of the License.
[30]10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
19 *
20 * $Id: reglookup.c 168 2010-03-03 00:08:42Z tim $
21 */
22
23
24#include <stdlib.h>
25#include <stdio.h>
26#include <string.h>
[33]27#include <strings.h>
[42]28#include <time.h>
[147]29#include "regfi.h"
30#include "void_stack.h"
[30]31
[40]32/* Globals, influenced by command line parameters */
33bool print_verbose = false;
34bool print_security = false;
[42]35bool print_header = true;
[40]36bool path_filter_enabled = false;
37bool type_filter_enabled = false;
38char* path_filter = NULL;
39int type_filter;
40char* registry_file = NULL;
41
[42]42/* Other globals */
[135]43REGFI_FILE* f;
[66]44
[40]45
[116]46/* XXX: A hack to share some functions with reglookup-recover.c.
[125]47 *      Should move these into a proper library at some point.
[111]48 */
49#include "common.c"
[61]50
[38]51
[159]52void printValue(REGFI_ITERATOR* iter, const REGFI_VK_REC* vk, char* prefix)
[41]53{
[159]54  REGFI_DATA* data;
[111]55  char* quoted_value = NULL;
56  char* quoted_name = NULL;
57  char* conv_error = NULL;
58  const char* str_type = NULL;
[41]59
[162]60  if(vk->valuename == NULL)
61    quoted_name = quote_buffer(vk->valuename_raw, vk->name_length, 
62                               key_special_chars);
63  else
64    quoted_name = quote_string(vk->valuename, key_special_chars);
[111]65  if (quoted_name == NULL)
66  { /* Value names are NULL when we're looking at the "(default)" value.
67     * Currently we just return a 0-length string to try an eliminate
68     * ambiguity with a literal "(default)" value.  The data type of a line
69     * in the output allows one to differentiate between the parent key and
70     * this value.
71     */
72    quoted_name = malloc(1*sizeof(char));
73    if(quoted_name == NULL)
[143]74      bailOut(REGLOOKUP_EXIT_OSERR, "ERROR: Could not allocate sufficient memory.\n");
[111]75    quoted_name[0] = '\0';
76  }
[159]77 
78  data = regfi_iterator_fetch_data(iter, vk);
[41]79
[159]80  printMsgs(iter->f);
81  if(data != NULL)
[41]82  {
[159]83    quoted_value = data_to_ascii(data, &conv_error);
[138]84    if(quoted_value == NULL)
85    {
86      if(conv_error == NULL)
87        fprintf(stderr, "WARN: Could not quote value for '%s/%s'.  "
88                "Memory allocation failure likely.\n", prefix, quoted_name);
89      else
90        fprintf(stderr, "WARN: Could not quote value for '%s/%s'.  "
91                "Returned error: %s\n", prefix, quoted_name, conv_error);
92    }
[159]93    else if(conv_error != NULL)
94      fprintf(stderr, "WARN: While quoting value for '%s/%s', "
[138]95              "warning returned: %s\n", prefix, quoted_name, conv_error);
[159]96    regfi_free_data(data);
[138]97  }
[41]98
[111]99  str_type = regfi_type_val2str(vk->type);
100  if(print_security)
[41]101  {
[111]102    if(str_type == NULL)
103      printf("%s/%s,0x%.8X,%s,,,,,\n", prefix, quoted_name,
104             vk->type, quoted_value);
[66]105    else
[111]106      printf("%s/%s,%s,%s,,,,,\n", prefix, quoted_name,
107             str_type, quoted_value);
[71]108  }
[111]109  else
110  {
111    if(str_type == NULL)
112      printf("%s/%s,0x%.8X,%s,\n", prefix, quoted_name,
113             vk->type, quoted_value);
114    else
115      printf("%s/%s,%s,%s,\n", prefix, quoted_name,
116             str_type, quoted_value);
117  }
[42]118
[111]119  if(quoted_value != NULL)
120    free(quoted_value);
121  if(quoted_name != NULL)
122    free(quoted_name);
123  if(conv_error != NULL)
124    free(conv_error);
[41]125}
126
127
[81]128char** splitPath(const char* s)
[30]129{
[81]130  char** ret_val;
[38]131  const char* cur = s;
[33]132  char* next = NULL;
[38]133  char* copy;
[168]134  uint32_t ret_cur = 0;
[38]135
[135]136  ret_val = (char**)malloc((REGFI_MAX_DEPTH+1+1)*sizeof(char**));
[81]137  if (ret_val == NULL)
[38]138    return NULL;
[81]139  ret_val[0] = NULL;
140
141  /* We return a well-formed, 0-length, path even when input is icky. */
[37]142  if (s == NULL)
[81]143    return ret_val;
[38]144 
145  while((next = strchr(cur, '/')) != NULL)
[33]146  {
[38]147    if ((next-cur) > 0)
148    {
149      copy = (char*)malloc((next-cur+1)*sizeof(char));
150      if(copy == NULL)
[143]151        bailOut(REGLOOKUP_EXIT_OSERR, "ERROR: Memory allocation problem.\n");
[38]152         
153      memcpy(copy, cur, next-cur);
154      copy[next-cur] = '\0';
[81]155      ret_val[ret_cur++] = copy;
[135]156      if(ret_cur < (REGFI_MAX_DEPTH+1+1))
[81]157        ret_val[ret_cur] = NULL;
158      else
[143]159        bailOut(REGLOOKUP_EXIT_DATAERR, "ERROR: Registry maximum depth exceeded.\n");
[38]160    }
161    cur = next+1;
[33]162  }
[81]163
164  /* Grab last element, if path doesn't end in '/'. */
[33]165  if(strlen(cur) > 0)
[38]166  {
167    copy = strdup(cur);
[81]168    ret_val[ret_cur++] = copy;
[135]169    if(ret_cur < (REGFI_MAX_DEPTH+1+1))
[81]170      ret_val[ret_cur] = NULL;
171    else
[143]172      bailOut(REGLOOKUP_EXIT_DATAERR, "ERROR: Registry maximum depth exceeded.\n");
[38]173  }
[33]174
175  return ret_val;
176}
177
[81]178
[83]179void freePath(char** path)
180{
[168]181  uint32_t i;
[83]182
183  if(path == NULL)
184    return;
185
186  for(i=0; path[i] != NULL; i++)
187    free(path[i]);
188
189  free(path);
190}
191
192
[81]193/* Returns a quoted path from an iterator's stack */
194char* iter2Path(REGFI_ITERATOR* i)
[33]195{
[81]196  const REGFI_ITER_POSITION* cur;
[161]197  const REGFI_NK_REC* tmp_key;
[168]198  uint32_t buf_left = 127;
199  uint32_t buf_len = buf_left+1;
200  uint32_t name_len = 0;
201  uint32_t grow_amt;
[81]202  char* buf;
[31]203  char* new_buf;
[66]204  char* name;
[31]205  void_stack_iterator* iter;
206 
207  buf = (char*)malloc((buf_len)*sizeof(char));
208  if (buf == NULL)
209    return NULL;
[54]210  buf[0] = '\0';
[30]211
[81]212  iter = void_stack_iterator_new(i->key_positions);
[31]213  if (iter == NULL)
[30]214  {
[31]215    free(buf);
216    return NULL;
[30]217  }
218
[33]219  /* skip root element */
[81]220  if(void_stack_size(i->key_positions) < 1)
221  {
222    buf[0] = '/';
223    buf[1] = '\0';
224    return buf;
225  }
[33]226  cur = void_stack_iterator_next(iter);
227
[81]228  do
[31]229  {
[81]230    cur = void_stack_iterator_next(iter);
231    if (cur == NULL)
[161]232      tmp_key = i->cur_key;
[81]233    else
[161]234      tmp_key = cur->nk;
[81]235
[161]236    if(tmp_key->keyname == NULL)
237      name = quote_buffer(i->cur_key->keyname_raw, i->cur_key->name_length,
238                          key_special_chars);
239    else
240      name = quote_string(tmp_key->keyname, key_special_chars);
241
[33]242    buf[buf_len-buf_left-1] = '/';
243    buf_left -= 1;
[66]244    name_len = strlen(name);
[31]245    if(name_len+1 > buf_left)
246    {
[168]247      grow_amt = (uint32_t)(buf_len/2);
[31]248      buf_len += name_len+1+grow_amt-buf_left;
249      if((new_buf = realloc(buf, buf_len)) == NULL)
250      {
[136]251        free(name);
[31]252        free(buf);
253        free(iter);
254        return NULL;
255      }
256      buf = new_buf;
257      buf_left = grow_amt + name_len + 1;
258    }
[66]259    strncpy(buf+(buf_len-buf_left-1), name, name_len);
[31]260    buf_left -= name_len;
261    buf[buf_len-buf_left-1] = '\0';
[66]262    free(name);
[81]263  } while(cur != NULL);
[30]264
[31]265  return buf;
266}
[30]267
[31]268
[137]269void printValueList(REGFI_ITERATOR* iter, char* prefix)
[32]270{
[150]271  REGFI_VK_REC* value;
[80]272
[137]273  value = regfi_iterator_first_value(iter);
[80]274  while(value != NULL)
[81]275  {
276    if(!type_filter_enabled || (value->type == type_filter))
[159]277      printValue(iter, value, prefix);
[150]278    regfi_free_value(value);
[137]279    value = regfi_iterator_next_value(iter);
[138]280    printMsgs(iter->f);
[81]281  }
[33]282}
283
[37]284
[137]285void printKey(REGFI_ITERATOR* iter, char* full_path)
[33]286{
[43]287  static char empty_str[1] = "";
[42]288  char* owner = NULL;
289  char* group = NULL;
290  char* sacl = NULL;
291  char* dacl = NULL;
[125]292  char* quoted_classname;
[42]293  char mtime[20];
294  time_t tmp_time[1];
295  struct tm* tmp_time_s = NULL;
[135]296  const REGFI_SK_REC* sk;
[137]297  const REGFI_NK_REC* k = regfi_iterator_cur_key(iter);
[160]298  REGFI_CLASSNAME* classname;
[42]299
[168]300  *tmp_time = regfi_nt2unix_time(&k->mtime);
[43]301  tmp_time_s = gmtime(tmp_time);
302  strftime(mtime, sizeof(mtime), "%Y-%m-%d %H:%M:%S", tmp_time_s);
303
[137]304  if(print_security && (sk=regfi_iterator_cur_sk(iter)))
[43]305  {
[109]306    owner = regfi_get_owner(sk->sec_desc);
307    group = regfi_get_group(sk->sec_desc);
308    sacl = regfi_get_sacl(sk->sec_desc);
309    dacl = regfi_get_dacl(sk->sec_desc);
[43]310    if(owner == NULL)
311      owner = empty_str;
312    if(group == NULL)
313      group = empty_str;
314    if(sacl == NULL)
315      sacl = empty_str;
316    if(dacl == NULL)
317      dacl = empty_str;
318
[160]319    classname = regfi_iterator_fetch_classname(iter, k);
320    printMsgs(iter->f);
321    if(classname != NULL)
[126]322    {
[160]323      if(classname->interpreted == NULL)
[126]324      {
[160]325        fprintf(stderr, "WARN: Could not convert class name"
326                " charset for key '%s'.  Quoting raw...\n", full_path);
327        quoted_classname = quote_buffer(classname->raw, classname->size,
328                                        key_special_chars);
[126]329      }
[160]330      else
331        quoted_classname = quote_string(classname->interpreted, 
332                                        key_special_chars);
333
334      if(quoted_classname == NULL)
[126]335      {
[160]336        fprintf(stderr, "ERROR: Could not quote classname"
337                " for key '%s' due to unknown error.\n", full_path);
338        quoted_classname = empty_str;
[126]339      }
340    }
[125]341    else
342      quoted_classname = empty_str;
[160]343    regfi_free_classname(classname);
[43]344
[138]345    printMsgs(iter->f);
[125]346    printf("%s,KEY,,%s,%s,%s,%s,%s,%s\n", full_path, mtime, 
347           owner, group, sacl, dacl, quoted_classname);
348
[43]349    if(owner != empty_str)
350      free(owner);
351    if(group != empty_str)
352      free(group);
353    if(sacl != empty_str)
354      free(sacl);
355    if(dacl != empty_str)
356      free(dacl);
[125]357    if(quoted_classname != empty_str)
358      free(quoted_classname);
[43]359  }
360  else
[66]361    printf("%s,KEY,,%s\n", full_path, mtime);
[43]362}
363
364
[81]365void printKeyTree(REGFI_ITERATOR* iter)
[43]366{
[135]367  const REGFI_NK_REC* root = NULL;
368  const REGFI_NK_REC* cur = NULL;
[150]369  REGFI_NK_REC* sub = NULL;
[43]370  char* path = NULL;
[78]371  int key_type = regfi_type_str2val("KEY");
[81]372  bool print_this = true;
373
374  root = cur = regfi_iterator_cur_key(iter);
375  sub = regfi_iterator_first_subkey(iter);
[138]376  printMsgs(iter->f);
[137]377
[81]378  if(root == NULL)
[143]379    bailOut(REGLOOKUP_EXIT_DATAERR, "ERROR: root cannot be NULL.\n");
[81]380 
381  do
[31]382  {
[81]383    if(print_this)
[54]384    {
[81]385      path = iter2Path(iter);
386      if(path == NULL)
[143]387        bailOut(REGLOOKUP_EXIT_OSERR, "ERROR: Could not construct iterator's path.\n");
[137]388
[81]389      if(!type_filter_enabled || (key_type == type_filter))
[109]390        printKey(iter, path);
[81]391      if(!type_filter_enabled || (key_type != type_filter))
392        printValueList(iter, path);
393     
394      free(path);
[54]395    }
[66]396   
[81]397    if(sub == NULL)
[31]398    {
[81]399      if(cur != root)
[31]400      {
[81]401        /* We're done with this sub-tree, going up and hitting other branches. */
402        if(!regfi_iterator_up(iter))
[137]403        {
[138]404          printMsgs(iter->f);
[143]405          bailOut(REGLOOKUP_EXIT_DATAERR, "ERROR: could not traverse iterator upward.\n");
[137]406        }
407
[81]408        cur = regfi_iterator_cur_key(iter);
409        if(cur == NULL)
[137]410        {
[138]411          printMsgs(iter->f);
[143]412          bailOut(REGLOOKUP_EXIT_DATAERR, "ERROR: unexpected NULL for key.\n");
[137]413        }
[150]414       
[81]415        sub = regfi_iterator_next_subkey(iter);
[66]416      }
[81]417      print_this = false;
[31]418    }
[81]419    else
420    { /* We have unexplored sub-keys. 
421       * Let's move down and print this first sub-tree out.
422       */
423      if(!regfi_iterator_down(iter))
[137]424      {
[138]425        printMsgs(iter->f);
[143]426        bailOut(REGLOOKUP_EXIT_DATAERR, "ERROR: could not traverse iterator downward.\n");
[137]427      }
[81]428
[150]429      cur = regfi_iterator_cur_key(iter);
430      regfi_free_key(sub);
[81]431      sub = regfi_iterator_first_subkey(iter);
432      print_this = true;
433    }
[138]434    printMsgs(iter->f);
[81]435  } while(!((cur == root) && (sub == NULL)));
436
[54]437  if(print_verbose)
[138]438    fprintf(stderr, "INFO: Finished printing key tree.\n");
[30]439}
440
[81]441
[140]442/* XXX: What if there is BOTH a value AND a key with that name??
443 *      What if there are multiple keys/values with the same name??
444 */
[33]445/*
[80]446 * Returns 0 if path was not found.
447 * Returns 1 if path was found as value.
448 * Returns 2 if path was found as key.
[33]449 * Returns less than 0 on other error.
450 */
[80]451int retrievePath(REGFI_ITERATOR* iter, char** path)
[33]452{
[150]453  REGFI_VK_REC* value;
[81]454  char* tmp_path_joined;
455  const char** tmp_path;
[168]456  uint32_t i;
[80]457 
458  if(path == NULL)
[33]459    return -1;
460
[80]461  /* One extra for any value at the end, and one more for NULL */
[135]462  tmp_path = (const char**)malloc(sizeof(const char**)*(REGFI_MAX_DEPTH+1+1));
[80]463  if(tmp_path == NULL)
[33]464    return -2;
465
[80]466  /* Strip any potential value name at end of path */
467  for(i=0; 
[136]468      (path[i] != NULL) && (path[i+1] != NULL) && (i < REGFI_MAX_DEPTH+1);
[80]469      i++)
[136]470  { tmp_path[i] = path[i]; }
[80]471  tmp_path[i] = NULL;
472
[54]473  if(print_verbose)
[138]474    fprintf(stderr, "INFO: Attempting to retrieve specified path: %s\n",
[54]475            path_filter);
476
[82]477  /* Special check for '/' path filter */
478  if(path[0] == NULL)
479  {
480    if(print_verbose)
[138]481      fprintf(stderr, "INFO: Found final path element as root key.\n");
[136]482    free(tmp_path);
[82]483    return 2;
484  }
485
[80]486  if(!regfi_iterator_walk_path(iter, tmp_path))
[33]487  {
[138]488    printMsgs(iter->f);
[80]489    free(tmp_path);
490    return 0;
[33]491  }
492
[80]493  if(regfi_iterator_find_value(iter, path[i]))
494  {
495    if(print_verbose)
[138]496      fprintf(stderr, "INFO: Found final path element as value.\n");
[33]497
[80]498    value = regfi_iterator_cur_value(iter);
[138]499    printMsgs(iter->f);
[81]500    tmp_path_joined = iter2Path(iter);
[54]501
[80]502    if((value == NULL) || (tmp_path_joined == NULL))
[143]503      bailOut(REGLOOKUP_EXIT_OSERR, "ERROR: Unexpected error before printValue.\n");
[54]504
[121]505    if(!type_filter_enabled || (value->type == type_filter))
[159]506      printValue(iter, value, tmp_path_joined);
[54]507
[150]508    regfi_free_value(value);
[80]509    free(tmp_path);
510    free(tmp_path_joined);
511    return 1;
[33]512  }
[80]513  else if(regfi_iterator_find_subkey(iter, path[i]))
[33]514  {
[138]515    printMsgs(iter->f);
[80]516    if(print_verbose)
[138]517      fprintf(stderr, "INFO: Found final path element as key.\n");
[82]518
519    if(!regfi_iterator_down(iter))
[137]520    {
[138]521      printMsgs(iter->f);
[143]522      bailOut(REGLOOKUP_EXIT_DATAERR, "ERROR: Unexpected error on traversing path filter key.\n");
[137]523    }
[82]524
[80]525    return 2;
[33]526  }
[138]527  printMsgs(iter->f);
[33]528
[54]529  if(print_verbose)
[138]530    fprintf(stderr, "INFO: Could not find last element of path.\n");
[54]531
[80]532  return 0;
[33]533}
534
535
[37]536static void usage(void)
537{
[61]538  fprintf(stderr, "Usage: reglookup [-v] [-s]"
[40]539          " [-p <PATH_FILTER>] [-t <TYPE_FILTER>]"
[39]540          " <REGISTRY_FILE>\n");
[111]541  fprintf(stderr, "Version: %s\n", REGLOOKUP_VERSION);
[39]542  fprintf(stderr, "Options:\n");
543  fprintf(stderr, "\t-v\t sets verbose mode.\n");
[47]544  fprintf(stderr, "\t-h\t enables header row. (default)\n");
545  fprintf(stderr, "\t-H\t disables header row.\n");
[44]546  fprintf(stderr, "\t-s\t enables security descriptor output.\n");
547  fprintf(stderr, "\t-S\t disables security descriptor output. (default)\n");
[40]548  fprintf(stderr, "\t-p\t restrict output to elements below this path.\n");
549  fprintf(stderr, "\t-t\t restrict results to this specific data type.\n");
[37]550  fprintf(stderr, "\n");
551}
552
553
[30]554int main(int argc, char** argv)
555{
[80]556  char** path = NULL;
557  REGFI_ITERATOR* iter;
[33]558  int retr_path_ret;
[168]559  uint32_t argi, arge;
[31]560
[37]561  /* Process command line arguments */
[30]562  if(argc < 2)
563  {
[37]564    usage();
[143]565    bailOut(REGLOOKUP_EXIT_USAGE, "ERROR: Requires at least one argument.\n");
[30]566  }
[37]567 
[44]568  arge = argc-1;
569  for(argi = 1; argi < arge; argi++)
[37]570  {
[40]571    if (strcmp("-p", argv[argi]) == 0)
[37]572    {
[44]573      if(++argi >= arge)
[37]574      {
575        usage();
[143]576        bailOut(REGLOOKUP_EXIT_USAGE, "ERROR: '-p' option requires parameter.\n");
[37]577      }
[40]578      if((path_filter = strdup(argv[argi])) == NULL)
[143]579        bailOut(REGLOOKUP_EXIT_OSERR, "ERROR: Memory allocation problem.\n");
[38]580
[40]581      path_filter_enabled = true;
[37]582    }
583    else if (strcmp("-t", argv[argi]) == 0)
584    {
[44]585      if(++argi >= arge)
[37]586      {
587        usage();
[143]588        bailOut(REGLOOKUP_EXIT_USAGE, "ERROR: '-t' option requires parameter.\n");
[37]589      }
[78]590      if((type_filter = regfi_type_str2val(argv[argi])) < 0)
[40]591      {
592        fprintf(stderr, "ERROR: Invalid type specified: %s.\n", argv[argi]);
[143]593        bailOut(REGLOOKUP_EXIT_USAGE, "");
[40]594      }
[37]595      type_filter_enabled = true;
596    }
[47]597    else if (strcmp("-h", argv[argi]) == 0)
598      print_header = true;
599    else if (strcmp("-H", argv[argi]) == 0)
600      print_header = false;
[37]601    else if (strcmp("-s", argv[argi]) == 0)
602      print_security = true;
[44]603    else if (strcmp("-S", argv[argi]) == 0)
604      print_security = false;
[37]605    else if (strcmp("-v", argv[argi]) == 0)
606      print_verbose = true;
[44]607    else
[37]608    {
[38]609      usage();
[37]610      fprintf(stderr, "ERROR: Unrecognized option: %s\n", argv[argi]);
[143]611      bailOut(REGLOOKUP_EXIT_USAGE, "");
[37]612    }
613  }
[44]614  if((registry_file = strdup(argv[argi])) == NULL)
[143]615    bailOut(REGLOOKUP_EXIT_OSERR, "ERROR: Memory allocation problem.\n");
[30]616
[110]617  f = regfi_open(registry_file);
[37]618  if(f == NULL)
619  {
620    fprintf(stderr, "ERROR: Couldn't open registry file: %s\n", registry_file);
[143]621    bailOut(REGLOOKUP_EXIT_NOINPUT, "");
[37]622  }
[38]623
[138]624  if(print_verbose)
625    regfi_set_message_mask(f, REGFI_MSG_INFO|REGFI_MSG_WARN|REGFI_MSG_ERROR);
626
[159]627  /* XXX: add command line option to choose output encoding */
[161]628  iter = regfi_iterator_new(f, REGFI_ENCODING_ASCII);
[80]629  if(iter == NULL)
[158]630  {
631    printMsgs(f);
[143]632    bailOut(REGLOOKUP_EXIT_OSERR, "ERROR: Couldn't create registry iterator.\n");
[158]633  }
[30]634
[81]635  if(print_header)
636  {
637    if(print_security)
[125]638      printf("PATH,TYPE,VALUE,MTIME,OWNER,GROUP,SACL,DACL,CLASS\n");
[81]639    else
640      printf("PATH,TYPE,VALUE,MTIME\n");
641  }
642
[80]643  if(path_filter_enabled && path_filter != NULL)
644    path = splitPath(path_filter);
[81]645
[80]646  if(path != NULL)
[33]647  {
[80]648    retr_path_ret = retrievePath(iter, path);
[138]649    printMsgs(iter->f);
[83]650    freePath(path);
651
[80]652    if(retr_path_ret == 0)
[141]653      fprintf(stderr, "WARN: Specified path '%s' not found.\n", path_filter);
[80]654    else if (retr_path_ret == 2)
[81]655      printKeyTree(iter);
[93]656    else if(retr_path_ret < 0)
657    {
658      fprintf(stderr, "ERROR: retrievePath() returned %d.\n", 
659              retr_path_ret);
[143]660      bailOut(REGLOOKUP_EXIT_DATAERR,
661              "ERROR: Unknown error occurred in retrieving path.\n");
[93]662    }
[33]663  }
[37]664  else
[81]665    printKeyTree(iter);
[31]666
[80]667  regfi_iterator_free(iter);
[78]668  regfi_close(f);
[30]669
670  return 0;
671}
Note: See TracBrowser for help on using the repository browser.