home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume28 / bcs-2.0 / part02 < prev    next >
Encoding:
Text File  |  1994-03-29  |  49.8 KB  |  1,864 lines

  1. Newsgroups: comp.sources.unix
  2. From: ejb@ERA.COM (Jay Berkenbilt)
  3. Subject: v28i003: bcs-2.0 - A Baseline Configuration System, Part02/25
  4. References: <1.764985670.1461@gw.home.vix.com>
  5. Sender: unix-sources-moderator@gw.home.vix.com
  6. Approved: vixie@gw.home.vix.com
  7.  
  8. Submitted-By: ejb@ERA.COM (Jay Berkenbilt)
  9. Posting-Number: Volume 28, Issue 3
  10. Archive-Name: bcs-2.0/part02
  11.  
  12. #!/bin/sh
  13. # this is bcs.02 (part 2 of bcs-2.0)
  14. # do not concatenate these parts, unpack them in order with /bin/sh
  15. # file bcs-2.0/lib/file_info.c continued
  16. #
  17. if test ! -r _shar_seq_.tmp; then
  18.     echo 'Please unpack part 1 first!'
  19.     exit 1
  20. fi
  21. (read Scheck
  22.  if test "$Scheck" != 2; then
  23.     echo Please unpack part "$Scheck" next!
  24.     exit 1
  25.  else
  26.     exit 0
  27.  fi
  28. ) < _shar_seq_.tmp || exit 1
  29. if test ! -f _shar_wnt_.tmp; then
  30.     echo 'x - still skipping bcs-2.0/lib/file_info.c'
  31. else
  32. echo 'x - continuing file bcs-2.0/lib/file_info.c'
  33. sed 's/^X//' << 'SHAR_EOF' >> 'bcs-2.0/lib/file_info.c' &&
  34. X * This notice must be kept intact when this file is distributed.
  35. X *
  36. X * This file is concerned with maintaining the file information table.
  37. X */
  38. X
  39. #if !defined(lint) && !defined(CODECENTER) || defined(RCS_HDRS)
  40. /* Define a static function and call it.  No warnings this way. */
  41. static void rcsid(char *s)
  42. {rcsid("@(#)$Id: file_info.c,v 1.45 1994/03/14 16:53:44 ejb Exp $");}
  43. #endif /* !lint && !CODECENTER || RCS_HDRS */
  44. X
  45. #include "bcs_p.h"
  46. #include "file_info.h"
  47. X
  48. #define ALL_IMPORTANT "*"
  49. X
  50. X
  51. /*
  52. X * PRIVATE ROUTINES
  53. X */
  54. X
  55. static fi_file_queue_entry new_fi_file_queue_entry(bcs_obj_type bcs_obj,
  56. X                           char *name,
  57. X                           fi_file_queue_entry parent)
  58. {
  59. X    fi_file_queue_entry new_file_queue_entry;
  60. X
  61. X    new_file_queue_entry =
  62. X    bcsi_safe_malloc(bcs_obj->whoami,
  63. X             sizeof(struct fi_file_queue_entry_rec));
  64. X    new_file_queue_entry->name = bcsi_safe_strdup(bcs_obj->whoami, name);
  65. X    if (parent)
  66. X    {
  67. X    char *lastcomp;
  68. X    
  69. X    if ((lastcomp = strrchr(name, PATH_SEP_CHAR)) == NULL)
  70. X        lastcomp = name;
  71. X    else
  72. X        lastcomp++;
  73. X    new_file_queue_entry->path_info =
  74. X        bcsi_path_info_from_parent(bcs_obj, lastcomp, parent->path_info);
  75. X    }
  76. X    else
  77. X    {
  78. X    new_file_queue_entry->path_info = bcsi_get_path_info(bcs_obj, name);
  79. X    }
  80. X
  81. X    return new_file_queue_entry;
  82. }
  83. X
  84. static void delete_fi_file_queue_entry(fi_file_queue_entry file_queue_entry)
  85. {
  86. X    if (file_queue_entry)
  87. X    {
  88. X    /* No need to free other fields since they are not copied here */
  89. X    if (file_queue_entry->name)
  90. X        free(file_queue_entry->name);
  91. X    free(file_queue_entry);
  92. X    }
  93. }
  94. X
  95. /*
  96. X * Constructor for bcs_file_info.
  97. X *
  98. X * This routine allocates a new file info structure and initializes
  99. X * all of its fields to some value.  When it is finished, it caches it
  100. X * in the table.  This routine may have side effects that cause other
  101. X * entries to but added to the table as well.
  102. X */
  103. static bcs_file_info new_bcs_file_info(bcs_obj_type bcs_obj,
  104. X                       char *filename,
  105. X                       path_cache path_info)
  106. {
  107. X    bcs_file_info file_info;
  108. X
  109. X    DPRINT((bcs_obj, BCS_DEBUG_TRACE | BCS_DEBUG_LOGIC,
  110. X        "ENTERING new_bcs_file_info(%s)", filename));
  111. X
  112. X    file_info = bcsi_safe_malloc(bcs_obj->whoami,
  113. X                 sizeof(struct bcs_file_info_rec));
  114. X
  115. X    /* Initialize all fields of file info to SOMETHING */
  116. X    file_info->path_info = path_info;
  117. X    file_info->user_path = bcsi_safe_strdup(bcs_obj->whoami, filename);
  118. X    file_info->clean_path = NULL;
  119. X    file_info->rel_path = NULL;
  120. X    file_info->cont_path = NULL;
  121. X    file_info->indx = FI_UNINITIALIZED;
  122. X    file_info->which = which_uninitialized;
  123. X    file_info->link_type = link_type_uninitialized;
  124. X    file_info->linkpath = NULL;
  125. X    file_info->important = FI_UNINITIALIZED;
  126. X    file_info->unimp_warn = FI_UNINITIALIZED;
  127. X    file_info->stage_params = stage_param_type_uninitialized;
  128. X    file_info->lists = NULL;
  129. X    file_info->staging.has_baseline_counterpart = FI_UNINITIALIZED;
  130. X    file_info->staging.bl_path = NULL;
  131. X    file_info->staging.bl_info = NULL;
  132. X    file_info->staging.is_staged = FI_UNINITIALIZED;
  133. X
  134. X    pc_insert_file_info(bcs_obj, path_info, file_info);
  135. X
  136. X    DPRINT((bcs_obj, BCS_DEBUG_TRACE, "LEAVING  new_bcs_file_info(%s)",
  137. X        filename));
  138. X
  139. X    return file_info;
  140. }
  141. X
  142. static bcs_file_info file_info_from_path_info(bcs_obj_type bcs_obj,
  143. X                          char *name,
  144. X                          path_cache path_info)
  145. {
  146. X    bcs_file_info file_info = NULL;
  147. X
  148. X    if (path_info != NULL)
  149. X    {
  150. X    file_info = pc_file_info(bcs_obj, path_info);
  151. X
  152. X    if (file_info == NULL)
  153. X    {
  154. X        if (name == NULL)
  155. X        name = pc_can_path(bcs_obj, path_info);
  156. X        file_info = new_bcs_file_info(bcs_obj, name, path_info);
  157. X    }
  158. X    }
  159. X
  160. X    return file_info;
  161. }
  162. X
  163. static void classify_baseline_file(bcs_obj_type bcs_obj,
  164. X                   bcs_file_info file_info)
  165. {
  166. X    char *lastcomp;
  167. X    int important = FALSE;
  168. X    stage_param_type stage_params = fi_normal;
  169. X    bcs_file_info parent_info = NULL;
  170. X
  171. X    lastcomp = pc_lastcomp(bcs_obj, file_info->path_info);
  172. X    parent_info =
  173. X    file_info_from_path_info(bcs_obj, NULL,
  174. X                 pc_parent(bcs_obj, file_info->path_info));
  175. X
  176. X    if (parent_info == NULL)
  177. X    {
  178. X    /*
  179. X     * This means that / is in the baseline.  Although this should
  180. X     * probably never really happen, handle the case anyway.
  181. X     */
  182. X    important = TRUE;
  183. X    stage_params = fi_normal;
  184. X    }
  185. X    else
  186. X    {
  187. X    bcs_stringlist *lists;
  188. X    lists = fi_lists(bcs_obj, parent_info);
  189. X    
  190. X    /*
  191. X     * First perform checks for special files whose importance
  192. X     * and stage parameters cannot be overridden.
  193. X     */
  194. X    
  195. X    /*
  196. X     * If this file is a file internally used by BCS, it is automatically
  197. X     * unimportant so that it doesn't show up in staging areas.
  198. X     * Don't check BL_PATH since it's not important a priori 
  199. X     * in the baseline...
  200. X     */
  201. X    if ((strcmp(lastcomp, IMPFILE) == 0) ||
  202. X        (strcmp(lastcomp, UNIMPFILE) == 0) ||
  203. X        (strcmp(lastcomp, AUTOSTAGE) == 0) ||
  204. X        (strcmp(lastcomp, NOSTAGE) == 0) ||
  205. X        (strcmp(lastcomp, NOWARN) == 0) ||
  206. X        (strcmp(fi_rel_path(bcs_obj, file_info), BL_CONF) == 0))
  207. X    {
  208. X        important = TRUE;
  209. X        stage_params = fi_no_mirror;
  210. X    }
  211. X    
  212. X    /* This file is important if it is needed by the CM system */
  213. X    else if (cm_is_precious(bcs_obj, lastcomp))
  214. X    {
  215. X        important = TRUE;
  216. X        stage_params = fi_no_stage;
  217. X    }
  218. X    
  219. X    /*
  220. X     * All of the above checks are for importances that cannot be
  221. X     * overridden.  Check the explicit lists no earlier or later
  222. X     * than here.  Check implist first since it overrides unimplist.
  223. X     */
  224. X    
  225. X    else
  226. X    {
  227. X        /* If all files in this directory are important, this one is. */
  228. X        if ((lists[implist]->n == 1) &&
  229. X        (strcmp(lists[implist]->data[0], ALL_IMPORTANT) == 0))
  230. X        important = TRUE;
  231. X        
  232. X        /* Check to see whether this file is explicitly important */
  233. X        else if (bcsi_in_stringlist(lastcomp, lists[implist]))
  234. X        important = TRUE;
  235. X        
  236. X        /* Check to see whether this file is explicitly unimportant */
  237. X        else if (bcsi_in_stringlist(lastcomp, lists[unimplist]))
  238. X        important = FALSE;
  239. X        
  240. X        /*
  241. X         * If this file is a link, resolve and test importance of what 
  242. X         * it is linked to
  243. X         */
  244. X        else if (pc_islink(bcs_obj, file_info->path_info))
  245. X        {
  246. X        bcs_file_info link_info;
  247. X        
  248. X        link_info = fi_ult_link_info(bcs_obj, file_info);
  249. X        if (link_info != NULL)
  250. X        {
  251. X            important = fi_important(bcs_obj, link_info);
  252. X        }
  253. X        }
  254. X        
  255. X        /* If this file is a directory, it is important */
  256. X        else if (pc_isdir(bcs_obj, file_info->path_info))
  257. X        important = TRUE;
  258. X        
  259. X        /* If this file has a log in the CM system it is important */
  260. X        else if (cm_haslog(bcs_obj, fi_clean_path(bcs_obj, file_info)))
  261. X        important = TRUE;
  262. X        
  263. X        /* Otherwise, this file is unimportant */
  264. X        else
  265. X        important = FALSE;
  266. X        
  267. X        /*
  268. X         * Determine stage params
  269. X         */
  270. X        
  271. X        if (pc_islink(bcs_obj, file_info->path_info))
  272. X        stage_params = fi_no_stage;
  273. X        else
  274. X        {
  275. X        if (bcsi_in_stringlist(lastcomp, lists[autostage]))
  276. X            stage_params = fi_auto_stage;
  277. X        else if (bcsi_in_stringlist(lastcomp, lists[nostage]))
  278. X            stage_params = fi_no_stage;
  279. X        else
  280. X            stage_params = fi_normal;
  281. X        }
  282. X    }
  283. X    }
  284. X
  285. X    file_info->important = important;
  286. X    file_info->stage_params = stage_params;
  287. }
  288. X
  289. /*
  290. X * PUBLIC ROUTINES
  291. X */
  292. X
  293. void bcsi_delete_file_info(bcs_file_info file_info)
  294. {
  295. X    if (file_info)
  296. X    {
  297. X    int i;
  298. X    
  299. X    /* Do not delete the path_cache structure.  It deletes us instead. */
  300. X    if (file_info->user_path)
  301. X        free(file_info->user_path);
  302. X    if (file_info->clean_path)
  303. X        free(file_info->clean_path);
  304. X    if (file_info->rel_path)
  305. X        free(file_info->rel_path);
  306. X    if (file_info->cont_path)
  307. X        free(file_info->cont_path);
  308. X    if (file_info->linkpath)
  309. X        free(file_info->linkpath);
  310. X    if (file_info->lists)
  311. X    {
  312. X        for (i = 0; i < NUM_LISTS; i++)
  313. X        fl_delete_flex_list((flex_list *) &(file_info->lists[i]),
  314. X                    free);
  315. X        free(file_info->lists);
  316. X    }
  317. X    
  318. X    if (file_info->which == in_staging)
  319. X        if (file_info->staging.bl_path)
  320. X        free(file_info->staging.bl_path);
  321. X    free(file_info);
  322. X    }
  323. }
  324. X
  325. /*
  326. X * Calculate the baseline path in the proper form for a file.
  327. X * This routine should only be called for files in a staging area.
  328. X *
  329. X * If the baseline prefix for the staging area is an absolute path,
  330. X * then the baseline path is simply the baseline prefix appended with
  331. X * the relative path to the file from the top of the staging area.
  332. X *
  333. X * If the baseline prefix is relative, then the baseline path
  334. X * is the baseline prefix prepended with the right number of "../"'s
  335. X * appended with the name of the path relative to the top of the
  336. X * staging area.  The number of "../"'s should be equal to the number
  337. X * of directory levels below the top of the staging area this file is.
  338. X */
  339. char *bcsi_calc_bl_path(bcs_obj_type bcs_obj, int indx, char *rel_path)
  340. {
  341. X    char *prefix;
  342. X    char bl_path[MAXPATHLEN];
  343. X
  344. X    prefix = bcs_obj->staging->data[indx]->bl_path;
  345. X    if (prefix[0] == PATH_SEP_CHAR)
  346. X    {
  347. X    /* Absolute prefix */
  348. X    bcsi_concat_paths(bl_path, prefix, rel_path);
  349. X    }
  350. X    else
  351. X    {
  352. X    bl_path[0] = '\0';
  353. X    if (strlen(rel_path))
  354. X    {
  355. X        char *p;
  356. X        
  357. X        /* Relative prefix */
  358. X        for (p = strchr(rel_path, PATH_SEP_CHAR);
  359. X         p; p = strchr(p + 1, PATH_SEP_CHAR))
  360. X        {
  361. X        strcat(bl_path, "..");
  362. X        strcat(bl_path, PATH_SEP_STR);
  363. X        }
  364. X    }
  365. X    else
  366. X    {
  367. X        bcsi_append_last_component
  368. X        (bl_path, bcs_obj->staging->data[indx]->path.user_path);
  369. X        strcat(bl_path, PATH_SEP_STR);
  370. X    }
  371. X    strcat(bl_path, prefix);
  372. X    if (strlen(rel_path))
  373. X    {
  374. X        strcat(bl_path, PATH_SEP_STR);
  375. X        strcat(bl_path, rel_path);
  376. X    }
  377. X    }
  378. X
  379. X    return (bcsi_safe_strdup(bcs_obj->whoami, bl_path));
  380. }
  381. X
  382. X
  383. /*
  384. X * Remove file info for this path if it exists.
  385. X */
  386. void bcsi_remove_file_info(bcs_obj_type bcs_obj, char *name)
  387. {
  388. X    path_cache path_info;
  389. X
  390. X    path_info = bcsi_get_path_info(bcs_obj, name);
  391. X    if (path_info)
  392. X    pc_remove_file_info(bcs_obj, path_info);
  393. }
  394. X
  395. /*
  396. X * This routine takes a directory name and adds its contents, possibly
  397. X * recursively, to the file information table.    If the `resultp'
  398. X * pointer is non-NULL, it returns a list of the file information
  399. X * structures sorted by filename.  This routine returns a standard BCS
  400. X * error code.
  401. X */
  402. int bcs_examine_dir(bcs_obj_type bcs_obj, char *dir,
  403. X            int recursive,
  404. X            bcs_ed_callback callback, void *cbdata)
  405. {
  406. X    fi_file_queue file_queue;
  407. X    fi_file_queue_entry queue_entry = NULL;
  408. X    int error = BCS_SUCCESS;
  409. X
  410. X    DPRINT((bcs_obj, BCS_DEBUG_TRACE, "ENTERING bcs_examine_dir(%s)", dir));
  411. X
  412. X    /*
  413. X     * Prepare for a tree traversal of the file system starting from
  414. X     * the directory passed in.  For each directory in the queue,
  415. X     * append all subdirectories to the queue if recursive is set.
  416. X     */
  417. X
  418. X    file_queue = (fi_file_queue) fl_new_flex_list(bcs_obj->whoami);
  419. X
  420. X    /*
  421. X     * Add passed in directory to queue as long as it is really a
  422. X     * directory.  Make sure we check specially for baseline
  423. X     * directories since they may really be symbolic links.
  424. X     */
  425. X    if (bcs_isbldir(bcs_obj, dir, NULL, NULL, NULL) || bcs_isdir(bcs_obj, dir))
  426. X    {
  427. X    queue_entry = new_fi_file_queue_entry(bcs_obj, dir, NULL);
  428. X    fl_add_to_tail(bcs_obj->whoami, (flex_list)file_queue, queue_entry);
  429. X    /*
  430. X     * Special case: If dir is really a link, replace its path_info
  431. X     * field with what it is linked to.  We know it is linked to a
  432. X     * directory or else bcs_isdir wouldn't have passed.
  433. X     */
  434. X    if (! pc_isdir(bcs_obj, queue_entry->path_info))
  435. X    {
  436. X        queue_entry->path_info =
  437. X        pc_ult_link_info(bcs_obj, queue_entry->path_info);
  438. X    }
  439. X    }
  440. X    else
  441. X    {
  442. X    error = BCS_ERR_USER;
  443. X    bcs_message(bcs_obj, stderr, "%s is not a directory", dir);
  444. X    }
  445. X    
  446. X    /* Traverse the file system depth first */
  447. X    if (! error)
  448. X    {
  449. X    int first = TRUE;
  450. X    bcs_which which;
  451. X    fi_file_queue_entry new_queue_entry;
  452. X    bcs_stringlist entries = NULL;
  453. X    int i;
  454. X    char cur_filename[MAXPATHLEN];
  455. X    char *p;
  456. X    bcs_file_info new_file_info;
  457. X
  458. X    pc_get_bl_index(bcs_obj, queue_entry->path_info, NULL, &which);
  459. X    while (file_queue->n > 0)
  460. X    {
  461. X        queue_entry = file_queue->data[file_queue->n - 1];
  462. X        new_file_info =
  463. X        file_info_from_path_info(bcs_obj, queue_entry->name,
  464. X                     queue_entry->path_info);
  465. X        /*
  466. X         * Do not call the callback for the actual directory passed in.
  467. X         * We only want to act on the contents of this directory.
  468. X         */
  469. X        if (! first)
  470. X        {
  471. X        if (new_file_info && callback)
  472. X            (*callback)(bcs_obj, new_file_info, cbdata);
  473. X        }
  474. X
  475. X        /* Remove this from the queue, but don't free it yet */
  476. X        fl_delete_range(bcs_obj->whoami, (flex_list) file_queue,
  477. X                file_queue->n - 1, file_queue->n - 1, NULL);
  478. X
  479. X        /*
  480. X         * Check this entry to see whether we should add its children
  481. X         * to the queue.  If this is our first time through or if
  482. X         * we are recursive and this is a directory, then we add
  483. X         * this entry's children to the queue as long as we are not
  484. X         * crossing baseline/staging area boundaries and this is not
  485. X         * a precious directory to the CM system.
  486. X         */
  487. X
  488. X        if (new_file_info &&
  489. X        (first || (recursive && fi_isdir(bcs_obj, new_file_info))) &&
  490. X        (! cm_is_precious(bcs_obj, queue_entry->name)) &&
  491. X        (fi_which(bcs_obj, new_file_info) == which))
  492. X        {
  493. X        error = bcsi_read_directory_entries(bcs_obj,
  494. X                            queue_entry->name,
  495. X                            &entries);
  496. X        if (! error)
  497. X        {
  498. X            strcpy(cur_filename, queue_entry->name);
  499. X            /*
  500. X             * Prepare to append each directory entry to the name
  501. X             * of the directory.  If the last character of the
  502. X             * path name is already the path separator, just append
  503. X             * as is.  If the last component of the path is ".",
  504. X             * overwrite.  Otherwise, append the path separator
  505. X             * and then append the entry name.
  506. X             */
  507. X            p = cur_filename + strlen(cur_filename);
  508. X            if (strlen(cur_filename) > 0)
  509. X            {
  510. X            if (*(p-1) != PATH_SEP_CHAR)
  511. X            {
  512. X                if ((strlen(cur_filename) >= 2) &&
  513. X                (*(p-2) == PATH_SEP_CHAR) &&
  514. X                (*(p-1) == '.'))
  515. X                {
  516. X                p--;
  517. X                }
  518. X                else
  519. X                {
  520. X                strcat(cur_filename, PATH_SEP_STR);
  521. X                p++;
  522. X                }
  523. X            }
  524. X            }
  525. X            /* Add entries in reverse so they'll be properly sorted */
  526. X            for (i = entries->n - 1; i >= 0; i--)
  527. X            {
  528. X            strcpy(p, entries->data[i]);
  529. X            new_queue_entry =
  530. X                new_fi_file_queue_entry(bcs_obj,
  531. X                            cur_filename,
  532. X                            queue_entry);
  533. X            fl_add_to_tail(bcs_obj->whoami,
  534. X                       (flex_list) file_queue,
  535. X                       new_queue_entry);
  536. X            }
  537. X            fl_delete_flex_list((flex_list *) &entries, free);
  538. X        }
  539. X        }
  540. X        delete_fi_file_queue_entry(queue_entry);
  541. X        first = FALSE;
  542. X    }  
  543. X    }
  544. X
  545. X    fl_delete_flex_list((flex_list *) &file_queue,
  546. X            (fl_free_fn_type)delete_fi_file_queue_entry);
  547. X
  548. X    DPRINT((bcs_obj, BCS_DEBUG_TRACE, "LEAVING bcs_examine_dir(%s)", dir));
  549. X    return error;
  550. }
  551. X
  552. /*
  553. X * Look up a file in the file information table.  If found, return
  554. X * resulting structure.  Otherwise, insert this file and all
  555. X * path components leading up to it if necessary.
  556. X */
  557. bcs_file_info bcs_get_file_info(bcs_obj_type bcs_obj, char *name)
  558. {
  559. X    bcs_file_info file_info = NULL;
  560. X    path_cache path_info = NULL;
  561. X
  562. X    DPRINT((bcs_obj, BCS_DEBUG_TRACE, "ENTERING bcs_get_file_info(%s)",
  563. X        name));
  564. X
  565. X    path_info = bcsi_get_path_info(bcs_obj, name);
  566. X    file_info = file_info_from_path_info(bcs_obj, name, path_info);
  567. X
  568. X    DPRINT((bcs_obj, BCS_DEBUG_TRACE, "LEAVING bcs_get_file_info(%s)",
  569. X        name));
  570. X    return file_info;
  571. }
  572. X
  573. void bcs_print_file_info(bcs_obj_type bcs_obj, bcs_file_info file_info)
  574. {
  575. X    int indx;
  576. X    bcs_which which;
  577. X    char *link_type_str;
  578. X    char *stage_param_str;
  579. X
  580. X    indx = fi_index(bcs_obj, file_info);
  581. X    which = fi_which(bcs_obj, file_info);
  582. X
  583. X    printf("%s%s:\n", fi_user_path(bcs_obj, file_info),
  584. X       (fi_isdir(bcs_obj, file_info) ? PATH_SEP_STR : ""));
  585. X    printf("  canonical path: %s\n", fi_can_path(bcs_obj, file_info));
  586. X    printf("  %s\n", (which == in_none) ? "not in baseline or staging area" :
  587. X       ((which == in_baseline) ? "in baseline" : "in staging area"));
  588. X    if (which == in_none)
  589. X    return;
  590. X    printf("  baseline or staging area index: %d\n", indx);
  591. X    printf("  %simportant\n", fi_important(bcs_obj, file_info) ? "" : "un");
  592. X    if (which == in_staging)
  593. X    {
  594. X    if (fi_has_baseline_counterpart(bcs_obj, file_info))
  595. X        printf("  %sstaged\n",
  596. X           fi_is_staged(bcs_obj, file_info) ? "" : "not ");
  597. X    else
  598. X        printf("  no baseline counterpart\n");
  599. X    }
  600. X
  601. X    switch(fi_link_type(bcs_obj, file_info))
  602. X    {
  603. X      case fi_not_link:
  604. X    link_type_str = "not a link";
  605. X    break;
  606. X      case fi_dangling:
  607. X    link_type_str = "dangling";
  608. X    break;
  609. X      case fi_to_baseline:
  610. X    link_type_str = "link to baseline counterpart";
  611. X    break;
  612. X      case fi_internal:
  613. X    link_type_str = "internal";
  614. X    break;
  615. X      case fi_external:
  616. X    link_type_str = "external";
  617. X    break;
  618. X      default:
  619. X    link_type_str = "unknown";
  620. X    break;
  621. X    }
  622. X    printf("  link type: %s\n", link_type_str);
  623. X
  624. X    if (which == in_baseline)
  625. X    {
  626. X    switch(fi_stage_params(bcs_obj, file_info))
  627. X    {
  628. X      case fi_normal:
  629. X        stage_param_str = "normal";
  630. X        break;
  631. X      case fi_auto_stage:
  632. X        stage_param_str = "automatically staged";
  633. X        break;
  634. X      case fi_no_stage:
  635. X        stage_param_str = "not stageable";
  636. X        break;
  637. X      case fi_no_mirror:
  638. X        stage_param_str = "not mirrored in staging area";
  639. X        break;
  640. X      default:
  641. X        stage_param_str = "unknown";
  642. X        break;
  643. X    }
  644. X    printf("  stage parameters: %s\n", stage_param_str);
  645. X    }
  646. }
  647. X
  648. char *fi_user_path(bcs_obj_type bcs_obj, bcs_file_info file_info)
  649. {
  650. X    return file_info->user_path;
  651. }
  652. X
  653. char *fi_clean_path(bcs_obj_type bcs_obj, bcs_file_info file_info)
  654. {
  655. X    if (file_info->clean_path == NULL)
  656. X    {
  657. X    int indx;
  658. X    bcs_which which;
  659. X    
  660. X    indx = fi_index(bcs_obj, file_info);
  661. X    which = fi_which(bcs_obj, file_info);
  662. X    if (which == in_none)
  663. X    {
  664. X        char *can_path;
  665. X        can_path = fi_can_path(bcs_obj, file_info);
  666. X        file_info->clean_path =
  667. X        bcsi_safe_strdup(bcs_obj->whoami, can_path);
  668. X    }
  669. X    else
  670. X    {
  671. X        char clean_path[MAXPATHLEN];
  672. X        char *cont_path;
  673. X        char *rel_path;
  674. X
  675. X        cont_path = fi_cont_path(bcs_obj, file_info);
  676. X        rel_path = fi_rel_path(bcs_obj, file_info);
  677. X        bcsi_concat_paths(clean_path, cont_path, rel_path);
  678. X        file_info->clean_path =
  679. X        bcsi_safe_strdup(bcs_obj->whoami, clean_path);
  680. X    }
  681. X    }    
  682. X
  683. X    return file_info->clean_path;
  684. }
  685. X
  686. char *fi_rel_path(bcs_obj_type bcs_obj, bcs_file_info file_info)
  687. {
  688. X    if (file_info->rel_path == NULL)
  689. X    {
  690. X    int indx;
  691. X    bcs_which which;
  692. X    char *can_path;
  693. X    char *rel_path;
  694. X    char *containing_path;
  695. X
  696. X    indx = fi_index(bcs_obj, file_info);
  697. X    which = fi_which(bcs_obj, file_info);
  698. X
  699. X    can_path = fi_can_path(bcs_obj, file_info);
  700. X    if (which == in_baseline)
  701. X    {
  702. X        containing_path =
  703. X        bcs_obj->baseline->data[indx]->path.can_path;
  704. X    }
  705. X    else if (which == in_staging)
  706. X    {
  707. X        containing_path =
  708. X        bcs_obj->staging->data[indx]->path.can_path;
  709. X    }
  710. X    else
  711. X    {
  712. X        bcs_message(bcs_obj, stderr,
  713. X            "INTERNAL ERROR: fi_rel_path called on "
  714. X            "path (%s) neither in baseline nor staging area.",
  715. X            fi_user_path(bcs_obj, file_info));
  716. X        abort();
  717. X    }
  718. X    rel_path = can_path + strlen(containing_path);
  719. X    if (*rel_path)
  720. X        rel_path++;
  721. X    file_info->rel_path = bcsi_safe_strdup(bcs_obj->whoami, rel_path);
  722. X    }
  723. X
  724. X    return file_info->rel_path;
  725. }
  726. X
  727. char *fi_cont_path(bcs_obj_type bcs_obj, bcs_file_info file_info)
  728. {
  729. X    if (file_info->cont_path == NULL)
  730. X    {
  731. X    int indx;
  732. X    bcs_which which;
  733. X    char *cont_path;
  734. X
  735. X    indx = fi_index(bcs_obj, file_info);
  736. X    which = fi_which(bcs_obj, file_info);
  737. X
  738. X    if (which == in_baseline)
  739. X    {
  740. X        cont_path =
  741. X        bcs_obj->baseline->data[indx]->path.user_path;
  742. X    }
  743. X    else if (which == in_staging)
  744. X    {
  745. X        cont_path =
  746. X        bcs_obj->staging->data[indx]->path.user_path;
  747. X    }
  748. X    else
  749. X    {
  750. X        bcs_message(bcs_obj, stderr,
  751. X            "INTERNAL ERROR: fi_cont_path called on "
  752. X            "path (%s) neither in baseline nor staging area.",
  753. X            fi_user_path(bcs_obj, file_info));
  754. X        abort();
  755. X    }
  756. X    file_info->cont_path = bcsi_safe_strdup(bcs_obj->whoami, cont_path);
  757. X    }
  758. X
  759. X    return file_info->cont_path;
  760. }
  761. X
  762. char *fi_can_path(bcs_obj_type bcs_obj, bcs_file_info file_info)
  763. {
  764. X    return pc_can_path(bcs_obj, file_info->path_info);
  765. }
  766. X
  767. int fi_index(bcs_obj_type bcs_obj, bcs_file_info file_info)
  768. {
  769. X    if (file_info->indx == FI_UNINITIALIZED)
  770. X    {
  771. X    /* Initialize both which and index */
  772. X    pc_get_bl_index(bcs_obj, file_info->path_info,
  773. X            &(file_info->indx),
  774. X            &(file_info->which));
  775. X    }
  776. X    return file_info->indx;
  777. }
  778. X
  779. bcs_which fi_which(bcs_obj_type bcs_obj, bcs_file_info file_info)
  780. {
  781. X    if (file_info->which == which_uninitialized)
  782. X    (void) fi_index(bcs_obj, file_info);
  783. X
  784. X    return file_info->which;
  785. }
  786. X
  787. bcs_link_type fi_link_type(bcs_obj_type bcs_obj, bcs_file_info file_info)
  788. {
  789. X    if (file_info->link_type == link_type_uninitialized)
  790. X    {
  791. X    file_info->link_type = fi_not_link;
  792. X    if (pc_islink(bcs_obj, file_info->path_info))
  793. X    {
  794. X        char *linkpath;
  795. X        int indx;
  796. X        bcs_which which;
  797. X
  798. X        linkpath = fi_linkpath(bcs_obj, file_info);
  799. X        indx = fi_index(bcs_obj, file_info);
  800. X        which = fi_which(bcs_obj, file_info);
  801. X
  802. X        if ((which == in_staging) &&
  803. X        (fi_has_baseline_counterpart(bcs_obj, file_info)) &&
  804. X        (strcmp(fi_bl_path(bcs_obj, file_info), linkpath) == 0))
  805. X        {
  806. X        file_info->link_type = fi_to_baseline;
  807. X        }
  808. X        else
  809. X        {
  810. X        /*
  811. X         * Follow links multiple levels to determine what link
  812. X         * type this is.  That way if a link goes through
  813. X         * multiple levels, the link type of this link
  814. X         * will be its ultimate destination.
  815. X         */
  816. X        bcs_file_info link_info;
  817. X        bcs_which lwhich;
  818. X        link_info = fi_ult_link_info(bcs_obj, file_info);
  819. X        
  820. X        if (link_info)
  821. X        {
  822. X            lwhich = fi_which(bcs_obj, link_info);
  823. X            if (which == lwhich)
  824. X            file_info->link_type = fi_internal;
  825. X            else
  826. X            file_info->link_type = fi_external;
  827. X        }
  828. X        else
  829. X            file_info->link_type = fi_dangling;
  830. X        }
  831. X    }
  832. X    else
  833. X        file_info->link_type = fi_not_link;
  834. X    }
  835. X
  836. X    return file_info->link_type;
  837. }
  838. X
  839. char *fi_linkpath(bcs_obj_type bcs_obj, bcs_file_info file_info)
  840. {
  841. X    if (file_info->linkpath == NULL)
  842. X    {
  843. X    file_info->linkpath =
  844. X        bcsi_safe_strdup(bcs_obj->whoami,
  845. X                 pc_linkpath(bcs_obj, file_info->path_info));
  846. X    }
  847. X
  848. X    return file_info->linkpath;
  849. }
  850. X
  851. bcs_file_info fi_ult_link_info(bcs_obj_type bcs_obj, bcs_file_info file_info)
  852. {
  853. X    bcs_file_info link_info = NULL;
  854. X    path_cache ult_path_info;
  855. X
  856. X    ult_path_info = pc_ult_link_info(bcs_obj, file_info->path_info);
  857. X    if (ult_path_info)
  858. X    {
  859. X    link_info = file_info_from_path_info(bcs_obj, NULL,
  860. X                         ult_path_info);
  861. X    }
  862. X    
  863. X    return link_info;
  864. }
  865. X
  866. int fi_important(bcs_obj_type bcs_obj, bcs_file_info file_info)
  867. {
  868. X    if (file_info->important == FI_UNINITIALIZED)
  869. X    {
  870. X    int indx;
  871. X    bcs_which which;
  872. X    struct stat *statbuf;
  873. X
  874. X    file_info->important = FALSE;
  875. X    indx = fi_index(bcs_obj, file_info);
  876. X    which = fi_which(bcs_obj, file_info);
  877. X    statbuf = pc_statbuf(bcs_obj, file_info->path_info);
  878. X
  879. X    if (which == in_staging)
  880. X    {
  881. X        /*
  882. X         * Initialize non-pointer members staging structure as well
  883. X         * as important
  884. X         */
  885. X        file_info->staging.has_baseline_counterpart = FALSE;
  886. X        file_info->staging.is_staged = FALSE;
  887. X
  888. X        if (strcmp(fi_rel_path(bcs_obj, file_info), BL_PATH) == 0)
  889. X        {
  890. X        file_info->staging.has_baseline_counterpart = FALSE;
  891. X        file_info->important = TRUE;
  892. X        }
  893. X        else
  894. X        {
  895. X        bcs_file_info bl_file_info;
  896. X
  897. X        bl_file_info = fi_bl_info(bcs_obj, file_info);
  898. X        if (bl_file_info)
  899. X        {
  900. X            file_info->staging.has_baseline_counterpart = TRUE;
  901. X            if (fi_stage_params(bcs_obj, bl_file_info) == fi_no_mirror)
  902. X            file_info->important = FALSE;
  903. X            else
  904. X            file_info->important =
  905. X                fi_important(bcs_obj, bl_file_info);
  906. X            if (file_info->important)
  907. X            {
  908. X            if (fi_link_type(bcs_obj, bl_file_info) == fi_not_link)
  909. X                file_info->staging.is_staged =
  910. X                (! pc_islink(bcs_obj, file_info->path_info));
  911. X            }
  912. X            else
  913. X            /* Never consider unimportant files staged */
  914. X            file_info->staging.is_staged = FALSE;
  915. X        }
  916. X        else
  917. X        {
  918. X            file_info->staging.has_baseline_counterpart = FALSE;
  919. X            file_info->important = FALSE;
  920. X        }
  921. X        }
  922. X        DPRINT((bcs_obj, BCS_DEBUG_LOGIC,
  923. X            "fi_important: has_baseline_counterpart = %d, "
  924. X            "staged = %d",
  925. X            file_info->staging.has_baseline_counterpart,
  926. X            file_info->staging.is_staged));
  927. X    }
  928. X    else if (which == in_baseline)
  929. X    {
  930. X        classify_baseline_file(bcs_obj, file_info);
  931. X    }
  932. X
  933. X    DPRINT((bcs_obj, BCS_DEBUG_LOGIC,
  934. X        "fi_important(%s): important = %d",
  935. X        fi_user_path(bcs_obj, file_info), file_info->important));
  936. X    }
  937. X
  938. X    return file_info->important;
  939. }
  940. X
  941. int fi_unimp_warn(bcs_obj_type bcs_obj, bcs_file_info file_info)
  942. {
  943. X    if (file_info->unimp_warn == FI_UNINITIALIZED)
  944. X    {
  945. X    char nowarn_file[MAXPATHLEN];
  946. X    int indx;
  947. X
  948. X    file_info->unimp_warn = FALSE;
  949. X    indx = fi_index(bcs_obj, file_info);
  950. X
  951. X    /*
  952. X     * Check to see whether this is an unimportant file that a warning
  953. X     * should be issued about.  This would be the case if this file
  954. X     * is a directory or has a special suffix and if the NOWARN file
  955. X     * doesn't exist in its directory in the baseline.
  956. X     */
  957. X    if (! fi_important(bcs_obj, file_info))
  958. X    {
  959. X        char *p;
  960. X
  961. X        bcsi_concat_paths
  962. X        (nowarn_file,
  963. X         bcs_obj->baseline->data[indx]->path.user_path,
  964. X         fi_rel_path(bcs_obj, file_info));
  965. X        if ((p = strrchr(nowarn_file, PATH_SEP_CHAR)) != NULL)
  966. X        *p = '\0';
  967. X        else
  968. X        nowarn_file[0] = '\0';
  969. X        bcsi_concat_paths(nowarn_file, nowarn_file, NOWARN);
  970. X
  971. X        if (! bcsi_exists(bcs_obj, nowarn_file))
  972. X        {
  973. X        /*
  974. X         * Set warning flag if this file ends with a specified
  975. X         * suffix or is a directory
  976. X         */
  977. X        if (fi_isdir(bcs_obj, file_info))
  978. X            file_info->unimp_warn = TRUE;
  979. X        else
  980. X        {
  981. X            bcs_stringlist unimp_warn_suffixes;
  982. X            char *cur_suffix;
  983. X            int name_len;
  984. X            int suf_len;
  985. X            int i;
  986. X            char *filename;
  987. X
  988. X            filename = fi_can_path(bcs_obj, file_info);
  989. X            name_len = strlen(filename);
  990. X            unimp_warn_suffixes =
  991. X            bcs_obj->baseline->data[indx]->
  992. X                unimp_warn_suffixes;
  993. X            for (i = 0; i < unimp_warn_suffixes->n; i++)
  994. X            {
  995. X            cur_suffix = unimp_warn_suffixes->data[i];
  996. X            suf_len = strlen(cur_suffix);
  997. X            if ((name_len >= suf_len) &&
  998. X                (strcmp(&filename[name_len - suf_len],
  999. X                    cur_suffix) == 0))
  1000. X            {
  1001. X                file_info->unimp_warn = TRUE;
  1002. X            }
  1003. X            }
  1004. X        }
  1005. X        }
  1006. X    }
  1007. X    }
  1008. X
  1009. X    return file_info->unimp_warn;
  1010. }
  1011. X
  1012. stage_param_type fi_stage_params(bcs_obj_type bcs_obj, bcs_file_info file_info)
  1013. {
  1014. X    if (fi_which(bcs_obj, file_info) != in_baseline)
  1015. X    return fi_no_mirror;
  1016. X
  1017. X    if (file_info->stage_params == stage_param_type_uninitialized)
  1018. X    {
  1019. X    (void) fi_important(bcs_obj, file_info);
  1020. X    }
  1021. X    
  1022. X    return file_info->stage_params;
  1023. }
  1024. X
  1025. bcs_stringlist *fi_lists(bcs_obj_type bcs_obj, bcs_file_info file_info)
  1026. {
  1027. X    if (! fi_isdir(bcs_obj, file_info))
  1028. X    {
  1029. X    bcs_message(bcs_obj, stderr,
  1030. X            "INTERNAL ERROR: fi_lists called on file (%s) "
  1031. X            "that is not a directory.",
  1032. X            fi_user_path(bcs_obj, file_info));
  1033. X    abort();
  1034. X    }
  1035. X
  1036. X    if (file_info->lists == NULL)
  1037. X    {
  1038. X    char tmppath[MAXPATHLEN];
  1039. X    char *p;
  1040. X    bcs_stringlist *lists;
  1041. X    
  1042. X    lists = bcsi_safe_malloc(bcs_obj->whoami,
  1043. X                 NUM_LISTS * sizeof(bcs_stringlist));
  1044. X    
  1045. X    strcpy(tmppath, fi_can_path(bcs_obj, file_info));
  1046. X    strcat(tmppath, PATH_SEP_STR);
  1047. X    p = tmppath + strlen(tmppath);
  1048. X    
  1049. X    strcpy(p, IMPFILE);
  1050. X    lists[implist] = bcsi_file_to_stringlist(bcs_obj, tmppath);
  1051. X    
  1052. X    strcpy(p, UNIMPFILE);
  1053. X    lists[unimplist] = bcsi_file_to_stringlist(bcs_obj, tmppath);
  1054. X    
  1055. X    strcpy(p, AUTOSTAGE);
  1056. X    lists[autostage] = bcsi_file_to_stringlist(bcs_obj, tmppath);    
  1057. X    
  1058. X    strcpy(p, NOSTAGE);
  1059. X    lists[nostage] = bcsi_file_to_stringlist(bcs_obj, tmppath);    
  1060. X    
  1061. X    file_info->lists = lists;
  1062. X    }
  1063. X
  1064. X    return file_info->lists;
  1065. }
  1066. X
  1067. int fi_has_baseline_counterpart(bcs_obj_type bcs_obj, bcs_file_info file_info)
  1068. {
  1069. X    if (fi_which(bcs_obj, file_info) != in_staging)
  1070. X    return FALSE;
  1071. X
  1072. X    if (file_info->staging.has_baseline_counterpart == FI_UNINITIALIZED)
  1073. X    {
  1074. X    (void) fi_important(bcs_obj, file_info);
  1075. X    }
  1076. X    
  1077. X    return file_info->staging.has_baseline_counterpart;
  1078. }
  1079. X
  1080. char *fi_bl_path(bcs_obj_type bcs_obj, bcs_file_info file_info)
  1081. {
  1082. X    if (fi_which(bcs_obj, file_info) != in_staging)
  1083. X    {
  1084. X    bcs_message(bcs_obj, stderr,
  1085. X            "INTERNAL ERROR: fi_bl_path called on file (%s) "
  1086. X            "not in staging area.",
  1087. X            fi_user_path(bcs_obj, file_info));
  1088. X    abort();
  1089. X    }
  1090. X
  1091. X    if (file_info->staging.bl_path == NULL)
  1092. X    {
  1093. X    int indx;
  1094. X    char *rel_path;
  1095. X
  1096. X    indx = fi_index(bcs_obj, file_info);
  1097. X    rel_path = fi_rel_path(bcs_obj, file_info);
  1098. X
  1099. X    file_info->staging.bl_path =
  1100. X        bcsi_calc_bl_path(bcs_obj, indx, rel_path);
  1101. X    }
  1102. X    return file_info->staging.bl_path;
  1103. }
  1104. X
  1105. bcs_file_info fi_bl_info(bcs_obj_type bcs_obj, bcs_file_info file_info)
  1106. {
  1107. X    if (fi_which(bcs_obj, file_info) != in_staging)
  1108. X    {
  1109. X    bcs_message(bcs_obj, stderr,
  1110. X            "INTERNAL ERROR: fi_bl_info called on file (%s) "
  1111. X            "not in staging area.",
  1112. X            fi_user_path(bcs_obj, file_info));
  1113. X    abort();
  1114. X    }
  1115. X
  1116. X    if (file_info->staging.bl_info == NULL)
  1117. X    {
  1118. X    char *bl_path;
  1119. X    char tmppath[MAXPATHLEN];
  1120. X    bcs_file_info bl_file_info;
  1121. X
  1122. X    bl_path = fi_bl_path(bcs_obj, file_info);
  1123. X    if (bl_path[0] == PATH_SEP_CHAR)
  1124. X        strcpy(tmppath, bl_path);
  1125. X    else
  1126. X        bcsi_resolve_readlink(tmppath, bl_path,
  1127. X                  fi_can_path(bcs_obj, file_info));
  1128. X    
  1129. X    DPRINT((bcs_obj, BCS_DEBUG_LOGIC,
  1130. X        "new_file_info: baseline_path = %s = %s",
  1131. X        bl_path, tmppath));
  1132. X    bl_file_info = bcs_get_file_info(bcs_obj, tmppath);
  1133. X
  1134. X    /*
  1135. X     * Don't count this if the counterpart is not really in the
  1136. X     * baseline.  This could happen if you have staging areas
  1137. X     * under the baseline and don't put them in UNIMPFILE.
  1138. X     */
  1139. X    if (bl_file_info && (fi_which(bcs_obj, bl_file_info) != in_baseline))
  1140. X        bl_file_info = NULL;
  1141. X    
  1142. X    file_info->staging.bl_info = bl_file_info;
  1143. X    }
  1144. X
  1145. X    return file_info->staging.bl_info;
  1146. }
  1147. X
  1148. int fi_is_staged(bcs_obj_type bcs_obj, bcs_file_info file_info)
  1149. {
  1150. X    if (fi_which(bcs_obj, file_info) != in_staging)
  1151. X    return FALSE;
  1152. X
  1153. X    if (file_info->staging.is_staged == FI_UNINITIALIZED)
  1154. X    {
  1155. X    (void) fi_important(bcs_obj, file_info);
  1156. X    }
  1157. X    
  1158. X    return file_info->staging.is_staged;
  1159. }
  1160. X
  1161. int fi_writable(bcs_obj_type bcs_obj, bcs_file_info file_info)
  1162. {
  1163. X    return ((pc_statbuf(bcs_obj, file_info->path_info)->st_mode & S_IWUSR)
  1164. X        ? TRUE : FALSE);
  1165. }
  1166. X
  1167. int fi_isdir(bcs_obj_type bcs_obj, bcs_file_info file_info)
  1168. {
  1169. X    return pc_isdir(bcs_obj, file_info->path_info);
  1170. }
  1171. SHAR_EOF
  1172. echo 'File bcs-2.0/lib/file_info.c is complete' &&
  1173. chmod 0444 bcs-2.0/lib/file_info.c ||
  1174. echo 'restore of bcs-2.0/lib/file_info.c failed'
  1175. Wc_c="`wc -c < 'bcs-2.0/lib/file_info.c'`"
  1176. test 30386 -eq "$Wc_c" ||
  1177.     echo 'bcs-2.0/lib/file_info.c: original size 30386, current size' "$Wc_c"
  1178. rm -f _shar_wnt_.tmp
  1179. fi
  1180. # ============= bcs-2.0/lib/file_info.h ==============
  1181. if test -f 'bcs-2.0/lib/file_info.h' -a X"$1" != X"-c"; then
  1182.     echo 'x - skipping bcs-2.0/lib/file_info.h (File already exists)'
  1183.     rm -f _shar_wnt_.tmp
  1184. else
  1185. > _shar_wnt_.tmp
  1186. echo 'x - extracting bcs-2.0/lib/file_info.h (Text)'
  1187. sed 's/^X//' << 'SHAR_EOF' > 'bcs-2.0/lib/file_info.h' &&
  1188. /* 
  1189. X * $Id: file_info.h,v 1.7 1994/03/07 21:47:41 qjb Exp $
  1190. X * $Source: /local/tmp/bcs-2.0/lib/RCS/file_info.h,v $
  1191. X * $Author: qjb $
  1192. X *
  1193. X * Copyright (C) 1994  E. Jay Berkenbilt
  1194. X * 
  1195. X * This file is part of BCS.  BCS may be distributed according to the terms
  1196. X * of the General Public License and/or the Artistic License.  See the
  1197. X * `COPYING' and `Artistic' files with the source distribution for details.
  1198. X * This notice must be kept intact when this file is distributed.
  1199. X *
  1200. X * This file defines data structures private to file_info.c
  1201. X */
  1202. X
  1203. #ifndef __FILE_INFO_H__
  1204. #define __FILE_INFO_H__
  1205. X
  1206. #if !defined(lint) && !defined(CODECENTER) || defined(RCS_HDRS)
  1207. /* Define a static function and call it.  No warnings this way. */
  1208. static void rcsid_file_info_h(char *s)
  1209. {rcsid_file_info_h("@(#)$Id: file_info.h,v 1.7 1994/03/07 21:47:41 qjb Exp $");}
  1210. #endif /* !lint && !CODECENTER || RCS_HDRS */
  1211. X
  1212. #define FI_UNINITIALIZED -1
  1213. X
  1214. typedef struct fi_file_queue_entry_rec {
  1215. X    char *name;
  1216. X    path_cache path_info;
  1217. } *fi_file_queue_entry;
  1218. X
  1219. FL_DEFINE(fi_file_queue_rec, fi_file_queue, fi_file_queue_entry);
  1220. X
  1221. typedef struct fi_link_info_rec {
  1222. X    char *linkpath;        /* where this link immediately points */
  1223. X    char *ult_linkpath;        /* where this link eventually points */
  1224. } *fi_link_info;
  1225. X
  1226. struct bcs_file_info_rec {
  1227. X    path_cache path_info;    /* path cache entry containing us */
  1228. X    char *user_path;        /* filename relative to how user specified */
  1229. X    char *clean_path;           /* pathname to file with respect to bl/st dir */
  1230. X    char *cont_path;        /* user path of containing bl/staging dir */
  1231. X    char *rel_path;        /* path relative to top of bl/staging dir */
  1232. X    int indx;            /* which baseline/staging area this is in */
  1233. X    bcs_which which;        /* baseline or staging area */
  1234. X    bcs_link_type link_type;
  1235. X    char *linkpath;        /* valid only if link_type != fi_not_link */
  1236. X    int important;
  1237. X    int unimp_warn;           /* warn if unimportant and has special suffix */
  1238. X    stage_param_type stage_params; /* valid only if in baseline */
  1239. X    bcs_stringlist *lists;    /* important, unimportant, etc. lists */
  1240. X    struct {
  1241. X    int has_baseline_counterpart;
  1242. X    char *bl_path;        /* path to baseline counterpart */
  1243. X    struct bcs_file_info_rec *bl_info; /* fi record for bl counterpart */
  1244. X    int is_staged;        /* whether file is staged */
  1245. X    } staging;            /* valid only if in staging area */
  1246. };
  1247. X
  1248. /* For various per-directory configuration files */
  1249. enum { implist, unimplist, autostage, nostage };
  1250. #define NUM_LISTS (nostage + 1)
  1251. X
  1252. #endif /* __FILE_INFO_H__ */
  1253. SHAR_EOF
  1254. chmod 0444 bcs-2.0/lib/file_info.h ||
  1255. echo 'restore of bcs-2.0/lib/file_info.h failed'
  1256. Wc_c="`wc -c < 'bcs-2.0/lib/file_info.h'`"
  1257. test 2509 -eq "$Wc_c" ||
  1258.     echo 'bcs-2.0/lib/file_info.h: original size 2509, current size' "$Wc_c"
  1259. rm -f _shar_wnt_.tmp
  1260. fi
  1261. # ============= bcs-2.0/lib/find_cmd ==============
  1262. if test -f 'bcs-2.0/lib/find_cmd' -a X"$1" != X"-c"; then
  1263.     echo 'x - skipping bcs-2.0/lib/find_cmd (File already exists)'
  1264.     rm -f _shar_wnt_.tmp
  1265. else
  1266. > _shar_wnt_.tmp
  1267. echo 'x - extracting bcs-2.0/lib/find_cmd (Text)'
  1268. sed 's/^X//' << 'SHAR_EOF' > 'bcs-2.0/lib/find_cmd' &&
  1269. #!/bin/sh
  1270. #
  1271. # $Id: find_cmd,v 1.1 1993/08/24 04:18:16 qjb Exp $
  1272. # $Source: /local/tmp/bcs-2.0/lib/RCS/find_cmd,v $
  1273. # $Author: qjb $
  1274. #
  1275. # Find first occurence command in the path
  1276. #
  1277. X
  1278. whoami=`basename $0`
  1279. if test $# -ne 1; then
  1280. X  echo "Usage: $whoami command" 1>&2
  1281. X  exit 1
  1282. fi
  1283. X
  1284. cmd=$1
  1285. X
  1286. IFS=:
  1287. for dir in $PATH; do
  1288. X  if test "$dir" != "" -a "$dir" != "."; then
  1289. X    if test -f $dir/$cmd; then
  1290. X      echo $dir/$cmd
  1291. X      exit 0
  1292. X    fi
  1293. X  fi
  1294. done
  1295. X
  1296. Xexit 0
  1297. SHAR_EOF
  1298. chmod 0444 bcs-2.0/lib/find_cmd ||
  1299. echo 'restore of bcs-2.0/lib/find_cmd failed'
  1300. Wc_c="`wc -c < 'bcs-2.0/lib/find_cmd'`"
  1301. test 445 -eq "$Wc_c" ||
  1302.     echo 'bcs-2.0/lib/find_cmd: original size 445, current size' "$Wc_c"
  1303. rm -f _shar_wnt_.tmp
  1304. fi
  1305. # ============= bcs-2.0/lib/flexlist.c ==============
  1306. if test -f 'bcs-2.0/lib/flexlist.c' -a X"$1" != X"-c"; then
  1307.     echo 'x - skipping bcs-2.0/lib/flexlist.c (File already exists)'
  1308.     rm -f _shar_wnt_.tmp
  1309. else
  1310. > _shar_wnt_.tmp
  1311. echo 'x - extracting bcs-2.0/lib/flexlist.c (Text)'
  1312. sed 's/^X//' << 'SHAR_EOF' > 'bcs-2.0/lib/flexlist.c' &&
  1313. /* 
  1314. X * $Id: flexlist.c,v 1.11 1994/03/07 21:47:41 qjb Exp $
  1315. X * $Source: /local/tmp/bcs-2.0/lib/RCS/flexlist.c,v $
  1316. X * $Author: qjb $
  1317. X *
  1318. X * Copyright (C) 1994  E. Jay Berkenbilt
  1319. X * 
  1320. X * This file is part of BCS.  BCS may be distributed according to the terms
  1321. X * of the General Public License and/or the Artistic License.  See the
  1322. X * `COPYING' and `Artistic' files with the source distribution for details.
  1323. X * This notice must be kept intact when this file is distributed.
  1324. X *
  1325. X * This file provides an implementation of dynamic arrays with efficient
  1326. X * insert and lookup but inefficient delete.
  1327. X */
  1328. X
  1329. #if !defined(lint) && !defined(CODECENTER) || defined(RCS_HDRS)
  1330. /* Define a static function and call it.  No warnings this way. */
  1331. static void rcsid(char *s)
  1332. {rcsid("@(#)$Id: flexlist.c,v 1.11 1994/03/07 21:47:41 qjb Exp $");}
  1333. #endif /* !lint && !CODECENTER || RCS_HDRS */
  1334. X
  1335. #include "bcs_p.h"
  1336. X
  1337. flex_list fl_new_flex_list(char *whoami)
  1338. {
  1339. X    int i;
  1340. X    flex_list list;
  1341. X    
  1342. X    list = bcsi_safe_malloc(whoami, sizeof(struct flex_list_rec));
  1343. X
  1344. X    list->max = FLEX_MAX_INIT;
  1345. X    list->n = 0;
  1346. X    list->data = bcsi_safe_malloc(whoami, FLEX_MAX_INIT * sizeof(fl_pointer));
  1347. X
  1348. X    for (i = 0; i < FLEX_MAX_INIT; i++)
  1349. X    list->data[i] = NULL;
  1350. X
  1351. X    return list;
  1352. }
  1353. X
  1354. void fl_delete_flex_list(flex_list *list, fl_free_fn_type free_fn)
  1355. {
  1356. X    if (*list)
  1357. X    {
  1358. X    if (free_fn)
  1359. X    {
  1360. X        int i;
  1361. X        for (i = 0; i < (*list)->n; i++)
  1362. X        if ((*list)->data[i])
  1363. X        {
  1364. X            (*free_fn)((*list)->data[i]);
  1365. X            (*list)->data[i] = NULL;
  1366. X        }
  1367. X    }
  1368. X    if ((*list)->data)
  1369. X        free((*list)->data);
  1370. X    free (*list);
  1371. X    *list = NULL;
  1372. X    }
  1373. }
  1374. X
  1375. void fl_add_to_tail (char *whoami, flex_list list, fl_pointer data)
  1376. {
  1377. X    fl_insert(whoami, list, list->n, data);
  1378. }
  1379. X
  1380. void fl_delete_range(char *whoami, flex_list list, int start, int end,
  1381. X             fl_free_fn_type free_fn)
  1382. {
  1383. X    int i;
  1384. X    int num_items;
  1385. X
  1386. X    num_items = end - start + 1;
  1387. X
  1388. X    for (i = start; i <= end; i++)
  1389. X    if (list->data[i])
  1390. X    {
  1391. X        if (free_fn)
  1392. X        (*free_fn)(list->data[i]);
  1393. X        list->data[i] = NULL;
  1394. X    }
  1395. X    
  1396. X    for (i = end + 1; i < list->n; i++)
  1397. X    list->data[i - num_items] = list->data[i];
  1398. X    list->n -= num_items;
  1399. }
  1400. X
  1401. void fl_insert(char *whoami, flex_list list, int indx, fl_pointer data)
  1402. {
  1403. X    fl_pointer *newdata;
  1404. X    int i;
  1405. X
  1406. X    if (list->n + 1 > list->max)
  1407. X    {
  1408. X    newdata = bcsi_safe_malloc(whoami, list->max * 2 * sizeof(fl_pointer));
  1409. X    for (i = 0; i < list->max; i++)
  1410. X        newdata[i] = list->data[i];
  1411. X    for (i = list->max; i < 2 * list->max; i++)
  1412. X        newdata[i] = NULL;
  1413. X    free(list->data);
  1414. X    list->data = newdata;
  1415. X    list->max *= 2;
  1416. X    }
  1417. X
  1418. X    for (i = list->n; i > indx; i--)
  1419. X    list->data[i] = list->data[i - 1];
  1420. X
  1421. X    list->data[indx] = data;
  1422. X    list->n++;
  1423. }
  1424. SHAR_EOF
  1425. chmod 0444 bcs-2.0/lib/flexlist.c ||
  1426. echo 'restore of bcs-2.0/lib/flexlist.c failed'
  1427. Wc_c="`wc -c < 'bcs-2.0/lib/flexlist.c'`"
  1428. test 2676 -eq "$Wc_c" ||
  1429.     echo 'bcs-2.0/lib/flexlist.c: original size 2676, current size' "$Wc_c"
  1430. rm -f _shar_wnt_.tmp
  1431. fi
  1432. # ============= bcs-2.0/lib/init.c ==============
  1433. if test -f 'bcs-2.0/lib/init.c' -a X"$1" != X"-c"; then
  1434.     echo 'x - skipping bcs-2.0/lib/init.c (File already exists)'
  1435.     rm -f _shar_wnt_.tmp
  1436. else
  1437. > _shar_wnt_.tmp
  1438. echo 'x - extracting bcs-2.0/lib/init.c (Text)'
  1439. sed 's/^X//' << 'SHAR_EOF' > 'bcs-2.0/lib/init.c' &&
  1440. /* 
  1441. X * $Id: init.c,v 1.36 1994/03/07 21:47:41 qjb Exp $
  1442. X * $Source: /local/tmp/bcs-2.0/lib/RCS/init.c,v $
  1443. X * $Author: qjb $
  1444. X *
  1445. X * Copyright (C) 1994  E. Jay Berkenbilt
  1446. X * 
  1447. X * This file is part of BCS.  BCS may be distributed according to the terms
  1448. X * of the General Public License and/or the Artistic License.  See the
  1449. X * `COPYING' and `Artistic' files with the source distribution for details.
  1450. X * This notice must be kept intact when this file is distributed.
  1451. X *
  1452. X * This file handles BCS startup operations.
  1453. X */
  1454. X
  1455. #if !defined(lint) && !defined(CODECENTER) || defined(RCS_HDRS)
  1456. /* Define a static function and call it.  No warnings this way. */
  1457. static void rcsid(char *s)
  1458. {rcsid("@(#)$Id: init.c,v 1.36 1994/03/07 21:47:41 qjb Exp $");}
  1459. #endif /* !lint && !CODECENTER || RCS_HDRS */
  1460. X
  1461. #include "bcs_p.h"
  1462. #include "version.h"
  1463. #include "builddate.h"
  1464. X
  1465. #define BL_CONF_COMMENT '#'
  1466. #define BL_CONF_SEPARATOR ':'
  1467. X
  1468. /**
  1469. X ** PRIVATE ROUTINES
  1470. X **/
  1471. X
  1472. /*
  1473. X * "Constructor" for bcs_obj
  1474. X */
  1475. static bcs_obj_type new_bcs_obj(char *whoami)
  1476. {
  1477. X    bcs_obj_type obj;
  1478. X
  1479. X    obj = bcsi_safe_malloc(whoami, sizeof(struct bcs_obj_rec));
  1480. X
  1481. X    obj->whoami = whoami;    /* just use memory from argv[0] */
  1482. #ifdef DEBUG
  1483. X    obj->debug_flags = 0;
  1484. #endif
  1485. X    obj->baseline = NULL;
  1486. X    obj->staging = NULL;
  1487. X    obj->recursive = FALSE;
  1488. X    obj->no_action = FALSE;
  1489. X
  1490. X    return obj;
  1491. }
  1492. X
  1493. X
  1494. /*
  1495. X * This routine checks to see whether cmd_option was specified on the
  1496. X * commandline or, if not, whether the environment variable in env_var
  1497. X * is set.  If required is TRUE, it requires one of these to be set.
  1498. X * If neither case occurs, an error status is returned
  1499. X * (BCS_ERR_USAGE).  Otherwise, result points to the value.
  1500. X */
  1501. static int get_env_flag(bcs_obj_type bcs_obj,
  1502. X            char *env_var, char *cmd_option,
  1503. X            int argc, char *argv[],
  1504. X            int required, char **result)
  1505. {
  1506. X    int i;
  1507. X    /* Search for the commandline option */
  1508. X
  1509. X    for (i = 1; i < argc; i++)
  1510. X    {
  1511. X    if (argv[i] && (strcmp(argv[i], cmd_option) == 0))
  1512. X    {
  1513. X        if (i + 1 >= argc)
  1514. X        {
  1515. X        bcs_message(bcs_obj, stderr,
  1516. X                "the %s option requires an argument.", cmd_option);
  1517. X        return BCS_ERR_USAGE;
  1518. X        }
  1519. X        else
  1520. X        {
  1521. X        argv[i] = NULL;
  1522. X        *result = argv[i + 1];
  1523. X        argv[i + 1] = NULL;
  1524. X        return BCS_SUCCESS;
  1525. X        }
  1526. X    }
  1527. X    }
  1528. X
  1529. X    /* If not found, search for the environment variable */
  1530. X    if ((*result = getenv(env_var)) == NULL)
  1531. X    {
  1532. X    if (required)
  1533. X    {
  1534. X        bcs_message(bcs_obj, stderr,
  1535. X            "either the %s option must be specified or the "
  1536. X            "%s environment variable must be set.",
  1537. X            cmd_option, env_var);
  1538. X        return BCS_ERR_USAGE;
  1539. X    }
  1540. X    else
  1541. X    {
  1542. X        *result = NULL;
  1543. X    }
  1544. X    }
  1545. X
  1546. X    return BCS_SUCCESS;
  1547. }
  1548. X
  1549. #ifdef DEBUG
  1550. static int find_dstring(char *dstring, char *keyword)
  1551. {
  1552. X    char *p;
  1553. X    int found = FALSE;
  1554. X
  1555. X    if ((p = strstr(dstring, keyword)) != NULL)
  1556. X    {
  1557. X    /*
  1558. X     * This is it if the the keyword starts at the beginning
  1559. X     * of the string or after a colon and ends at the end
  1560. X     * of the string or before a colon.
  1561. X     */
  1562. X    found = (((p == dstring) || (*(p-1) == ':')) &&
  1563. X         ((*(p + strlen(keyword)) == '\0') ||
  1564. X          (*(p + strlen(keyword)) == ':')));
  1565. X    }
  1566. X
  1567. X    return found;
  1568. }
  1569. #endif /* DEBUG */
  1570. X
  1571. static int parse_dflags(bcs_obj_type bcs_obj, int argc, char *argv[])
  1572. {
  1573. X    int status = BCS_SUCCESS;
  1574. X    char *result;
  1575. X
  1576. X    status = get_env_flag(bcs_obj, DEBUG_ENV, "--debug", argc, argv,
  1577. X              FALSE, &result);
  1578. X    if ((status == BCS_SUCCESS) && result)
  1579. X    {
  1580. #ifdef DEBUG
  1581. X    bcs_obj->debug_flags = 0;
  1582. X    if (find_dstring(result, "all"))
  1583. X        bcs_obj->debug_flags = -1;
  1584. X    else
  1585. X    {
  1586. X        if (find_dstring(result, "logic"))
  1587. X        bcs_obj->debug_flags |= BCS_DEBUG_LOGIC;
  1588. X        if (find_dstring(result, "trace"))
  1589. X        bcs_obj->debug_flags |= BCS_DEBUG_TRACE;
  1590. X        if (find_dstring(result, "verbose"))
  1591. X        bcs_obj->debug_flags |= BCS_DEBUG_VERBOSE;
  1592. X        if (find_dstring(result, "path"))
  1593. X        bcs_obj->debug_flags |= BCS_DEBUG_PATH;
  1594. X    }
  1595. #else
  1596. X    bcs_message(bcs_obj, stderr,
  1597. X            "%s is set or --debug is specified on the commandline, "
  1598. X            "but DEBUG was not defined at compile time.",
  1599. X            DEBUG_ENV);
  1600. X    status = BCS_ERR_USAGE;
  1601. #endif /* DEBUG */
  1602. X    }
  1603. X
  1604. X    return status;
  1605. }
  1606. X
  1607. static bcs_stringlist parse_colon_string(bcs_obj_type bcs_obj, char *str)
  1608. {
  1609. X    char *workstring;
  1610. X    bcs_stringlist list;
  1611. X    char *start, *end;
  1612. X    int done = FALSE;
  1613. X
  1614. X    workstring = bcsi_safe_strdup(bcs_obj->whoami, str);
  1615. X    list = (bcs_stringlist)fl_new_flex_list(bcs_obj->whoami);
  1616. X
  1617. X    start = workstring;
  1618. X
  1619. X    do {
  1620. X    if ((end = strchr(start, ':')) == NULL)
  1621. X    {
  1622. X        end = start + strlen(start);
  1623. X        done = TRUE;
  1624. X    }
  1625. X    else
  1626. X    {
  1627. X        *end = '\0';
  1628. X    }
  1629. X
  1630. X    fl_add_to_tail(bcs_obj->whoami, (flex_list)list,
  1631. X               bcsi_safe_strdup(bcs_obj->whoami, start));
  1632. X    start = end + 1;
  1633. X    } while (! done);
  1634. X
  1635. X    free (workstring);
  1636. X    return list;
  1637. }
  1638. X
  1639. static int parse_colon_path(bcs_obj_type bcs_obj, int argc, char *argv[],
  1640. X                char *env_var, char *cmd_opt,
  1641. X                bcs_stringlist *list)
  1642. {
  1643. X    int status = BCS_SUCCESS;
  1644. X    char *result;
  1645. X    int i;
  1646. X
  1647. X    status = get_env_flag(bcs_obj, env_var, cmd_opt, argc, argv,
  1648. X              TRUE, &result);
  1649. X    if (status == BCS_SUCCESS)
  1650. X    {
  1651. X    (*list) = parse_colon_string(bcs_obj, result);
  1652. X
  1653. X    DPRINT((bcs_obj, BCS_DEBUG_LOGIC, "%s:", env_var));
  1654. X    for (i = 0; i < (*list)->n; i++)
  1655. X    {
  1656. X        DPRINT((bcs_obj, BCS_DEBUG_LOGIC, "   %s",
  1657. X            (char *)(*list)->data[i]));
  1658. X    }
  1659. X    }
  1660. X
  1661. X    return status;
  1662. }
  1663. X
  1664. static int get_baseline(bcs_obj_type bcs_obj, int argc, char *argv[],
  1665. X            bcs_stringlist *list)
  1666. {
  1667. X    return parse_colon_path(bcs_obj, argc, argv, BASELINE_ENV,
  1668. X                "--baseline", list);
  1669. }
  1670. X
  1671. static int get_staging(bcs_obj_type bcs_obj, int argc, char *argv[],
  1672. X            bcs_stringlist *list)
  1673. {
  1674. X    return parse_colon_path(bcs_obj, argc, argv, STAGING_ENV,
  1675. X                "--staging", list);
  1676. }
  1677. X
  1678. X
  1679. static void init_path_info(bcs_obj_type bcs_obj,
  1680. X               char *pathname, bcs_path_info *path)
  1681. {
  1682. X    path_cache path_info;
  1683. X    char tmppath[MAXPATHLEN];
  1684. X    struct stat *statbuf;
  1685. X
  1686. X    /*
  1687. X     * For baseline and staging area directories, a special case
  1688. X     * of allowing the directory to be a symbolic link is implemented.
  1689. X     * The canonical path of the baseline or staging area directories
  1690. X     * is the real directory.
  1691. X     */
  1692. X
  1693. X    strcpy(tmppath, pathname);
  1694. X    if (strlen(tmppath))
  1695. X    {
  1696. X    strcat(tmppath, PATH_SEP_STR);
  1697. X    strcat(tmppath, ".");
  1698. X    }
  1699. X    path->user_path = pathname;
  1700. X    path_info = bcsi_get_path_info(bcs_obj, tmppath);
  1701. X    if (path_info == NULL)
  1702. X    {
  1703. X    bcs_message(bcs_obj, stderr,
  1704. X            "baseline or staging area directory %s does not exist",
  1705. X            pathname);
  1706. X    exit (BCS_ERR_SYSTEM);
  1707. X    }
  1708. X    path->can_path =
  1709. X    bcsi_safe_strdup(bcs_obj->whoami, pc_can_path(bcs_obj, path_info));
  1710. X    statbuf = pc_statbuf(bcs_obj, path_info);
  1711. X    path->ino = statbuf->st_ino;
  1712. X    path->dev = statbuf->st_dev;
  1713. }
  1714. X
  1715. static bcs_baseline_info new_baseline_info(bcs_obj_type bcs_obj, char *path)
  1716. {
  1717. X    bcs_baseline_info bi;
  1718. X
  1719. X    bi = bcsi_safe_malloc(bcs_obj->whoami,
  1720. X              sizeof(struct bcs_baseline_info_rec));
  1721. X    init_path_info(bcs_obj, path, &bi->path);
  1722. X    bi->cm_name = NULL;
  1723. X    bi->secure = FALSE;
  1724. X    bi->unimp_warn_suffixes = (bcs_stringlist)fl_new_flex_list(bcs_obj->whoami);
  1725. X
  1726. X    return bi;
  1727. }
  1728. X
  1729. bcs_staging_info new_staging_info(bcs_obj_type bcs_obj, char *path)
  1730. {
  1731. X    bcs_staging_info si;
  1732. X
  1733. X    si = bcsi_safe_malloc(bcs_obj->whoami,
  1734. X              sizeof(struct bcs_staging_info_rec));
  1735. X    init_path_info(bcs_obj, path, &si->path);
  1736. X    si->bl_path = NULL;
  1737. X
  1738. X    return si;
  1739. }
  1740. X
  1741. int check_for_file(bcs_obj_type bcs_obj, bcs_stringlist paths, char *file)
  1742. {
  1743. X    int error = FALSE;
  1744. X    char tmppath[MAXPATHLEN];
  1745. X    int i;
  1746. X    
  1747. X    /* Make sure each component is a directory */
  1748. X    for (i = 0; i < paths->n; i++)
  1749. X    {
  1750. X    strcpy(tmppath, paths->data[i]);
  1751. X    if (strlen(tmppath))
  1752. X    {
  1753. X        strcat(tmppath, PATH_SEP_STR);
  1754. X        strcat(tmppath, ".");
  1755. X    }
  1756. X    
  1757. X    if (bcs_isdir(bcs_obj, paths->data[i]) ||
  1758. X        bcs_isdir(bcs_obj, tmppath))
  1759. X    {
  1760. X        strcpy(tmppath, paths->data[i]);
  1761. X        strcat(tmppath, PATH_SEP_STR);
  1762. X        strcat(tmppath, file);
  1763. X        if (! bcsi_readable(bcs_obj, tmppath))
  1764. X        {
  1765. X        error = TRUE;
  1766. X        bcs_message(bcs_obj, stderr,
  1767. X                "%s does not exist or is not readable.", tmppath);
  1768. X        }
  1769. X    }
  1770. X    else
  1771. X    {
  1772. X        error = TRUE;
  1773. X        bcs_message(bcs_obj, stderr, "%s is not a directory.",
  1774. X            paths->data[i]);
  1775. X    }
  1776. X    }
  1777. X
  1778. X    return error;
  1779. }
  1780. X
  1781. /*
  1782. X * Read the baseline prefix file in the given directory.  This routine
  1783. X * exits if it fails for any reason.  Checks should be performed in advance
  1784. X * to make sure the file exists and is readable.
  1785. X */
  1786. char *read_bl_path(bcs_obj_type bcs_obj, char *path)
  1787. {
  1788. X    char tmppath[MAXPATHLEN];
  1789. X    FILE *prefix;
  1790. X    char result[MAXPATHLEN];
  1791. X    
  1792. X    strcpy(tmppath, path);
  1793. X    strcat(tmppath, PATH_SEP_STR);
  1794. X    strcat(tmppath, BL_PATH);
  1795. X
  1796. X    if ((prefix = fopen(tmppath, "r")) == NULL)
  1797. X    {
  1798. X    bcs_message(bcs_obj, stderr, "can't open %s for reading; exiting.",
  1799. X            tmppath);
  1800. X    exit(BCS_ERR_SYSTEM);
  1801. X    }
  1802. X
  1803. X    mem_zero(result, sizeof(result));
  1804. X    if (fgets(result, sizeof(result) - 1, prefix) == NULL)
  1805. X    {
  1806. X    bcs_message(bcs_obj, stderr, "failure reading %s; exiting",
  1807. X            path);
  1808. X    exit(BCS_ERR_SYSTEM);
  1809. X    }
  1810. X
  1811. X    fclose(prefix);
  1812. X
  1813. X    /* Strip off newline if any */
  1814. X    if ((strlen(result) > 0) && (result[strlen(result) - 1] == '\n'))
  1815. X    result[strlen(result) - 1] = '\0';
  1816. X
  1817. X    return bcsi_safe_strdup(bcs_obj->whoami, result);
  1818. }
  1819. X
  1820. /*
  1821. X * Read baseline conf files.  File should have already been shown to exist
  1822. X * and be readable before this routine is called.
  1823. X */
  1824. static int parse_bl_conf(bcs_obj_type bcs_obj, bcs_baseline_info bl_info)
  1825. {
  1826. X    FILE *bl;
  1827. X    char filename[MAXPATHLEN];
  1828. X    char line[BUFSIZ + 1];
  1829. X    char *p;
  1830. X    char *key, *value;
  1831. X    int lineno;
  1832. X    int error = FALSE;
  1833. X
  1834. X    strcpy(filename, bl_info->path.user_path);
  1835. X    strcat(filename, PATH_SEP_STR);
  1836. X    strcat(filename, BL_CONF);
  1837. X
  1838. X    if ((bl = fopen(filename, "r")) == NULL)
  1839. X    {
  1840. X    bcs_message(bcs_obj, stderr,
  1841. X            "parse_bl_conf called but %s cannot be opened for "
  1842. X            "reading", filename);
  1843. X    exit(BCS_ERR_INTERNAL);
  1844. X    }
  1845. X
  1846. X    DPRINT((bcs_obj, BCS_DEBUG_VERBOSE, "reading %s...", filename));
  1847. X
  1848. X    /*
  1849. X     * Read file a line at a time separating key from value.
  1850. X     * Each line is of the format key [ : value ]
  1851. X     * Spacing is not important.  If no value is present, it is taken
  1852. X     * to be a null string.
  1853. X     */
  1854. X    lineno = 0;
  1855. X    mem_zero(line, sizeof(line));
  1856. X    while ((fgets(line, sizeof(line) - 1, bl)) != NULL)
  1857. SHAR_EOF
  1858. true || echo 'restore of bcs-2.0/lib/init.c failed'
  1859. fi
  1860. echo 'End of bcs-2.0 part 2'
  1861. echo 'File bcs-2.0/lib/init.c is continued in part 3'
  1862. echo 3 > _shar_seq_.tmp
  1863. exit 0
  1864.