home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume27 / aegis-2.1 / part09 < prev    next >
Encoding:
Text File  |  1993-09-24  |  154.8 KB  |  6,081 lines

  1. Newsgroups: comp.sources.unix
  2. From: pmiller@bmr.gov.au (Peter Miller)
  3. Subject: v27i044: aegis - project change supervisor (V2.1), Part09/19
  4. References: <1.748951883.12788@gw.home.vix.com>
  5. Sender: unix-sources-moderator@gw.home.vix.com
  6. Approved: vixie@gw.home.vix.com
  7.  
  8. Submitted-By: pmiller@bmr.gov.au (Peter Miller)
  9. Posting-Number: Volume 27, Issue 44
  10. Archive-Name: aegis-2.1/part09
  11.  
  12. #! /bin/sh
  13. # This is a shell archive.  Remove anything before this line, then unpack
  14. # it by saving it into a file and typing "sh file".  To overwrite existing
  15. # files, type "sh file -c".  You can also feed this as standard input via
  16. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  17. # will see the following message at the end:
  18. #        "End of archive 9 (of 19)."
  19. # Contents:  aegis/aecpu.c aegis/aedb.c aegis/aenc.c aegis/aenf.c
  20. #   aegis/aenfu.c aegis/aerf.c aegis/aerm.c aegis/aermu.c aegis/lock.c
  21. #   aux/CHANGES.1.1 doc/c6.0.so
  22. # Wrapped by vixie@gw.home.vix.com on Sat Sep 25 03:00:41 1993
  23. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  24. if test -f 'aegis/aecpu.c' -a "${1}" != "-c" ; then 
  25.   echo shar: Will not clobber existing file \"'aegis/aecpu.c'\"
  26. else
  27. echo shar: Extracting \"'aegis/aecpu.c'\" \(13200 characters\)
  28. sed "s/^X//" >'aegis/aecpu.c' <<'END_OF_FILE'
  29. X/*
  30. X *    aegis - project change supervisor
  31. X *    Copyright (C) 1991, 1992, 1993 Peter Miller.
  32. X *    All rights reserved.
  33. X *
  34. X *    This program is free software; you can redistribute it and/or modify
  35. X *    it under the terms of the GNU General Public License as published by
  36. X *    the Free Software Foundation; either version 2 of the License, or
  37. X *    (at your option) any later version.
  38. X *
  39. X *    This program is distributed in the hope that it will be useful,
  40. X *    but WITHOUT ANY WARRANTY; without even the implied warranty of
  41. X *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  42. X *    GNU General Public License for more details.
  43. X *
  44. X *    You should have received a copy of the GNU General Public License
  45. X *    along with this program; if not, write to the Free Software
  46. X *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  47. X *
  48. X * MANIFEST: copy files into a change, and undo
  49. X */
  50. X
  51. X#include <stdio.h>
  52. X#include <stdlib.h>
  53. X#include <unistd.h>
  54. X
  55. X#include <aecpu.h>
  56. X#include <ael.h>
  57. X#include <arglex2.h>
  58. X#include <commit.h>
  59. X#include <change.h>
  60. X#include <error.h>
  61. X#include <file.h>
  62. X#include <help.h>
  63. X#include <lock.h>
  64. X#include <log.h>
  65. X#include <option.h>
  66. X#include <os.h>
  67. X#include <project.h>
  68. X#include <trace.h>
  69. X#include <undo.h>
  70. X#include <user.h>
  71. X#include <word.h>
  72. X
  73. X
  74. Xstatic void copy_file_undo_usage _((void));
  75. X
  76. Xstatic void
  77. Xcopy_file_undo_usage()
  78. X{
  79. X    char        *progname;
  80. X
  81. X    progname = option_progname_get();
  82. X    fprintf(stderr, "usage: %s -CoPy_file_Undo [ <option>... ] <filename>...\n", progname);
  83. X    fprintf(stderr, "       %s -CoPy_file_Undo -List [ <option>... ]\n", progname);
  84. X    fprintf(stderr, "       %s -CoPy_file_Undo -Help\n", progname);
  85. X    quit(1);
  86. X}
  87. X
  88. X
  89. Xstatic void copy_file_undo_help _((void));
  90. X
  91. Xstatic void
  92. Xcopy_file_undo_help()
  93. X{
  94. X    static char *text[] =
  95. X    {
  96. X"NAME",
  97. X"    %s -CoPy_file_Undo - reverse action of aecp",
  98. X"",
  99. X"SYNOPSIS",
  100. X"    %s -CoPy_file_Undo [ <option>... ] <filename>...",
  101. X"    %s -CoPy_file_Undo -List [ <option>... ]",
  102. X"    %s -CoPy_file_Undo -Help",
  103. X"",
  104. X"DESCRIPTION",
  105. X"    The %s -CoPy_file_Undo command is used to remove a",
  106. X"    file previously copied into a change.",
  107. X"",
  108. X"    The %s program will attempt to intuit the file names",
  109. X"    intended.  All file names are stored within %s as",
  110. X"    relative to the root of the baseline directory tree.  The",
  111. X"    development directory and the integration directory are",
  112. X"    shadows of the baseline directory, and so these relative",
  113. X"    names aply there, too.    Files named on the command line",
  114. X"    are first converted to absolute paths if necessary.  They",
  115. X"    are then compared with the baseline path, and the",
  116. X"    development directory path, and the integration directory",
  117. X"    path, to determine a root-relative name.  It is an error",
  118. X"    if the file named is outside one of these directory",
  119. X"    trees.",
  120. X"",
  121. X"    The named files will be removed from the list of files in",
  122. X"    the change.  The file is deleted from the development",
  123. X"    directory unless the -Keep option is specified.  The -",
  124. X"    Keep option should be used with great care, as you can",
  125. X"    confuse tools such as make(1) by leaving these files in",
  126. X"    place.",
  127. X"",
  128. X"    This command will cancel any build or test registrations,",
  129. X"    because deleting a file logically invalidates them.  If the",
  130. X"    config file was deleted, any diff registration will also be",
  131. X"    cancelled.",
  132. X"",
  133. X"OPTIONS",
  134. X"    The following options are understood:",
  135. X"",
  136. X"    -Change <number>",
  137. X"        This option may be used to specify a particular",
  138. X"        change within a project.  When no -Change option is",
  139. X"        specified, the AEGIS_CHANGE environment variable is",
  140. X"        consulted.  If that does not exist, the user's",
  141. X"        $HOME/.aegisrc file is examined for a default change",
  142. X"        field (see aeuconf(5) for more information).  If",
  143. X"        that does not exist, when the user is only working",
  144. X"        on one change within a project, that is the default",
  145. X"        change number.  Otherwise, it is an error.",
  146. X"",
  147. X"    -Help",
  148. X"        This option may be used to obtain more",
  149. X"        information about how to use the %s program.",
  150. X"",
  151. X"    -List",
  152. X"        This option may be used to obtain a list of",
  153. X"        suitable subjects for this command.  The list may",
  154. X"        be more general than expected.",
  155. X"",
  156. X"    -Project <name>",
  157. X"        This option may be used to select the project of",
  158. X"        interest.  When no -Project option is specified, the",
  159. X"        AEGIS_PROJECT environment variable is consulted.  If",
  160. X"        that does not exist, the user's $HOME/.aegisrc file",
  161. X"        is examined for a default project field (see",
  162. X"        aeuconf(5) for more information).  If that does not",
  163. X"        exist, when the user is only working on changes",
  164. X"        within a single project, the project name defaults",
  165. X"        to that project.  Otherwise, it is an error.",
  166. X"",
  167. X"    -TERse",
  168. X"        This option may be used to cause listings to",
  169. X"        produce the bare minimum of information.  It is",
  170. X"        usually useful for shell scripts.",
  171. X"",
  172. X"    -Verbose",
  173. X"        This option may be used to cause %s to produce",
  174. X"        more output.  By default %s only produces",
  175. X"        output on errors.  When used with the -List",
  176. X"        option this option causes column headings to be",
  177. X"        added.",
  178. X"",
  179. X"    All options may be abbreviated; the abbreviation is",
  180. X"    documented as the upper case letters, all lower case",
  181. X"    letters and underscores (_) are optional.  You must use",
  182. X"    consecutive sequences of optional letters.",
  183. X"",
  184. X"    All options are case insensitive, you may type them in",
  185. X"    upper case or lower case or a combination of both, case",
  186. X"    is not important.",
  187. X"",
  188. X"    For example: the arguments \"-project, \"-PROJ\" and \"-p\"",
  189. X"    are all interpreted to mean the -Project option.  The",
  190. X"    argument \"-prj\" will not be understood, because",
  191. X"    consecutive optional characters were not supplied.",
  192. X"",
  193. X"    Options and other command line arguments may be mixed",
  194. X"    arbitrarily on the command line, after the function",
  195. X"    selectors.",
  196. X"",
  197. X"    The GNU long option names are understood.  Since all",
  198. X"    option names for aegis are long, this means ignoring the",
  199. X"    extra leading '-'.  The \"--option=value\" convention is",
  200. X"    also understood.",
  201. X"",
  202. X"RECOMMENDED ALIAS",
  203. X"    The recommended alias for this command is",
  204. X"    csh%%    alias aecpu '%s -cpu \\!* -v'",
  205. X"    sh$    aecpu(){%s -cpu $* -v}",
  206. X"",
  207. X"ERRORS",
  208. X"    It is an error if the change is not in the",
  209. X"    'being_developed' state.",
  210. X"    It is an error if the change is not assigned to the",
  211. X"    current user.",
  212. X"",
  213. X"EXIT STATUS",
  214. X"    The %s command will exit with a status of 1 on any",
  215. X"    error.    The %s command will only exit with a status of",
  216. X"    0 if there are no errors.",
  217. X"",
  218. X"COPYRIGHT",
  219. X"    %C",
  220. X"",
  221. X"AUTHOR",
  222. X"    %A",
  223. X    };
  224. X
  225. X    help(text, SIZEOF(text), copy_file_undo_usage);
  226. X}
  227. X
  228. X
  229. Xstatic void copy_file_undo_list _((void));
  230. X
  231. Xstatic void
  232. Xcopy_file_undo_list()
  233. X{
  234. X    string_ty    *project_name;
  235. X    long        change_number;
  236. X
  237. X    trace(("copy_file_undo_list()\n{\n"/*}*/));
  238. X    arglex();
  239. X    project_name = 0;
  240. X    change_number = 0;
  241. X    while (arglex_token != arglex_token_eoln)
  242. X    {
  243. X        switch (arglex_token)
  244. X        {
  245. X        default:
  246. X            generic_argument(copy_file_undo_usage);
  247. X            continue;
  248. X
  249. X        case arglex_token_change:
  250. X            if (arglex() != arglex_token_number)
  251. X                copy_file_undo_usage();
  252. X            /* fall through... */
  253. X
  254. X        case arglex_token_number:
  255. X            if (change_number)
  256. X                fatal("duplicate -Change option");
  257. X            change_number = arglex_value.alv_number;
  258. X            if (change_number < 1)
  259. X                fatal("change %ld out of range", change_number);
  260. X            break;
  261. X
  262. X        case arglex_token_project:
  263. X            if (arglex() != arglex_token_string)
  264. X                copy_file_undo_usage();
  265. X            if (project_name)
  266. X                fatal("duplicate -Project option");
  267. X            project_name = str_from_c(arglex_value.alv_string);
  268. X            break;
  269. X        }
  270. X        arglex();
  271. X    }
  272. X    list_change_files(project_name, change_number);
  273. X    if (project_name)
  274. X        str_free(project_name);
  275. X    trace((/*{*/"}\n"));
  276. X}
  277. X
  278. X
  279. Xstatic void copy_file_undo_main _((void));
  280. X
  281. Xstatic void
  282. Xcopy_file_undo_main()
  283. X{
  284. X    wlist        wl;
  285. X    cstate        cstate_data;
  286. X    pstate        pstate_data;
  287. X    int        j;
  288. X    string_ty    *s1;
  289. X    string_ty    *s2;
  290. X    int        keep;
  291. X    pconf        pconf_data;
  292. X    string_ty    *project_name;
  293. X    project_ty    *pp;
  294. X    long        change_number;
  295. X    change_ty    *cp;
  296. X    int        nolog;
  297. X    user_ty        *up;
  298. X    int        config_seen;
  299. X    string_ty    *config_name;
  300. X
  301. X    trace(("copy_file_undo_main()\n{\n"/*}*/));
  302. X    wl_zero(&wl);
  303. X    project_name = 0;
  304. X    change_number = 0;
  305. X    keep = 0;
  306. X    nolog = 0;
  307. X    while (arglex_token != arglex_token_eoln)
  308. X    {
  309. X        switch (arglex_token)
  310. X        {
  311. X        default:
  312. X            generic_argument(copy_file_undo_usage);
  313. X            continue;
  314. X
  315. X        case arglex_token_string:
  316. X            s1 = str_from_c(arglex_value.alv_string);
  317. X            os_become_orig();
  318. X            s2 = os_pathname(s1, 1);
  319. X            os_become_undo();
  320. X            str_free(s1);
  321. X            if (wl_member(&wl, s2))
  322. X                fatal("file \"%s\" named more than once", arglex_value.alv_string);
  323. X            wl_append(&wl, s2);
  324. X            str_free(s2);
  325. X            break;
  326. X
  327. X        case arglex_token_keep:
  328. X            if (keep)
  329. X            {
  330. X                duplicate:
  331. X                fatal("duplicate %s option", arglex_value.alv_string);
  332. X            }
  333. X            keep = 1;
  334. X            break;
  335. X
  336. X        case arglex_token_change:
  337. X            if (arglex() != arglex_token_number)
  338. X                copy_file_undo_usage();
  339. X            /* fall through... */
  340. X
  341. X        case arglex_token_number:
  342. X            if (change_number)
  343. X                fatal("duplicate -Change option");
  344. X            change_number = arglex_value.alv_number;
  345. X            if (change_number < 1)
  346. X                fatal("change %ld out of range", change_number);
  347. X            break;
  348. X
  349. X        case arglex_token_project:
  350. X            if (arglex() != arglex_token_string)
  351. X                copy_file_undo_usage();
  352. X            if (project_name)
  353. X                fatal("duplicate -Project option");
  354. X            project_name = str_from_c(arglex_value.alv_string);
  355. X            break;
  356. X
  357. X        case arglex_token_nolog:
  358. X            if (nolog)
  359. X                goto duplicate;
  360. X            nolog = 1;
  361. X            break;
  362. X        }
  363. X        arglex();
  364. X    }
  365. X    if (!wl.wl_nwords)
  366. X        fatal("no files named");
  367. X
  368. X    /*
  369. X     * locate project data
  370. X     */
  371. X    if (!project_name)
  372. X        project_name = user_default_project();
  373. X    pp = project_alloc(project_name);
  374. X    str_free(project_name);
  375. X    project_bind_existing(pp);
  376. X
  377. X    /*
  378. X     * locate user data
  379. X     */
  380. X    up = user_executing(pp);
  381. X
  382. X    /*
  383. X     * locate change data
  384. X     */
  385. X    if (!change_number)
  386. X        change_number = user_default_change(up);
  387. X    cp = change_alloc(pp, change_number);
  388. X    change_bind_existing(cp);
  389. X
  390. X    /*
  391. X     * lock the change file
  392. X     */
  393. X    change_cstate_lock_prepare(cp);
  394. X    lock_take();
  395. X    cstate_data = change_cstate_get(cp);
  396. X    pstate_data = project_pstate_get(pp);
  397. X    pconf_data = change_pconf_get(cp);
  398. X
  399. X    /*
  400. X     * It is an error if the change is not in the in_development state.
  401. X     * It is an error if the change is not assigned to the current user.
  402. X     */
  403. X    if (cstate_data->state != cstate_state_being_developed)
  404. X        change_fatal(cp, "not in 'being_developed' state");
  405. X    if (!str_equal(change_developer_name(cp), user_name(up)))
  406. X    {
  407. X        change_fatal
  408. X        (
  409. X            cp,
  410. X            "user \"%S\" is not the developer",
  411. X            user_name(up)
  412. X        );
  413. X    }
  414. X
  415. X    /*
  416. X     * resolve the path of each file
  417. X     * 1.    the absolute path of the file name is obtained
  418. X     * 2.    if the file is inside the development directory, ok
  419. X     * 3.    if the file is inside the baseline, ok
  420. X     * 4.    if neither, error
  421. X     */
  422. X    config_seen = 0;
  423. X    config_name = str_from_c(THE_CONFIG_FILE);
  424. X    for (j = 0; j < wl.wl_nwords; ++j)
  425. X    {
  426. X        s1 = wl.wl_word[j];
  427. X        assert(s1->str_text[0] == '/');
  428. X        s2 = os_below_dir(change_development_directory_get(cp, 1), s1);
  429. X        if (!s2)
  430. X            s2 = os_below_dir(project_baseline_path_get(pp, 1), s1);
  431. X        if (!s2)
  432. X            change_fatal(cp, "path \"%S\" unrelated", s1);
  433. X        str_free(s1);
  434. X        wl.wl_word[j] = s2;
  435. X        if (str_equal(s2, config_name))
  436. X            config_seen++;
  437. X    }
  438. X    str_free(config_name);
  439. X
  440. X    /*
  441. X     * ensure that each file
  442. X     * 1. is already part of the change
  443. X     * 2. is being modified by this change
  444. X     */
  445. X    for (j = 0; j < wl.wl_nwords; ++j)
  446. X    {
  447. X        cstate_src    src_data;
  448. X
  449. X        s1 = wl.wl_word[j];
  450. X        src_data = change_src_find(cp, s1);
  451. X        if (!src_data)
  452. X            change_fatal(cp, "file \"%S\" not in change", s1);
  453. X        if (src_data->action != file_action_modify)
  454. X            change_fatal(cp, "file \"%S\" is not -CoPy_file", s1);
  455. X        if (config_seen)
  456. X            src_data->diff_time = 0;
  457. X    }
  458. X
  459. X    /*
  460. X     * Remove each file from the development directory,
  461. X     * if it still exists.
  462. X     * Remove the difference file, too.
  463. X     */
  464. X    if (!keep)
  465. X    {
  466. X        string_ty    *dd;
  467. X
  468. X        dd = change_development_directory_get(cp, 1);
  469. X        user_become(up);
  470. X        for (j = 0; j < wl.wl_nwords; ++j)
  471. X        {
  472. X            s1 = wl.wl_word[j];
  473. X            s2 = str_format("%S/%S", dd, s1);
  474. X            if (os_exists(s2))
  475. X                commit_unlink_errok(s2);
  476. X            str_free(s2);
  477. X
  478. X            s2 = str_format("%S/%S,D", dd, s1);
  479. X            if (os_exists(s2))
  480. X                commit_unlink_errok(s2);
  481. X            str_free(s2);
  482. X        }
  483. X        user_become_undo();
  484. X    }
  485. X
  486. X    /*
  487. X     * Remove each file to the change file,
  488. X     * and write it back out.
  489. X     */
  490. X    for (j = 0; j < wl.wl_nwords; ++j)
  491. X        change_src_remove(cp, wl.wl_word[j]);
  492. X
  493. X    /*
  494. X     * the number of files changed, or the version did,
  495. X     * so stomp on the validation fields.
  496. X     */
  497. X    cstate_data->build_time = 0;
  498. X    cstate_data->test_time = 0;
  499. X    cstate_data->test_baseline_time = 0;
  500. X    cstate_data->regression_test_time = 0;
  501. X
  502. X    /*
  503. X     * release the locks
  504. X     */
  505. X    change_cstate_write(cp);
  506. X    commit();
  507. X    lock_release();
  508. X
  509. X    /*
  510. X     * verbose success message
  511. X     */
  512. X    for (j = 0; j < wl.wl_nwords; ++j)
  513. X        change_verbose(cp, "file \"%S\" copy file undo", wl.wl_word[j]);
  514. X
  515. X    /*
  516. X     * run the change file command
  517. X     */
  518. X    if (!nolog)
  519. X        log_open(change_logfile_get(cp), up);
  520. X    change_run_change_file_command(cp, &wl, up);
  521. X    wl_free(&wl);
  522. X    project_free(pp);
  523. X    change_free(cp);
  524. X    user_free(up);
  525. X    trace((/*{*/"}\n"));
  526. X}
  527. X
  528. X
  529. Xvoid
  530. Xcopy_file_undo()
  531. X{
  532. X    trace(("copy_file_undo()\n{\n"/*}*/));
  533. X    switch (arglex())
  534. X    {
  535. X    default:
  536. X        copy_file_undo_main();
  537. X        break;
  538. X
  539. X    case arglex_token_help:
  540. X        copy_file_undo_help();
  541. X        break;
  542. X
  543. X    case arglex_token_list:
  544. X        copy_file_undo_list();
  545. X        break;
  546. X    }
  547. X    trace((/*{*/"}\n"));
  548. X}
  549. END_OF_FILE
  550. if test 13200 -ne `wc -c <'aegis/aecpu.c'`; then
  551.     echo shar: \"'aegis/aecpu.c'\" unpacked with wrong size!
  552. fi
  553. # end of 'aegis/aecpu.c'
  554. fi
  555. if test -f 'aegis/aedb.c' -a "${1}" != "-c" ; then 
  556.   echo shar: Will not clobber existing file \"'aegis/aedb.c'\"
  557. else
  558. echo shar: Extracting \"'aegis/aedb.c'\" \(12308 characters\)
  559. sed "s/^X//" >'aegis/aedb.c' <<'END_OF_FILE'
  560. X/*
  561. X *    aegis - project change supervisor
  562. X *    Copyright (C) 1991, 1992, 1993 Peter Miller.
  563. X *    All rights reserved.
  564. X *
  565. X *    This program is free software; you can redistribute it and/or modify
  566. X *    it under the terms of the GNU General Public License as published by
  567. X *    the Free Software Foundation; either version 2 of the License, or
  568. X *    (at your option) any later version.
  569. X *
  570. X *    This program is distributed in the hope that it will be useful,
  571. X *    but WITHOUT ANY WARRANTY; without even the implied warranty of
  572. X *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  573. X *    GNU General Public License for more details.
  574. X *
  575. X *    You should have received a copy of the GNU General Public License
  576. X *    along with this program; if not, write to the Free Software
  577. X *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  578. X *
  579. X * MANIFEST: functions to implement develop begin
  580. X */
  581. X
  582. X#include <stdio.h>
  583. X#include <stdlib.h>
  584. X#include <string.h>
  585. X#include <time.h>
  586. X#include <sys/types.h>
  587. X#include <sys/stat.h>
  588. X
  589. X#include <aedb.h>
  590. X#include <ael.h>
  591. X#include <arglex2.h>
  592. X#include <change.h>
  593. X#include <col.h>
  594. X#include <commit.h>
  595. X#include <common.h>
  596. X#include <dir.h>
  597. X#include <error.h>
  598. X#include <help.h>
  599. X#include <lock.h>
  600. X#include <option.h>
  601. X#include <os.h>
  602. X#include <project.h>
  603. X#include <sub.h>
  604. X#include <trace.h>
  605. X#include <undo.h>
  606. X#include <user.h>
  607. X
  608. X
  609. Xstatic void develop_begin_usage _((void));
  610. X
  611. Xstatic void
  612. Xdevelop_begin_usage()
  613. X{
  614. X    char        *progname;
  615. X
  616. X    progname = option_progname_get();
  617. X    fprintf(stderr, "usage: %s -Develop_Begin <change_number> [ <option>... ]\n", progname);
  618. X    fprintf(stderr, "       %s -Develop_Begin -List [ <option>... ]\n", progname);
  619. X    fprintf(stderr, "       %s -Develop_Begin -Help\n", progname);
  620. X    quit(1);
  621. X}
  622. X
  623. X
  624. Xstatic void develop_begin_help _((void));
  625. X
  626. Xstatic void
  627. Xdevelop_begin_help()
  628. X{
  629. X    static char *text[] =
  630. X    {
  631. X"NAME",
  632. X"    %s -Develop_Begin - begin development of a change",
  633. X"",
  634. X"SYNOPSIS",
  635. X"    %s -Develop_Begin <change-number> [ <option>... ]",
  636. X"    %s -Develop_Begin -List [ <option>... ]",
  637. X"    %s -Develop_Begin -Help",
  638. X"",
  639. X"DESCRIPTION",
  640. X"    The %s -Develop_Begin command is used to commence",
  641. X"    development of a change.",
  642. X"",
  643. X"    The development directory for the change will be created",
  644. X"    automatically; below the directory specified in the",
  645. X"    default_development_directory field of aeuconf(5), or if",
  646. X"    not set below the directory specified in the default_-",
  647. X"    development_directory field of aepattr(5), or if not set",
  648. X"    below the current user's home directory.  It is rare to",
  649. X"    need to know the exact pathname of the development",
  650. X"    directory, as the aecd(1) command can take you there at",
  651. X"    any time.",
  652. X"",
  653. X"    Successful execution of this command will move the",
  654. X"    specified change from the awaiting development state to",
  655. X"    the being developed state.",
  656. X"",
  657. X"OPTIONS",
  658. X"    The following options are understood:",
  659. X"",
  660. X"    -Change <number>",
  661. X"        This option may be used to specify a particular",
  662. X"        change within a project.  When no -Change option",
  663. X"        is specified, the AEGIS_CHANGE environment",
  664. X"        variable is consulted.  If that does not exist,",
  665. X"        the user's $HOME/.%src file is examined for a",
  666. X"        default change field (see aeuconf(5) for more",
  667. X"        information).  If that does not exist, when the",
  668. X"        user is only working on one change within a",
  669. X"        project, that is the default change number.",
  670. X"        Otherwise, it is an error.",
  671. X"",
  672. X"    -DIRectory <path>",
  673. X"        This option may be used to specify which directory",
  674. X"        is to be used.  It is an error if the current user",
  675. X"        does not have appropriate permissions to create",
  676. X"        the directory path given.  This must be an",
  677. X"        absolute path.",
  678. X"",
  679. X"        Caution: If you are using an automounter do not",
  680. X"        use `pwd` to make an absolute path, it usually",
  681. X"        gives the wrong answer.",
  682. X"",
  683. X"    -Help",
  684. X"        This option may be used to obtain more information",
  685. X"        about how to use the %s program.",
  686. X"",
  687. X"    -List",
  688. X"        This option may be used to obtain a list of",
  689. X"        suitable subjects for this command.  The list may",
  690. X"        be more general than expected.",
  691. X"",
  692. X"    -Project <name>",
  693. X"        This option may be used to select the project of",
  694. X"        interest.  When no -Project option is specified,",
  695. X"        the AEGIS_PROJECT environment variable is",
  696. X"        consulted.  If that does not exist, the user's",
  697. X"        $HOME/.%src file is examined for a default",
  698. X"        project field (see aeuconf(5) for more",
  699. X"        information).  If that does not exist, when the",
  700. X"        user is only working on changes within a single",
  701. X"        project, the project name defaults to that",
  702. X"        project.  Otherwise, it is an error.",
  703. X"",
  704. X"    -TERse",
  705. X"        This option may be used to cause listings to",
  706. X"        produce the bare minimum of information.  It is",
  707. X"        usually useful for shell scripts.",
  708. X"",
  709. X"    -Verbose",
  710. X"        This option may be used to cause %s to produce",
  711. X"        more output.  By default %s only produces",
  712. X"        output on errors.  When used with the -List option",
  713. X"        this option causes column headings to be added.",
  714. X"",
  715. X"    All options may be abbreviated; the abbreviation is",
  716. X"    documented as the upper case letters, all lower case",
  717. X"    letters and underscores (_) are optional.  You must use",
  718. X"    consecutive sequences of optional letters.",
  719. X"",
  720. X"    All options are case insensitive, you may type them in",
  721. X"    upper case or lower case or a combination of both, case",
  722. X"    is not important.",
  723. X"",
  724. X"    For example: the arguments \"-project, \"-PROJ\" and \"-p\"",
  725. X"    are all interpreted to mean the -Project option.  The",
  726. X"    argument \"-prj\" will not be understood, because",
  727. X"    consecutive optional characters were not supplied.",
  728. X"",
  729. X"    Options and other command line arguments may be mixed",
  730. X"    arbitrarily on the command line, after the function",
  731. X"    selectors.",
  732. X"",
  733. X"    The GNU long option names are understood.  Since all",
  734. X"    option names for aegis are long, this means ignoring the",
  735. X"    extra leading '-'.  The \"--option=value\" convention is",
  736. X"    also understood.",
  737. X"",
  738. X"RECOMMENDED ALIAS",
  739. X"    The recommended alias for this command is",
  740. X"    csh%%    alias aedb '%s -db \\!* -v'",
  741. X"    sh$    aedb(){%s -db $* -v}",
  742. X"",
  743. X"ERRORS",
  744. X"    It is an error if the change does not exist.",
  745. X"    It is an error if the change is not in the awaiting",
  746. X"    development state.",
  747. X"    It is an error if the current user is not a developer of",
  748. X"    the specified project.",
  749. X"",
  750. X"EXIT STATUS",
  751. X"    The %s command will exit with a status of 1 on any",
  752. X"    error.  The %s command will only exit with a status of",
  753. X"    0 if there are no errors.",
  754. X"",
  755. X"COPYRIGHT",
  756. X"    %C",
  757. X"",
  758. X"AUTHOR",
  759. X"    %A",
  760. X    };
  761. X
  762. X    help(text, SIZEOF(text), develop_begin_usage);
  763. X}
  764. X
  765. X
  766. Xstatic void develop_begin_list _((void));
  767. X
  768. Xstatic void
  769. Xdevelop_begin_list()
  770. X{
  771. X    string_ty    *project_name;
  772. X
  773. X    trace(("develop_begin_list()\n{\n"/*}*/));
  774. X    project_name = 0;
  775. X    arglex();
  776. X    while (arglex_token != arglex_token_eoln)
  777. X    {
  778. X        switch (arglex_token)
  779. X        {
  780. X        default:
  781. X            generic_argument(develop_begin_usage);
  782. X            continue;
  783. X
  784. X        case arglex_token_project:
  785. X            if (arglex() != arglex_token_string)
  786. X                develop_begin_usage();
  787. X            /* fall through... */
  788. X        
  789. X        case arglex_token_string:
  790. X            if (project_name)
  791. X                fatal("duplicate -Project option");
  792. X            project_name = str_from_c(arglex_value.alv_string);
  793. X            break;
  794. X        }
  795. X        arglex();
  796. X    }
  797. X    list_changes_in_state_mask
  798. X    (
  799. X        project_name,
  800. X        1 << cstate_state_awaiting_development
  801. X    );
  802. X    if (project_name)
  803. X        str_free(project_name);
  804. X    trace((/*{*/"}\n"));
  805. X}
  806. X
  807. X
  808. Xstatic void develop_begin_main _((void));
  809. X
  810. Xstatic void
  811. Xdevelop_begin_main()
  812. X{
  813. X    cstate        cstate_data;
  814. X    pstate        pstate_data;
  815. X    cstate_history    history_data;
  816. X    string_ty    *devdir;
  817. X    string_ty    *s2;
  818. X    string_ty    *project_name;
  819. X    project_ty    *pp;
  820. X    long        change_number;
  821. X    change_ty    *cp;
  822. X    user_ty        *up;
  823. X
  824. X    trace(("develop_begin_main()\n{\n"/*}*/));
  825. X    project_name = 0;
  826. X    change_number = 0;
  827. X    devdir = 0;
  828. X    while (arglex_token != arglex_token_eoln)
  829. X    {
  830. X        switch (arglex_token)
  831. X        {
  832. X        default:
  833. X            generic_argument(develop_begin_usage);
  834. X            continue;
  835. X
  836. X        case arglex_token_change:
  837. X            if (arglex() != arglex_token_number)
  838. X                develop_begin_usage();
  839. X            /* fall through... */
  840. X
  841. X        case arglex_token_number:
  842. X            if (change_number)
  843. X                fatal("duplicate -Change option");
  844. X            change_number = arglex_value.alv_number;
  845. X            if (change_number < 1)
  846. X                fatal("change %ld out of range", change_number);
  847. X            break;
  848. X
  849. X        case arglex_token_directory:
  850. X            if (arglex() != arglex_token_string)
  851. X                develop_begin_usage();
  852. X            if (devdir)
  853. X                fatal("duplicate -DIRectory option");
  854. X            /*
  855. X             * To cope with automounters, directories are stored as
  856. X             * given, or are derived from the home directory in the
  857. X             * passwd file.  Within aegis, pathnames have their
  858. X             * symbolic links resolved, and any comparison of paths
  859. X             * is done on this "system idea" of the pathname.
  860. X             */
  861. X            devdir = str_from_c(arglex_value.alv_string);
  862. X            break;
  863. X
  864. X        case arglex_token_project:
  865. X            if (arglex() != arglex_token_string)
  866. X                develop_begin_usage();
  867. X            /* fall through... */
  868. X        
  869. X        case arglex_token_string:
  870. X            if (project_name)
  871. X                fatal("duplicate -Project option");
  872. X            project_name = str_from_c(arglex_value.alv_string);
  873. X            break;
  874. X        }
  875. X        arglex();
  876. X    }
  877. X
  878. X    /*
  879. X     * locate project data
  880. X     */
  881. X    if (!project_name)
  882. X        project_name = user_default_project();
  883. X    pp = project_alloc(project_name);
  884. X    str_free(project_name);
  885. X    project_bind_existing(pp);
  886. X
  887. X    /*
  888. X     * locate user data
  889. X     */
  890. X    up = user_executing(pp);
  891. X
  892. X    /*
  893. X     * locate change data
  894. X     *
  895. X     * The change number must be given on the command line,
  896. X     * even if there is only one appropriate change.
  897. X     * The is the "least surprizes" principle at work,
  898. X     * even though we could sometimes work this out for ourself.
  899. X     */
  900. X    if (!change_number)
  901. X        fatal("change number must be stated explicitly");
  902. X    cp = change_alloc(pp, change_number);
  903. X    change_bind_existing(cp);
  904. X
  905. X    /*
  906. X     * Take an advisory write lock on the appropriate row of the change
  907. X     * table.  Take an advisory write lock on the appropriate row of the
  908. X     * user table.  The user table row may need to be created.
  909. X     * Block while can't get both simultaneously.
  910. X     */
  911. X    user_ustate_lock_prepare(up);
  912. X    change_cstate_lock_prepare(cp);
  913. X    lock_take();
  914. X    cstate_data = change_cstate_get(cp);
  915. X    pstate_data = project_pstate_get(pp);
  916. X
  917. X    /*
  918. X     * Extract the appropriate row of the change table.
  919. X     * It is an error if the change is not in the
  920. X     * undevelop_begined state.
  921. X     */
  922. X    if (cstate_data->state != cstate_state_awaiting_development)
  923. X        change_fatal(cp, "not in 'awaiting_development' state");
  924. X    if (!project_developer_query(pp, user_name(up)))
  925. X    {
  926. X        project_fatal
  927. X        (
  928. X            pp,
  929. X            "user \"%S\" is not a developer",
  930. X            user_name(up)
  931. X        );
  932. X    }
  933. X
  934. X    /*
  935. X     * Set the change data to reflect the current user
  936. X     * as developer and move it to the in-development state.
  937. X     * Append another entry to the change history.
  938. X     */
  939. X    cstate_data->state = cstate_state_being_developed;
  940. X    history_data = change_history_new(cp, up);
  941. X    history_data->what = cstate_history_what_develop_begin;
  942. X
  943. X    /*
  944. X     * Update user change table to include this change in the list of
  945. X     * changes being developed by this user.
  946. X     */
  947. X    user_own_add(up, project_name_get(pp), change_number);
  948. X
  949. X    /*
  950. X     * Create the change directory.
  951. X     */
  952. X    if (!devdir)
  953. X    {
  954. X        s2 = user_default_development_directory(up);
  955. X        assert(s2);
  956. X        devdir =
  957. X            str_format
  958. X            (
  959. X                "%S/%S.%3.3ld",
  960. X                s2,
  961. X                project_name_get(pp),
  962. X                change_number
  963. X            );
  964. X        str_free(s2);
  965. X    }
  966. X    change_development_directory_set(cp, devdir);
  967. X
  968. X    /*
  969. X     * Create the development directory.
  970. X     */
  971. X    user_become(up);
  972. X    os_mkdir(devdir, 02755);
  973. X    undo_rmdir_errok(devdir);
  974. X    user_become_undo();
  975. X    change_verbose(cp, "development directory \"%S\"", devdir);
  976. X
  977. X    /*
  978. X     * Clear the time fields.
  979. X     */
  980. X    cstate_data->build_time = 0;
  981. X    cstate_data->test_time = 0;
  982. X    cstate_data->test_baseline_time = 0;
  983. X    cstate_data->regression_test_time = 0;
  984. X
  985. X    /*
  986. X     * Update change table row (and change history table).
  987. X     * Update user table row.
  988. X     * Release advisory write locks.
  989. X     */
  990. X    change_cstate_write(cp);
  991. X    user_ustate_write(up);
  992. X    commit();
  993. X    lock_release();
  994. X
  995. X    /*
  996. X     * run the develop begin command
  997. X     */
  998. X    change_run_develop_begin_command(cp, up);
  999. X
  1000. X    /*
  1001. X     * verbose success message
  1002. X     */
  1003. X    change_verbose
  1004. X    (
  1005. X        cp,
  1006. X        "user \"%S\" has begun development",
  1007. X        user_name(up)
  1008. X    );
  1009. X    change_free(cp);
  1010. X    project_free(pp);
  1011. X    user_free(up);
  1012. X    trace((/*{*/"}\n"));
  1013. X}
  1014. X
  1015. X
  1016. Xvoid
  1017. Xdevelop_begin()
  1018. X{
  1019. X    trace(("develop_begin()\n{\n"/*}*/));
  1020. X    switch (arglex())
  1021. X    {
  1022. X    default:
  1023. X        develop_begin_main();
  1024. X        break;
  1025. X
  1026. X    case arglex_token_help:
  1027. X        develop_begin_help();
  1028. X        break;
  1029. X
  1030. X    case arglex_token_list:
  1031. X        develop_begin_list();
  1032. X        break;
  1033. X    }
  1034. X    trace((/*{*/"}\n"));
  1035. X}
  1036. END_OF_FILE
  1037. if test 12308 -ne `wc -c <'aegis/aedb.c'`; then
  1038.     echo shar: \"'aegis/aedb.c'\" unpacked with wrong size!
  1039. fi
  1040. # end of 'aegis/aedb.c'
  1041. fi
  1042. if test -f 'aegis/aenc.c' -a "${1}" != "-c" ; then 
  1043.   echo shar: Will not clobber existing file \"'aegis/aenc.c'\"
  1044. else
  1045. echo shar: Extracting \"'aegis/aenc.c'\" \(13153 characters\)
  1046. sed "s/^X//" >'aegis/aenc.c' <<'END_OF_FILE'
  1047. X/*
  1048. X *    aegis - project change supervisor
  1049. X *    Copyright (C) 1991, 1992, 1993 Peter Miller.
  1050. X *    All rights reserved.
  1051. X *
  1052. X *    This program is free software; you can redistribute it and/or modify
  1053. X *    it under the terms of the GNU General Public License as published by
  1054. X *    the Free Software Foundation; either version 2 of the License, or
  1055. X *    (at your option) any later version.
  1056. X *
  1057. X *    This program is distributed in the hope that it will be useful,
  1058. X *    but WITHOUT ANY WARRANTY; without even the implied warranty of
  1059. X *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  1060. X *    GNU General Public License for more details.
  1061. X *
  1062. X *    You should have received a copy of the GNU General Public License
  1063. X *    along with this program; if not, write to the Free Software
  1064. X *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  1065. X *
  1066. X * MANIFEST: functions to implement new change
  1067. X */
  1068. X
  1069. X#include <stdio.h>
  1070. X#include <stdlib.h>
  1071. X#include <time.h>
  1072. X
  1073. X#include <aeca.h>
  1074. X#include <aenc.h>
  1075. X#include <ael.h>
  1076. X#include <arglex2.h>
  1077. X#include <cattr.h>
  1078. X#include <change.h>
  1079. X#include <col.h>
  1080. X#include <commit.h>
  1081. X#include <common.h>
  1082. X#include <error.h>
  1083. X#include <help.h>
  1084. X#include <lock.h>
  1085. X#include <option.h>
  1086. X#include <os.h>
  1087. X#include <project.h>
  1088. X#include <trace.h>
  1089. X#include <user.h>
  1090. X
  1091. X
  1092. Xstatic void new_change_usage _((void));
  1093. X
  1094. Xstatic void
  1095. Xnew_change_usage()
  1096. X{
  1097. X    char    *progname;
  1098. X
  1099. X    progname = option_progname_get();
  1100. X    fprintf(stderr, "usage: %s -New_Change <attr-file> [ <option>... ]\n", progname);
  1101. X    fprintf(stderr, "       %s -New_Change -Edit [ <option>... ]\n", progname);
  1102. X    fprintf(stderr, "       %s -New_Change -List [ <option>... ]\n", progname);
  1103. X    fprintf(stderr, "       %s -New_Change -Help\n", progname);
  1104. X    quit(1);
  1105. X}
  1106. X
  1107. X
  1108. Xstatic void new_change_help _((void));
  1109. X
  1110. Xstatic void
  1111. Xnew_change_help()
  1112. X{
  1113. X    static char *text[] =
  1114. X    {
  1115. X"NAME",
  1116. X"    %s -New_Change - add a new change to a project",
  1117. X"",
  1118. X"SYNOPSIS",
  1119. X"    %s -New_Change <attr-file> [ <option>... ]",
  1120. X"    %s -New_Change -Edit [ <option>... ]",
  1121. X"    %s -New_Change -List [ <option>... ]",
  1122. X"    %s -New_Change -Help",
  1123. X"",
  1124. X"DESCRIPTION",
  1125. X"    The %s -New_Change command is used to add a new change",
  1126. X"    to a project.  See aecattr(5) for information on the",
  1127. X"    format of the attr-file.",
  1128. X"",
  1129. X"    The change is created in the 'awaiting_development'",
  1130. X"    state.    The change is not assigned to any user.     The",
  1131. X"    change has no development directory.",
  1132. X"",
  1133. X"    It is not possible to choose your own change number.",
  1134. X"",
  1135. X"OPTIONS",
  1136. X"    The following options are understood:",
  1137. X"",
  1138. X"    -Edit",
  1139. X"        Edit the attributes with a text editor, this is",
  1140. X"        usually more convenient than supplying a text",
  1141. X"        file.  The EDITOR environment variable will be",
  1142. X"        consulted for the name of the editor to use;",
  1143. X"        defaults to vi(1) if not set.  Warning: not well",
  1144. X"        behaved when faced with errors, the temporary",
  1145. X"        file is always deleted.",
  1146. X"",
  1147. X"    -Help",
  1148. X"        This option may be used to obtain more",
  1149. X"        information about how to use the %s program.",
  1150. X"",
  1151. X"    -List",
  1152. X"        This option may be used to obtain a list of",
  1153. X"        suitable subjects for this command.  The list may",
  1154. X"        be more general than expected.",
  1155. X"",
  1156. X"    -Project <name>",
  1157. X"        This option may be used to select the project of",
  1158. X"        interest.  When no -Project option is specified, the",
  1159. X"        AEGIS_PROJECT environment variable is consulted.  If",
  1160. X"        that does not exist, the user's $HOME/.aegisrc file",
  1161. X"        is examined for a default project field (see",
  1162. X"        aeuconf(5) for more information).  If that does not",
  1163. X"        exist, when the user is only working on changes",
  1164. X"        within a single project, the project name defaults",
  1165. X"        to that project.  Otherwise, it is an error.",
  1166. X"",
  1167. X"    -TERse",
  1168. X"        This option may be used to cause listings to",
  1169. X"        produce the bare minimum of information.  It is",
  1170. X"        usually useful for shell scripts.",
  1171. X"",
  1172. X"    -Verbose",
  1173. X"        This option may be used to cause %s to produce",
  1174. X"        more output.  By default %s only produces",
  1175. X"        output on errors.  When used with the -List",
  1176. X"        option this option causes column headings to be",
  1177. X"        added.",
  1178. X"",
  1179. X"    All options may be abbreviated; the abbreviation is",
  1180. X"    documented as the upper case letters, all lower case",
  1181. X"    letters and underscores (_) are optional.  You must use",
  1182. X"    consecutive sequences of optional letters.",
  1183. X"",
  1184. X"    All options are case insensitive, you may type them in",
  1185. X"    upper case or lower case or a combination of both, case",
  1186. X"    is not important.",
  1187. X"",
  1188. X"    For example: the arguments \"-project, \"-PROJ\" and \"-p\"",
  1189. X"    are all interpreted to mean the -Project option.  The",
  1190. X"    argument \"-prj\" will not be understood, because",
  1191. X"    consecutive optional characters were not supplied.",
  1192. X"",
  1193. X"    Options and other command line arguments may be mixed",
  1194. X"    arbitrarily on the command line, after the function",
  1195. X"    selectors.",
  1196. X"",
  1197. X"    The GNU long option names are understood.  Since all",
  1198. X"    option names for aegis are long, this means ignoring the",
  1199. X"    extra leading '-'.  The \"--option=value\" convention is",
  1200. X"    also understood.",
  1201. X"",
  1202. X"RECOMMENDED ALIAS",
  1203. X"    The recommended alias for this command is",
  1204. X"    csh%%    alias aenc '%s -nc \\!* -v'",
  1205. X"    sh$    aenc(){%s -nc $* -v}",
  1206. X"",
  1207. X"ERRORS",
  1208. X"    It is an error if the current user is not an",
  1209. X"    administrator of the project.  (In some cases it is",
  1210. X"    possible for developers of a project to create changes,",
  1211. X"    see aepattr(5) for more information.)",
  1212. X"",
  1213. X"EXIT STATUS",
  1214. X"    The %s command will exit with a status of 1 on any",
  1215. X"    error.    The %s command will only exit with a status of",
  1216. X"    0 if there are no errors.",
  1217. X"",
  1218. X"COPYRIGHT",
  1219. X"    %C",
  1220. X"",
  1221. X"AUTHOR",
  1222. X"    %A",
  1223. X    };
  1224. X
  1225. X    help(text, SIZEOF(text), new_change_usage);
  1226. X}
  1227. X
  1228. X
  1229. Xstatic void new_change_list _((void));
  1230. X
  1231. Xstatic void
  1232. Xnew_change_list()
  1233. X{
  1234. X    string_ty    *project_name;
  1235. X
  1236. X    trace(("new_chane_list()\n{\n"/*}*/));
  1237. X    project_name = 0;
  1238. X    arglex();
  1239. X    while (arglex_token != arglex_token_eoln)
  1240. X    {
  1241. X        switch (arglex_token)
  1242. X        {
  1243. X        default:
  1244. X            generic_argument(new_change_usage);
  1245. X            continue;
  1246. X
  1247. X        case arglex_token_project:
  1248. X            if (arglex() != arglex_token_string)
  1249. X                new_change_usage();
  1250. X            if (project_name)
  1251. X                fatal("duplicate -Project option");
  1252. X            project_name = str_from_c(arglex_value.alv_string);
  1253. X            break;
  1254. X        }
  1255. X        arglex();
  1256. X    }
  1257. X    list_changes(project_name, 0);
  1258. X    if (project_name)
  1259. X        str_free(project_name);
  1260. X    trace((/*{*/"}\n"));
  1261. X}
  1262. X
  1263. X
  1264. Xstatic void cattr_defaults _((cattr, pstate));
  1265. X
  1266. Xstatic void
  1267. Xcattr_defaults(a, ps)
  1268. X    cattr        a;
  1269. X    pstate        ps;
  1270. X{
  1271. X    if
  1272. X    (
  1273. X        a->cause == change_cause_internal_improvement
  1274. X    ||
  1275. X        a->cause == change_cause_internal_improvement
  1276. X    )
  1277. X    {
  1278. X        if (!(a->mask & cattr_test_exempt_mask))
  1279. X        {
  1280. X            a->test_exempt = 1;
  1281. X            a->mask |= cattr_test_exempt_mask;
  1282. X        }
  1283. X        if (!(a->mask & cattr_test_baseline_exempt_mask))
  1284. X        {
  1285. X            a->test_baseline_exempt = 1;
  1286. X            a->mask |= cattr_test_baseline_exempt_mask;
  1287. X        }
  1288. X        if (!(a->mask & cattr_regression_test_exempt_mask))
  1289. X        {
  1290. X            a->regression_test_exempt = 0;
  1291. X            a->mask |= cattr_regression_test_exempt_mask;
  1292. X        }
  1293. X    }
  1294. X    else
  1295. X    {
  1296. X        if (!(a->mask & cattr_regression_test_exempt_mask))
  1297. X        {
  1298. X            a->regression_test_exempt = 1;
  1299. X            a->mask |= cattr_regression_test_exempt_mask;
  1300. X        }
  1301. X    }
  1302. X    if (!(a->mask & cattr_test_exempt_mask))
  1303. X    {
  1304. X        a->test_exempt = ps->default_test_exemption;
  1305. X        a->mask |= cattr_test_exempt_mask;
  1306. X    }
  1307. X    if (!(a->mask & cattr_test_baseline_exempt_mask))
  1308. X    {
  1309. X        a->test_baseline_exempt = ps->default_test_exemption;
  1310. X        a->mask |= cattr_test_baseline_exempt_mask;
  1311. X    }
  1312. X}
  1313. X
  1314. X
  1315. Xstatic void new_change_main _((void));
  1316. X
  1317. Xstatic void
  1318. Xnew_change_main()
  1319. X{
  1320. X    pstate        pstate_data;
  1321. X    cstate        cstate_data;
  1322. X    cstate_history    history_data;
  1323. X    cattr        cattr_data;
  1324. X    string_ty    *project_name;
  1325. X    project_ty    *pp;
  1326. X    long        change_number;
  1327. X    change_ty    *cp;
  1328. X    user_ty        *up;
  1329. X    int        edit;
  1330. X
  1331. X    trace(("new_change_main()\n{\n"/*}*/));
  1332. X    cattr_data = 0;
  1333. X    project_name = 0;
  1334. X    edit = 0;
  1335. X    while (arglex_token != arglex_token_eoln)
  1336. X    {
  1337. X        switch (arglex_token)
  1338. X        {
  1339. X        default:
  1340. X            generic_argument(new_change_usage);
  1341. X            continue;
  1342. X
  1343. X        case arglex_token_string:
  1344. X            if (cattr_data)
  1345. X                fatal("too many files named");
  1346. X            os_become_orig();
  1347. X            cattr_data = cattr_read_file(arglex_value.alv_string);
  1348. X            os_become_undo();
  1349. X            cattr_verify(arglex_value.alv_string, cattr_data);
  1350. X            break;
  1351. X
  1352. X        case arglex_token_project:
  1353. X            if (arglex() != arglex_token_string)
  1354. X                new_change_usage();
  1355. X            if (project_name)
  1356. X                fatal("duplicate -Project option");
  1357. X            project_name = str_from_c(arglex_value.alv_string);
  1358. X            break;
  1359. X
  1360. X        case arglex_token_edit:
  1361. X            if (edit)
  1362. X                fatal("duplicate \"%s\" option", arglex_value.alv_string);
  1363. X            edit++;
  1364. X            break;
  1365. X        }
  1366. X        arglex();
  1367. X    }
  1368. X    if (!edit && !cattr_data)
  1369. X        fatal("no change attributes file named");
  1370. X
  1371. X    /*
  1372. X     * locate project data
  1373. X     */
  1374. X    if (!project_name)
  1375. X        fatal("project name must be stated explicitly");
  1376. X    pp = project_alloc(project_name);
  1377. X    str_free(project_name);
  1378. X    project_bind_existing(pp);
  1379. X
  1380. X    /*
  1381. X     * locate user data
  1382. X     */
  1383. X    up = user_executing(pp);
  1384. X    
  1385. X    /*
  1386. X     * see if must invoke editor
  1387. X     */
  1388. X    if (edit)
  1389. X    {
  1390. X        /*
  1391. X         * build template cattr
  1392. X         */
  1393. X        if (!cattr_data)
  1394. X        {
  1395. X            string_ty *none = str_from_c("none");
  1396. X            cattr_data = (cattr)cattr_type.alloc();
  1397. X            cattr_data->brief_description = str_copy(none);
  1398. X            cattr_data->description = str_copy(none);
  1399. X            cattr_data->cause = change_cause_internal_bug;
  1400. X            str_free(none);
  1401. X        }
  1402. X
  1403. X        /*
  1404. X         * default a few things
  1405. X         */
  1406. X        pstate_data = project_pstate_get(pp);
  1407. X        cattr_defaults(cattr_data, pstate_data);
  1408. X
  1409. X        /*
  1410. X         * edit the attributes
  1411. X         */
  1412. X        cattr_edit(&cattr_data);
  1413. X    }
  1414. X
  1415. X    /*
  1416. X     * Lock the project state file.
  1417. X     * Block if necessary.
  1418. X     */
  1419. X    project_pstate_lock_prepare(pp);
  1420. X    lock_take();
  1421. X    pstate_data = project_pstate_get(pp);
  1422. X
  1423. X    /*
  1424. X     * it is an error if
  1425. X     * the user is not an administrator for the project.
  1426. X     */
  1427. X    if
  1428. X    (
  1429. X        !project_administrator_query(pp, user_name(up))
  1430. X    &&
  1431. X        (
  1432. X            !pstate_data->developers_may_create_changes
  1433. X        ||
  1434. X            !project_developer_query(pp, user_name(up))
  1435. X        )
  1436. X    )
  1437. X    {
  1438. X        project_fatal
  1439. X        (
  1440. X            pp,
  1441. X            "user \"%S\" is not an administrator",
  1442. X            user_name(up)
  1443. X        );
  1444. X    }
  1445. X
  1446. X    /*
  1447. X     * when developers create changes,
  1448. X     * they may not give themselves a testing exemption,
  1449. X     * only administrators may do that.
  1450. X     */
  1451. X    if (!project_administrator_query(pp, user_name(up)))
  1452. X    {
  1453. X        /*
  1454. X         * If they are asking for default behaviour, don't complain.
  1455. X         * (e.g. admin may have given general testing exemption)
  1456. X         */
  1457. X        cattr dflt = cattr_type.alloc();
  1458. X        dflt->cause = cattr_data->cause;
  1459. X        cattr_defaults(dflt, pstate_data);
  1460. X
  1461. X        if
  1462. X        (
  1463. X            (
  1464. X                (cattr_data->mask & cattr_test_exempt_mask)
  1465. X            &&
  1466. X                cattr_data->test_exempt
  1467. X            &&
  1468. X                (cattr_data->test_exempt != dflt->test_exempt)
  1469. X            )
  1470. X        ||
  1471. X            (
  1472. X                (cattr_data->mask & cattr_test_baseline_exempt_mask)
  1473. X            &&
  1474. X                cattr_data->test_baseline_exempt
  1475. X            &&
  1476. X                (cattr_data->test_baseline_exempt != dflt->test_baseline_exempt)
  1477. X            )
  1478. X        ||
  1479. X            (
  1480. X                (cattr_data->mask & cattr_regression_test_exempt_mask)
  1481. X            &&
  1482. X                cattr_data->regression_test_exempt
  1483. X            &&
  1484. X                (cattr_data->regression_test_exempt != dflt->regression_test_exempt)
  1485. X            )
  1486. X        )
  1487. X            fatal("developers may not grant testing exemptions");
  1488. X        cattr_type.free(dflt);
  1489. X    }
  1490. X
  1491. X    /*
  1492. X     * Add another row to the change table.
  1493. X     * Create the change history.
  1494. X     */
  1495. X    assert(pstate_data->next_change_number >= 1);
  1496. X    change_number = pstate_data->next_change_number++;
  1497. X    cp = change_alloc(pp, change_number);
  1498. X    change_bind_new(cp);
  1499. X
  1500. X    cstate_data = change_cstate_get(cp);
  1501. X    cstate_data->state = cstate_state_awaiting_development;
  1502. X    history_data = change_history_new(cp, up);
  1503. X    history_data->what = cstate_history_what_new_change;
  1504. X    if (cattr_data->description)
  1505. X        cstate_data->description = str_copy(cattr_data->description);
  1506. X    assert(cattr_data->brief_description);
  1507. X    cstate_data->brief_description = str_copy(cattr_data->brief_description);
  1508. X    assert(cattr_data->mask & cattr_cause_mask);
  1509. X    if (change_number == 1)
  1510. X    {
  1511. X        cattr_data->cause = change_cause_internal_enhancement;
  1512. X        cattr_data->test_baseline_exempt = 1;
  1513. X        cattr_data->mask |= cattr_test_baseline_exempt_mask;
  1514. X        cattr_data->regression_test_exempt = 1;
  1515. X        cattr_data->mask |= cattr_regression_test_exempt_mask;
  1516. X    }
  1517. X    cattr_defaults(cattr_data, pstate_data);
  1518. X    cstate_data->cause = cattr_data->cause;
  1519. X    assert(cattr_data->mask & cattr_test_exempt_mask);
  1520. X    cstate_data->test_exempt = cattr_data->test_exempt;
  1521. X    assert(cattr_data->mask & cattr_test_baseline_exempt_mask);
  1522. X    cstate_data->test_baseline_exempt =
  1523. X        cattr_data->test_baseline_exempt;
  1524. X    assert(cattr_data->mask & cattr_regression_test_exempt_mask);
  1525. X    cstate_data->regression_test_exempt =
  1526. X        cattr_data->regression_test_exempt;
  1527. X    cattr_type.free(cattr_data);
  1528. X
  1529. X    /*
  1530. X     * Write out the change file.
  1531. X     * There is no need to lock this file
  1532. X     * as it does not exist yet;
  1533. X     * the project state file, with the number in it, is locked.
  1534. X     */
  1535. X    change_cstate_write(cp);
  1536. X
  1537. X    /*
  1538. X     * Add the change to the list of existing changes.
  1539. X     * Incriment the next_change_number.
  1540. X     * and write pstate back out.
  1541. X     */
  1542. X    project_change_append(pp, change_number);
  1543. X
  1544. X    /*
  1545. X     * Unlock the pstate file.
  1546. X     */
  1547. X    project_pstate_write(pp);
  1548. X    commit();
  1549. X    lock_release();
  1550. X
  1551. X    /*
  1552. X     * verbose success message
  1553. X     */
  1554. X    change_verbose(cp, "created");
  1555. X    project_free(pp);
  1556. X    change_free(cp);
  1557. X    user_free(up);
  1558. X    trace((/*{*/"}\n"));
  1559. X}
  1560. X
  1561. X
  1562. Xvoid
  1563. Xnew_change()
  1564. X{
  1565. X    trace(("new_change()\n{\n"/*}*/));
  1566. X    switch (arglex())
  1567. X    {
  1568. X    default:
  1569. X        new_change_main();
  1570. X        break;
  1571. X
  1572. X    case arglex_token_help:
  1573. X        new_change_help();
  1574. X        break;
  1575. X
  1576. X    case arglex_token_list:
  1577. X        new_change_list();
  1578. X        break;
  1579. X    }
  1580. X    trace((/*{*/"}\n"));
  1581. X}
  1582. END_OF_FILE
  1583. if test 13153 -ne `wc -c <'aegis/aenc.c'`; then
  1584.     echo shar: \"'aegis/aenc.c'\" unpacked with wrong size!
  1585. fi
  1586. # end of 'aegis/aenc.c'
  1587. fi
  1588. if test -f 'aegis/aenf.c' -a "${1}" != "-c" ; then 
  1589.   echo shar: Will not clobber existing file \"'aegis/aenf.c'\"
  1590. else
  1591. echo shar: Extracting \"'aegis/aenf.c'\" \(14176 characters\)
  1592. sed "s/^X//" >'aegis/aenf.c' <<'END_OF_FILE'
  1593. X/*
  1594. X *    aegis - project change supervisor
  1595. X *    Copyright (C) 1991, 1992, 1993 Peter Miller.
  1596. X *    All rights reserved.
  1597. X *
  1598. X *    This program is free software; you can redistribute it and/or modify
  1599. X *    it under the terms of the GNU General Public License as published by
  1600. X *    the Free Software Foundation; either version 2 of the License, or
  1601. X *    (at your option) any later version.
  1602. X *
  1603. X *    This program is distributed in the hope that it will be useful,
  1604. X *    but WITHOUT ANY WARRANTY; without even the implied warranty of
  1605. X *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  1606. X *    GNU General Public License for more details.
  1607. X *
  1608. X *    You should have received a copy of the GNU General Public License
  1609. X *    along with this program; if not, write to the Free Software
  1610. X *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  1611. X *
  1612. X * MANIFEST: functions to add or remove a new file to a change
  1613. X */
  1614. X
  1615. X#include <stdio.h>
  1616. X#include <stdlib.h>
  1617. X#include <unistd.h>
  1618. X
  1619. X#include <ael.h>
  1620. X#include <aenf.h>
  1621. X#include <arglex2.h>
  1622. X#include <change.h>
  1623. X#include <col.h>
  1624. X#include <commit.h>
  1625. X#include <error.h>
  1626. X#include <glue.h>
  1627. X#include <help.h>
  1628. X#include <lock.h>
  1629. X#include <log.h>
  1630. X#include <option.h>
  1631. X#include <os.h>
  1632. X#include <project.h>
  1633. X#include <trace.h>
  1634. X#include <user.h>
  1635. X#include <word.h>
  1636. X
  1637. X
  1638. Xstatic void new_file_usage _((void));
  1639. X
  1640. Xstatic void
  1641. Xnew_file_usage()
  1642. X{
  1643. X    char        *progname;
  1644. X
  1645. X    progname = option_progname_get();
  1646. X    fprintf(stderr, "usage: %s -New_File <filename>... [ <option>... ]\n", progname);
  1647. X    fprintf(stderr, "       %s -New_File -List [ <option>... ]\n", progname);
  1648. X    fprintf(stderr, "       %s -New_File -Help\n", progname);
  1649. X    quit(1);
  1650. X}
  1651. X
  1652. X
  1653. Xstatic void new_file_help _((void));
  1654. X
  1655. Xstatic void
  1656. Xnew_file_help()
  1657. X{
  1658. X    static char *text[] =
  1659. X    {
  1660. X"NAME",
  1661. X"    %s -New_File - add new files to a change",
  1662. X"",
  1663. X"SYNOPSIS",
  1664. X"    %s -New_File <file-name>... [ <option>... ]",
  1665. X"    %s -New_File -List [ <option>... ]",
  1666. X"    %s -New_File -Help",
  1667. X"",
  1668. X"DESCRIPTION",
  1669. X"    The %s -New_File command is used to add new files to a",
  1670. X"    change.",
  1671. X"",
  1672. X"    The %s program will attempt to intuit the file names",
  1673. X"    intended.  All file names are stored within %s as",
  1674. X"    relative to the root of the baseline directory tree.  The",
  1675. X"    development directory and the integration directory are",
  1676. X"    shadows of the baseline directory, and so these relative",
  1677. X"    names aply there, too.    Files named on the command line",
  1678. X"    are first converted to absolute paths if necessary.  They",
  1679. X"    are then compared with the baseline path, and the",
  1680. X"    development directory path, and the integration directory",
  1681. X"    path, to determine a root-relative name.  It is an error",
  1682. X"    if the file named is outside one of these directory",
  1683. X"    trees.",
  1684. X"",
  1685. X"    The named files will be added to the list of files in the",
  1686. X"    change.  For each file named, a new file is created in the",
  1687. X"    development directory, if it does not exist already.  The",
  1688. X"    config file will be searched for a template for the new",
  1689. X"    file.  If a template is found, the new file will be",
  1690. X"    initialized to the template, otherwise it will be created",
  1691. X"    empty.  If the file already exists, it will not be altered.",
  1692. X"    See aepconf(5) for more information.",
  1693. X"",
  1694. X"OPTIONS",
  1695. X"    The following options are understood",
  1696. X"",
  1697. X"    -Build",
  1698. X"        This option may be used to specify that the file",
  1699. X"        is constructed during a build (often only an",
  1700. X"        integrate build), so that history of it may be",
  1701. X"        kept.  This is useful for generating patch files,",
  1702. X"        where a history of generated files is important.",
  1703. X"        Files created in this way may not be copied into",
  1704. X"        a change, though they may be deleted.  Avoid",
  1705. X"        using files of this type, if at all possible.",
  1706. X"",
  1707. X"    -Change <number>",
  1708. X"        This option may be used to specify a particular",
  1709. X"        change within a project.  When no -Change option is",
  1710. X"        specified, the AEGIS_CHANGE environment variable is",
  1711. X"        consulted.  If that does not exist, the user's",
  1712. X"        $HOME/.aegisrc file is examined for a default change",
  1713. X"        field (see aeuconf(5) for more information).  If",
  1714. X"        that does not exist, when the user is only working",
  1715. X"        on one change within a project, that is the default",
  1716. X"        change number.  Otherwise, it is an error.",
  1717. X"",
  1718. X"    -Help",
  1719. X"        This option may be used to obtain more",
  1720. X"        information about how to use the %s program.",
  1721. X"",
  1722. X"    -List",
  1723. X"        This option may be used to obtain a list of",
  1724. X"        suitable subjects for this command.  The list may",
  1725. X"        be more general than expected.",
  1726. X"",
  1727. X"    -Project <name>",
  1728. X"        This option may be used to select the project of",
  1729. X"        interest.  When no -Project option is specified, the",
  1730. X"        AEGIS_PROJECT environment variable is consulted.  If",
  1731. X"        that does not exist, the user's $HOME/.aegisrc file",
  1732. X"        is examined for a default project field (see",
  1733. X"        aeuconf(5) for more information).  If that does not",
  1734. X"        exist, when the user is only working on changes",
  1735. X"        within a single project, the project name defaults",
  1736. X"        to that project.  Otherwise, it is an error.",
  1737. X"",
  1738. X"    -TERse",
  1739. X"        This option may be used to cause listings to",
  1740. X"        produce the bare minimum of information.  It is",
  1741. X"        usually useful for shell scripts.",
  1742. X"",
  1743. X"    -Verbose",
  1744. X"        This option may be used to cause %s to produce",
  1745. X"        more output.  By default %s only produces",
  1746. X"        output on errors.  When used with the -List",
  1747. X"        option this option causes column headings to be",
  1748. X"        added.",
  1749. X"",
  1750. X"    All options may be abbreviated; the abbreviation is",
  1751. X"    documented as the upper case letters, all lower case",
  1752. X"    letters and underscores (_) are optional.  You must use",
  1753. X"    consecutive sequences of optional letters.",
  1754. X"",
  1755. X"    All options are case insensitive, you may type them in",
  1756. X"    upper case or lower case or a combination of both, case",
  1757. X"    is not important.",
  1758. X"",
  1759. X"    For example: the arguments \"-project, \"-PROJ\" and \"-p\"",
  1760. X"    are all interpreted to mean the -Project option.  The",
  1761. X"    argument \"-prj\" will not be understood, because",
  1762. X"    consecutive optional characters were not supplied.",
  1763. X"",
  1764. X"    Options and other command line arguments may be mixed",
  1765. X"    arbitrarily on the command line, after the function",
  1766. X"    selectors.",
  1767. X"",
  1768. X"    The GNU long option names are understood.  Since all",
  1769. X"    option names for aegis are long, this means ignoring the",
  1770. X"    extra leading '-'.  The \"--option=value\" convention is",
  1771. X"    also understood.",
  1772. X"",
  1773. X"RECOMMENDED ALIAS",
  1774. X"    The recommended alias for this command is",
  1775. X"    csh%%    alias aenf '%s -nf \\!* -v'",
  1776. X"    sh$    aenf(){%s -nf $* -v}",
  1777. X"",
  1778. X"ERRORS",
  1779. X"    It is an error if the change is not in the",
  1780. X"    'being_developed' state.",
  1781. X"    It is an error if the change is not assigned to the",
  1782. X"    current user.",
  1783. X"    It is an error if the file is already part of the change.",
  1784. X"    It is an error if the file is already part of the",
  1785. X"    baseline.",
  1786. X"",
  1787. X"EXIT STATUS",
  1788. X"    The %s command will exit with a status of 1 on any",
  1789. X"    error.    The %s command will only exit with a status of",
  1790. X"    0 if there are no errors.",
  1791. X"",
  1792. X"COPYRIGHT",
  1793. X"    %C",
  1794. X"",
  1795. X"AUTHOR",
  1796. X"    %A",
  1797. X    };
  1798. X
  1799. X    help(text, SIZEOF(text), new_file_usage);
  1800. X}
  1801. X
  1802. X
  1803. Xstatic void new_file_list _((void));
  1804. X
  1805. Xstatic void
  1806. Xnew_file_list()
  1807. X{
  1808. X    string_ty    *project_name;
  1809. X    long        change_number;
  1810. X
  1811. X    trace(("new_file_list()\n{\n"/*}*/));
  1812. X    project_name = 0;
  1813. X    change_number = 0;
  1814. X    arglex();
  1815. X    while (arglex_token != arglex_token_eoln)
  1816. X    {
  1817. X        switch (arglex_token)
  1818. X        {
  1819. X        default:
  1820. X            generic_argument(new_file_usage);
  1821. X            continue;
  1822. X
  1823. X        case arglex_token_change:
  1824. X            if (arglex() != arglex_token_number)
  1825. X                new_file_usage();
  1826. X            /* fall through... */
  1827. X
  1828. X        case arglex_token_number:
  1829. X            if (change_number)
  1830. X                fatal("duplicate -Change option");
  1831. X            change_number = arglex_value.alv_number;
  1832. X            if (change_number < 1)
  1833. X                fatal("change %ld out of range", change_number);
  1834. X            break;
  1835. X
  1836. X        case arglex_token_project:
  1837. X            if (arglex() != arglex_token_string)
  1838. X                new_file_usage();
  1839. X            if (project_name)
  1840. X                fatal("duplicate -Project option");
  1841. X            project_name = str_from_c(arglex_value.alv_string);
  1842. X            break;
  1843. X        }
  1844. X        arglex();
  1845. X    }
  1846. X    list_project_files(project_name, change_number);
  1847. X    if (project_name)
  1848. X        str_free(project_name);
  1849. X    trace((/*{*/"}\n"));
  1850. X}
  1851. X
  1852. X
  1853. Xstatic void new_file_main _((void));
  1854. X
  1855. Xstatic void
  1856. Xnew_file_main()
  1857. X{
  1858. X    string_ty    *bl;
  1859. X    string_ty    *dd;
  1860. X    wlist        wl;
  1861. X    cstate        cstate_data;
  1862. X    pstate        pstate_data;
  1863. X    int        j;
  1864. X    string_ty    *s1;
  1865. X    string_ty    *s2;
  1866. X    pconf        pconf_data;
  1867. X    string_ty    *project_name;
  1868. X    project_ty    *pp;
  1869. X    long        change_number;
  1870. X    change_ty    *cp;
  1871. X    int        nolog;
  1872. X    user_ty        *up;
  1873. X    int        generated;
  1874. X
  1875. X    trace(("new_file_main()\n{\n"/*}*/));
  1876. X    project_name = 0;
  1877. X    change_number = 0;
  1878. X    generated = 0;
  1879. X    wl_zero(&wl);
  1880. X    nolog = 0;
  1881. X    while (arglex_token != arglex_token_eoln)
  1882. X    {
  1883. X        switch (arglex_token)
  1884. X        {
  1885. X        default:
  1886. X            generic_argument(new_file_usage);
  1887. X            continue;
  1888. X
  1889. X        case arglex_token_string:
  1890. X            s1 = str_from_c(arglex_value.alv_string);
  1891. X            os_become_orig();
  1892. X            s2 = os_pathname(s1, 1);
  1893. X            str_free(s1);
  1894. X            if (wl_member(&wl, s2))
  1895. X                fatal("file \"%s\" named more than once", arglex_value.alv_string);
  1896. X            s1 = os_entryname(s2);
  1897. X            os_become_undo();
  1898. X            if (s1->str_length > PATH_ELEMENT_MAX - 2)
  1899. X            {
  1900. X                fatal
  1901. X                (
  1902. X                    "file \"%s\" basename too long (by %ld)",
  1903. X                    arglex_value.alv_string,
  1904. X                    s1->str_length - (PATH_ELEMENT_MAX - 2)
  1905. X                );
  1906. X            }
  1907. X            str_free(s1);
  1908. X            wl_append(&wl, s2);
  1909. X            str_free(s2);
  1910. X            break;
  1911. X
  1912. X        case arglex_token_change:
  1913. X            if (arglex() != arglex_token_number)
  1914. X                new_file_usage();
  1915. X            /* fall through... */
  1916. X
  1917. X        case arglex_token_number:
  1918. X            if (change_number)
  1919. X                fatal("duplicate -Change option");
  1920. X            change_number = arglex_value.alv_number;
  1921. X            if (change_number < 1)
  1922. X                fatal("change %ld out of range", change_number);
  1923. X            break;
  1924. X
  1925. X        case arglex_token_project:
  1926. X            if (arglex() != arglex_token_string)
  1927. X                new_file_usage();
  1928. X            if (project_name)
  1929. X                fatal("duplicate -Project option");
  1930. X            project_name = str_from_c(arglex_value.alv_string);
  1931. X            break;
  1932. X
  1933. X        case arglex_token_nolog:
  1934. X            if (nolog)
  1935. X            {
  1936. X                duplicate:
  1937. X                fatal
  1938. X                (
  1939. X                    "duplicate %s option",
  1940. X                    arglex_value.alv_string
  1941. X                );
  1942. X            }
  1943. X            nolog = 1;
  1944. X            break;
  1945. X
  1946. X        case arglex_token_build:
  1947. X            if (generated)
  1948. X                goto duplicate;
  1949. X            generated = 1;
  1950. X            break;
  1951. X        }
  1952. X        arglex();
  1953. X    }
  1954. X    if (!wl.wl_nwords)
  1955. X        fatal("no files named");
  1956. X
  1957. X    /*
  1958. X     * locate project data
  1959. X     */
  1960. X    if (!project_name)
  1961. X        project_name = user_default_project();
  1962. X    pp = project_alloc(project_name);
  1963. X    str_free(project_name);
  1964. X    project_bind_existing(pp);
  1965. X
  1966. X    /*
  1967. X     * locate user data
  1968. X     */
  1969. X    up = user_executing(pp);
  1970. X
  1971. X    /*
  1972. X     * locate change data
  1973. X     */
  1974. X    if (!change_number)
  1975. X        change_number = user_default_change(up);
  1976. X    cp = change_alloc(pp, change_number);
  1977. X    change_bind_existing(cp);
  1978. X
  1979. X    /*
  1980. X     * lock the change file
  1981. X     */
  1982. X    change_cstate_lock_prepare(cp);
  1983. X    lock_take();
  1984. X    cstate_data = change_cstate_get(cp);
  1985. X    pstate_data = project_pstate_get(pp);
  1986. X    pconf_data = change_pconf_get(cp);
  1987. X
  1988. X    /*
  1989. X     * It is an error if the change is not in the in_development state.
  1990. X     * It is an error if the change is not assigned to the current user.
  1991. X     */
  1992. X    if (cstate_data->state != cstate_state_being_developed)
  1993. X        change_fatal(cp, "not in 'being_developed' state");
  1994. X    if (!str_equal(change_developer_name(cp), user_name(up)))
  1995. X    {
  1996. X        change_fatal
  1997. X        (
  1998. X            cp,
  1999. X            "user \"%S\" is not the developer",
  2000. X            user_name(up)
  2001. X        );
  2002. X    }
  2003. X
  2004. X    /*
  2005. X     * resolve the path of each file
  2006. X     * 1.    the absolute path of the file name is obtained
  2007. X     * 2.    if the file is inside the development directory, ok
  2008. X     * 3.    if the file is inside the baseline, ok
  2009. X     * 4.    if neither, error
  2010. X     */
  2011. X    dd = change_development_directory_get(cp, 1);
  2012. X    bl = project_baseline_path_get(pp, 1);
  2013. X    for (j = 0; j < wl.wl_nwords; ++j)
  2014. X    {
  2015. X        s1 = wl.wl_word[j];
  2016. X        assert(s1->str_text[0] == '/');
  2017. X        s2 = os_below_dir(dd, s1);
  2018. X        if (!s2)
  2019. X            s2 = os_below_dir(bl, s1);
  2020. X        if (!s2)
  2021. X            change_fatal(cp, "path \"%S\" unrelated", s1);
  2022. X        str_free(s1);
  2023. X        wl.wl_word[j] = s2;
  2024. X    }
  2025. X
  2026. X    /*
  2027. X     * ensure that each file
  2028. X     * 1. is not already part of the change
  2029. X     * 2. is not already part of the baseline
  2030. X     */
  2031. X    for (j = 0; j < wl.wl_nwords; ++j)
  2032. X    {
  2033. X        pstate_src    src_data;
  2034. X
  2035. X        s1 = wl.wl_word[j];
  2036. X        if (change_src_find(cp, s1))
  2037. X            change_fatal(cp, "file \"%S\" already exists", s1);
  2038. X        src_data = project_src_find(pp, s1);
  2039. X        if
  2040. X        (
  2041. X            src_data
  2042. X        &&
  2043. X            !src_data->about_to_be_created_by
  2044. X        &&
  2045. X            !src_data->deleted_by
  2046. X        )
  2047. X            project_fatal(pp, "file \"%S\" already exists", s1);
  2048. X    }
  2049. X
  2050. X    /*
  2051. X     * Create each file in the development directory,
  2052. X     * if it does not already exist.
  2053. X     * Create any necessary directories along the way.
  2054. X     */
  2055. X    user_become(up);
  2056. X    for (j = 0; j < wl.wl_nwords; ++j)
  2057. X    {
  2058. X        s1 = wl.wl_word[j];
  2059. X        os_mkdir_between(dd, s1, 02755);
  2060. X        s2 = str_format("%S/%S", dd, s1);
  2061. X        if (!os_exists(s2))
  2062. X        {
  2063. X            int        fd;
  2064. X            string_ty    *template;
  2065. X
  2066. X            user_become_undo();
  2067. X            template = change_file_template(cp, s1);
  2068. X            user_become(up);
  2069. X            fd = glue_creat(s2->str_text, 0666);
  2070. X            if (fd < 0)
  2071. X                nfatal("create(\"%s\")", s2->str_text);
  2072. X            if (template)
  2073. X            {
  2074. X                glue_write
  2075. X                (
  2076. X                    fd,
  2077. X                    template->str_text,
  2078. X                    template->str_length
  2079. X                );
  2080. X                str_free(template);
  2081. X            }
  2082. X            glue_close(fd);
  2083. X            os_chmod(s2, 0644 & ~change_umask(cp));
  2084. X        }
  2085. X        str_free(s2);
  2086. X    }
  2087. X    user_become_undo();
  2088. X
  2089. X    /*
  2090. X     * Add each file to the change file,
  2091. X     * and write it back out.
  2092. X     */
  2093. X    for (j = 0; j < wl.wl_nwords; ++j)
  2094. X    {
  2095. X        cstate_src    src_data;
  2096. X
  2097. X        src_data = change_src_new(cp);
  2098. X        src_data->file_name = str_copy(wl.wl_word[j]);
  2099. X        src_data->action = file_action_create;
  2100. X        if (generated)
  2101. X            src_data->usage = file_usage_build;
  2102. X        else
  2103. X            src_data->usage = file_usage_source;
  2104. X    }
  2105. X
  2106. X    /*
  2107. X     * the number of files changed, or the version did,
  2108. X     * so stomp on the validation fields.
  2109. X     */
  2110. X    cstate_data->build_time = 0;
  2111. X    cstate_data->test_time = 0;
  2112. X    cstate_data->test_baseline_time = 0;
  2113. X    cstate_data->regression_test_time = 0;
  2114. X
  2115. X    /*
  2116. X     * release the locks
  2117. X     */
  2118. X    change_cstate_write(cp);
  2119. X    commit();
  2120. X    lock_release();
  2121. X
  2122. X    /*
  2123. X     * run the change file command
  2124. X     */
  2125. X    if (!nolog)
  2126. X        log_open(change_logfile_get(cp), up);
  2127. X    change_run_change_file_command(cp, &wl, up);
  2128. X
  2129. X    /*
  2130. X     * verbose success message
  2131. X     */
  2132. X    for (j = 0; j < wl.wl_nwords; ++j)
  2133. X        change_verbose(cp, "file \"%S\" added", wl.wl_word[j]);
  2134. X    wl_free(&wl);
  2135. X    change_free(cp);
  2136. X    project_free(pp);
  2137. X    user_free(up);
  2138. X    trace((/*{*/"}\n"));
  2139. X}
  2140. X
  2141. X
  2142. Xvoid
  2143. Xnew_file()
  2144. X{
  2145. X    trace(("new_file()\n{\n"/*}*/));
  2146. X    switch (arglex())
  2147. X    {
  2148. X    default:
  2149. X        new_file_main();
  2150. X        break;
  2151. X
  2152. X    case arglex_token_help:
  2153. X        new_file_help();
  2154. X        break;
  2155. X
  2156. X    case arglex_token_list:
  2157. X        new_file_list();
  2158. X        break;
  2159. X    }
  2160. X    trace((/*{*/"}\n"));
  2161. X}
  2162. END_OF_FILE
  2163. if test 14176 -ne `wc -c <'aegis/aenf.c'`; then
  2164.     echo shar: \"'aegis/aenf.c'\" unpacked with wrong size!
  2165. fi
  2166. # end of 'aegis/aenf.c'
  2167. fi
  2168. if test -f 'aegis/aenfu.c' -a "${1}" != "-c" ; then 
  2169.   echo shar: Will not clobber existing file \"'aegis/aenfu.c'\"
  2170. else
  2171. echo shar: Extracting \"'aegis/aenfu.c'\" \(12929 characters\)
  2172. sed "s/^X//" >'aegis/aenfu.c' <<'END_OF_FILE'
  2173. X/*
  2174. X *    aegis - project change supervisor
  2175. X *    Copyright (C) 1991, 1992, 1993 Peter Miller.
  2176. X *    All rights reserved.
  2177. X *
  2178. X *    This program is free software; you can redistribute it and/or modify
  2179. X *    it under the terms of the GNU General Public License as published by
  2180. X *    the Free Software Foundation; either version 2 of the License, or
  2181. X *    (at your option) any later version.
  2182. X *
  2183. X *    This program is distributed in the hope that it will be useful,
  2184. X *    but WITHOUT ANY WARRANTY; without even the implied warranty of
  2185. X *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  2186. X *    GNU General Public License for more details.
  2187. X *
  2188. X *    You should have received a copy of the GNU General Public License
  2189. X *    along with this program; if not, write to the Free Software
  2190. X *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  2191. X *
  2192. X * MANIFEST: functions to add or remove a new file to a change
  2193. X */
  2194. X
  2195. X#include <stdio.h>
  2196. X#include <stdlib.h>
  2197. X#include <unistd.h>
  2198. X
  2199. X#include <ael.h>
  2200. X#include <aenfu.h>
  2201. X#include <arglex2.h>
  2202. X#include <change.h>
  2203. X#include <col.h>
  2204. X#include <commit.h>
  2205. X#include <error.h>
  2206. X#include <glue.h>
  2207. X#include <help.h>
  2208. X#include <lock.h>
  2209. X#include <log.h>
  2210. X#include <option.h>
  2211. X#include <os.h>
  2212. X#include <project.h>
  2213. X#include <trace.h>
  2214. X#include <user.h>
  2215. X#include <word.h>
  2216. X
  2217. X
  2218. Xstatic void new_file_undo_usage _((void));
  2219. X
  2220. Xstatic void
  2221. Xnew_file_undo_usage()
  2222. X{
  2223. X    char        *progname;
  2224. X
  2225. X    progname = option_progname_get();
  2226. X    fprintf(stderr, "usage: %s -New_File_Undo <filename>... [ <option>... ]\n", progname);
  2227. X    fprintf(stderr, "       %s -New_File_Undo -List [ <option>... ]\n", progname);
  2228. X    fprintf(stderr, "       %s -New_File_Undo -Help\n", progname);
  2229. X    quit(1);
  2230. X}
  2231. X
  2232. X
  2233. Xstatic void new_file_undo_help _((void));
  2234. X
  2235. Xstatic void
  2236. Xnew_file_undo_help()
  2237. X{
  2238. X    static char *text[] =
  2239. X    {
  2240. X"NAME",
  2241. X"    %s -New_File_Undo - remove new files form a change",
  2242. X"",
  2243. X"SYNOPSIS",
  2244. X"    %s -New_File_Undo <file-name>... [ <option>... ]",
  2245. X"    %s -New_File_Undo -List [ <option>... ]",
  2246. X"    %s -New_File_Undo -Help",
  2247. X"",
  2248. X"DESCRIPTION",
  2249. X"    The %s -New_File_Undo command is used to remove new",
  2250. X"    files from a change (reverse the actions of the '%s",
  2251. X"    -New_File' command).",
  2252. X"",
  2253. X"    The %s program will attempt to intuit the file names",
  2254. X"    intended.  All file names are stored within %s as",
  2255. X"    relative to the root of the baseline directory tree.  The",
  2256. X"    development directory and the integration directory are",
  2257. X"    shadows of the baseline dirdctory, and so these relative",
  2258. X"    names aply there, too.    Files named on the command line",
  2259. X"    are first converted to absolute paths if necessary.  They",
  2260. X"    are then compared with the baseline path, and the",
  2261. X"    development directory path, and the integration directory",
  2262. X"    path, to determine a root-relative name.  It is an error",
  2263. X"    if the file named is outside one of these directory",
  2264. X"    trees.",
  2265. X"",
  2266. X"    The file is removed from the list of files in the change.",
  2267. X"    The file is deleted from the development directory,",
  2268. X"    unless the -Keep option is used.",
  2269. X"",
  2270. X"OPTIONS",
  2271. X"    The following options are understood:",
  2272. X"",
  2273. X"    -Change <number>",
  2274. X"        This option may be used to specify a particular",
  2275. X"        change within a project.  When no -Change option is",
  2276. X"        specified, the AEGIS_CHANGE environment variable is",
  2277. X"        consulted.  If that does not exist, the user's",
  2278. X"        $HOME/.aegisrc file is examined for a default change",
  2279. X"        field (see aeuconf(5) for more information).  If",
  2280. X"        that does not exist, when the user is only working",
  2281. X"        on one change within a project, that is the default",
  2282. X"        change number.  Otherwise, it is an error.",
  2283. X"",
  2284. X"    -Help",
  2285. X"        This option may be used to obtain more",
  2286. X"        information about how to use the %s program.",
  2287. X"",
  2288. X"    -Keep",
  2289. X"        This option may be used to retain files and/or",
  2290. X"        directories usually deleted by the command.",
  2291. X"",
  2292. X"    -List",
  2293. X"        This option may be used to obtain a list of",
  2294. X"        suitable subjects for this command.  The list may",
  2295. X"        be more general than expected.",
  2296. X"",
  2297. X"    -Project <name>",
  2298. X"        This option may be used to select the project of",
  2299. X"        interest.  When no -Project option is specified, the",
  2300. X"        AEGIS_PROJECT environment variable is consulted.  If",
  2301. X"        that does not exist, the user's $HOME/.aegisrc file",
  2302. X"        is examined for a default project field (see",
  2303. X"        aeuconf(5) for more information).  If that does not",
  2304. X"        exist, when the user is only working on changes",
  2305. X"        within a single project, the project name defaults",
  2306. X"        to that project.  Otherwise, it is an error.",
  2307. X"",
  2308. X"    -TERse",
  2309. X"        This option may be used to cause listings to",
  2310. X"        produce the bare minimum of information.  It is",
  2311. X"        usually useful for shell scripts.",
  2312. X"",
  2313. X"    -Verbose",
  2314. X"        This option may be used to cause %s to produce",
  2315. X"        more output.  By default %s only produces",
  2316. X"        output on errors.  When used with the -List",
  2317. X"        option this option causes column headings to be",
  2318. X"        added.",
  2319. X"",
  2320. X"    All options may be abbreviated; the abbreviation is",
  2321. X"    documented as the upper case letters, all lower case",
  2322. X"    letters and underscores (_) are optional.  You must use",
  2323. X"    consecutive sequences of optional letters.",
  2324. X"",
  2325. X"    All options are case insensitive, you may type them in",
  2326. X"    upper case or lower case or a combination of both, case",
  2327. X"    is not important.",
  2328. X"",
  2329. X"    For example: the arguments \"-project, \"-PROJ\" and \"-p\"",
  2330. X"    are all interpreted to mean the -Project option.  The",
  2331. X"    argument \"-prj\" will not be understood, because",
  2332. X"    consecutive optional characters were not supplied.",
  2333. X"",
  2334. X"    Options and other command line arguments may be mixed",
  2335. X"    arbitrarily on the command line, after the function",
  2336. X"    selectors.",
  2337. X"",
  2338. X"    The GNU long option names are understood.  Since all",
  2339. X"    option names for aegis are long, this means ignoring the",
  2340. X"    extra leading '-'.  The \"--option=value\" convention is",
  2341. X"    also understood.",
  2342. X"",
  2343. X"RECOMMENDED ALIAS",
  2344. X"    The recommended alias for this command is",
  2345. X"    csh%%    alias aenfu '%s -nfu \\!$ -v'",
  2346. X"    sh$    aenfu(){%s -nfu $* -v}",
  2347. X"",
  2348. X"ERRORS",
  2349. X"    It is an error if the change is not in the",
  2350. X"    'being_developed' state.",
  2351. X"    It is an error if the change is not assigned to the",
  2352. X"    current user.",
  2353. X"    It is an error if the file is not in the change.",
  2354. X"    It is an error if the file was not added to the change",
  2355. X"    with the '%s -New_File' command.",
  2356. X"",
  2357. X"EXIT STATUS",
  2358. X"    The %s command will exit with a status of 1 on any",
  2359. X"    error.    The %s command will only exit with a status of",
  2360. X"    0 if there are no errors.",
  2361. X"",
  2362. X"COPYRIGHT",
  2363. X"    %C",
  2364. X"",
  2365. X"AUTHOR",
  2366. X"    %A",
  2367. X    };
  2368. X
  2369. X    help(text, SIZEOF(text), new_file_undo_usage);
  2370. X}
  2371. X
  2372. X
  2373. Xstatic void new_file_undo_list _((void));
  2374. X
  2375. Xstatic void
  2376. Xnew_file_undo_list()
  2377. X{
  2378. X    string_ty    *project_name;
  2379. X    long        change_number;
  2380. X
  2381. X    trace(("new_file_undo_list()\n{\n"/*}*/));
  2382. X    project_name = 0;
  2383. X    change_number = 0;
  2384. X    arglex();
  2385. X    while (arglex_token != arglex_token_eoln)
  2386. X    {
  2387. X        switch (arglex_token)
  2388. X        {
  2389. X        default:
  2390. X            generic_argument(new_file_undo_usage);
  2391. X            continue;
  2392. X
  2393. X        case arglex_token_change:
  2394. X            if (arglex() != arglex_token_number)
  2395. X                new_file_undo_usage();
  2396. X            /* fall through... */
  2397. X
  2398. X        case arglex_token_number:
  2399. X            if (change_number)
  2400. X                fatal("duplicate -Change option");
  2401. X            change_number = arglex_value.alv_number;
  2402. X            if (change_number < 1)
  2403. X                fatal("change %ld out of range", change_number);
  2404. X            break;
  2405. X
  2406. X        case arglex_token_project:
  2407. X            if (arglex() != arglex_token_string)
  2408. X                new_file_undo_usage();
  2409. X            if (project_name)
  2410. X                fatal("duplicate -Project option");
  2411. X            project_name = str_from_c(arglex_value.alv_string);
  2412. X            break;
  2413. X        }
  2414. X        arglex();
  2415. X    }
  2416. X    list_change_files(project_name, change_number);
  2417. X    if (project_name)
  2418. X        str_free(project_name);
  2419. X    trace((/*{*/"}\n"));
  2420. X}
  2421. X
  2422. X
  2423. Xstatic void new_file_undo_main _((void));
  2424. X
  2425. Xstatic void
  2426. Xnew_file_undo_main()
  2427. X{
  2428. X    wlist        wl;
  2429. X    cstate        cstate_data;
  2430. X    pstate        pstate_data;
  2431. X    int        j;
  2432. X    string_ty    *s1;
  2433. X    string_ty    *s2;
  2434. X    int        keep;
  2435. X    pconf        pconf_data;
  2436. X    string_ty    *project_name;
  2437. X    project_ty    *pp;
  2438. X    long        change_number;
  2439. X    change_ty    *cp;
  2440. X    int        nolog;
  2441. X    user_ty        *up;
  2442. X    string_ty    *dd;
  2443. X    string_ty    *bl;
  2444. X
  2445. X    trace(("new_file_undo_main()\n{\n"/*}*/));
  2446. X    project_name = 0;
  2447. X    change_number = 0;
  2448. X    wl_zero(&wl);
  2449. X    keep = 0;
  2450. X    nolog = 0;
  2451. X    while (arglex_token != arglex_token_eoln)
  2452. X    {
  2453. X        switch (arglex_token)
  2454. X        {
  2455. X        default:
  2456. X            generic_argument(new_file_undo_usage);
  2457. X            continue;
  2458. X
  2459. X        case arglex_token_string:
  2460. X            s1 = str_from_c(arglex_value.alv_string);
  2461. X            os_become_orig();
  2462. X            s2 = os_pathname(s1, 1);
  2463. X            os_become_undo();
  2464. X            str_free(s1);
  2465. X            if (wl_member(&wl, s2))
  2466. X                fatal("file \"%s\" named more than once", arglex_value.alv_string);
  2467. X            wl_append(&wl, s2);
  2468. X            str_free(s2);
  2469. X            break;
  2470. X
  2471. X        case arglex_token_keep:
  2472. X            if (keep)
  2473. X            {
  2474. X                duplicate:
  2475. X                fatal("duplicate %s option", arglex_value.alv_string);
  2476. X            }
  2477. X            keep = 1;
  2478. X            break;
  2479. X
  2480. X        case arglex_token_change:
  2481. X            if (arglex() != arglex_token_number)
  2482. X                new_file_undo_usage();
  2483. X            /* fall through... */
  2484. X
  2485. X        case arglex_token_number:
  2486. X            if (change_number)
  2487. X                fatal("duplicate -Change option");
  2488. X            change_number = arglex_value.alv_number;
  2489. X            if (change_number < 1)
  2490. X                fatal("change %ld out of range", change_number);
  2491. X            break;
  2492. X
  2493. X        case arglex_token_project:
  2494. X            if (arglex() != arglex_token_string)
  2495. X                new_file_undo_usage();
  2496. X            if (project_name)
  2497. X                fatal("duplicate -Project option");
  2498. X            project_name = str_from_c(arglex_value.alv_string);
  2499. X            break;
  2500. X
  2501. X        case arglex_token_nolog:
  2502. X            if (nolog)
  2503. X                goto duplicate;
  2504. X            nolog = 1;
  2505. X            break;
  2506. X        }
  2507. X        arglex();
  2508. X    }
  2509. X    if (!wl.wl_nwords)
  2510. X        fatal("no files named");
  2511. X
  2512. X    /*
  2513. X     * locate project data
  2514. X     */
  2515. X    if (!project_name)
  2516. X        project_name = user_default_project();
  2517. X    pp = project_alloc(project_name);
  2518. X    str_free(project_name);
  2519. X    project_bind_existing(pp);
  2520. X
  2521. X    /*
  2522. X     * locate user data
  2523. X     */
  2524. X    up = user_executing(pp);
  2525. X
  2526. X    /*
  2527. X     * locate change data
  2528. X     */
  2529. X    if (!change_number)
  2530. X        change_number = user_default_change(up);
  2531. X    cp = change_alloc(pp, change_number);
  2532. X    change_bind_existing(cp);
  2533. X
  2534. X    /*
  2535. X     * lock the change file
  2536. X     */
  2537. X    change_cstate_lock_prepare(cp);
  2538. X    lock_take();
  2539. X    cstate_data = change_cstate_get(cp);
  2540. X    pstate_data = project_pstate_get(pp);
  2541. X    pconf_data = change_pconf_get(cp);
  2542. X
  2543. X    /*
  2544. X     * It is an error if the change is not in the in_development state.
  2545. X     * It is an error if the change is not assigned to the current user.
  2546. X     */
  2547. X    if (cstate_data->state != cstate_state_being_developed)
  2548. X        change_fatal(cp, "not in 'being_developed' state");
  2549. X    if (!str_equal(change_developer_name(cp), user_name(up)))
  2550. X    {
  2551. X        change_fatal
  2552. X        (
  2553. X            cp,
  2554. X            "user \"%S\" is not the developer",
  2555. X            user_name(up)
  2556. X        );
  2557. X    }
  2558. X
  2559. X    /*
  2560. X     * resolve the path of each file
  2561. X     * 1.    the absolute path of the file name is obtained
  2562. X     * 2.    if the file is inside the development directory, ok
  2563. X     * 3.    if the file is inside the baseline, ok
  2564. X     * 4.    if neither, error
  2565. X     */
  2566. X    dd = change_development_directory_get(cp, 1);
  2567. X    bl = project_baseline_path_get(pp, 1);
  2568. X    for (j = 0; j < wl.wl_nwords; ++j)
  2569. X    {
  2570. X        s1 = wl.wl_word[j];
  2571. X        assert(s1->str_text[0] == '/');
  2572. X        s2 = os_below_dir(dd, s1);
  2573. X        if (!s2)
  2574. X            s2 = os_below_dir(bl, s1);
  2575. X        if (!s2)
  2576. X            change_fatal(cp, "path \"%S\" unrelated", s1);
  2577. X        str_free(s1);
  2578. X        wl.wl_word[j] = s2;
  2579. X    }
  2580. X
  2581. X    /*
  2582. X     * ensure that each file
  2583. X     * 1. is already part of the change
  2584. X     * 2. is being created by this change
  2585. X     */
  2586. X    for (j = 0; j < wl.wl_nwords; ++j)
  2587. X    {
  2588. X        cstate_src    src_data;
  2589. X
  2590. X        s1 = wl.wl_word[j];
  2591. X        src_data = change_src_find(cp, s1);
  2592. X        if (!src_data)
  2593. X            change_fatal(cp, "file \"%S\" not in change", s1);
  2594. X        if
  2595. X        (
  2596. X            src_data->action != file_action_create
  2597. X        ||
  2598. X            src_data->usage != file_usage_source
  2599. X        )
  2600. X            change_fatal(cp, "file \"%S\" is not -New_File", s1);
  2601. X    }
  2602. X
  2603. X    /*
  2604. X     * Remove each file from the development directory,
  2605. X     * if it still exists.
  2606. X     */
  2607. X    if (!keep)
  2608. X    {
  2609. X        user_become(up);
  2610. X        for (j = 0; j < wl.wl_nwords; ++j)
  2611. X        {
  2612. X            s1 = wl.wl_word[j];
  2613. X            s2 = str_format("%S/%S", dd, s1);
  2614. X            if (os_exists(s2))
  2615. X                commit_unlink_errok(s2);
  2616. X            str_free(s2);
  2617. X
  2618. X            s2 = str_format("%S/%S,D", dd, s1);
  2619. X            if (os_exists(s2))
  2620. X                commit_unlink_errok(s2);
  2621. X            str_free(s2);
  2622. X        }
  2623. X        os_become_undo();
  2624. X    }
  2625. X
  2626. X    /*
  2627. X     * Remove each file to the change file,
  2628. X     * and write it back out.
  2629. X     */
  2630. X    for (j = 0; j < wl.wl_nwords; ++j)
  2631. X        change_src_remove(cp, wl.wl_word[j]);
  2632. X
  2633. X    /*
  2634. X     * the number of files changed, or the version did,
  2635. X     * so stomp on the validation fields.
  2636. X     */
  2637. X    cstate_data->build_time = 0;
  2638. X    cstate_data->test_time = 0;
  2639. X    cstate_data->test_baseline_time = 0;
  2640. X    cstate_data->regression_test_time = 0;
  2641. X
  2642. X    /*
  2643. X     * release the locks
  2644. X     */
  2645. X    change_cstate_write(cp);
  2646. X    commit();
  2647. X    lock_release();
  2648. X
  2649. X    /*
  2650. X     * run the change file command
  2651. X     */
  2652. X    if (!nolog)
  2653. X        log_open(change_logfile_get(cp), up);
  2654. X    change_run_change_file_command(cp, &wl, up);
  2655. X
  2656. X    /*
  2657. X     * verbose success message
  2658. X     */
  2659. X    for (j = 0; j < wl.wl_nwords; ++j)
  2660. X    {
  2661. X        change_verbose
  2662. X        (
  2663. X            cp,
  2664. X            "file \"%S\" new file removed",
  2665. X            wl.wl_word[j]
  2666. X        );
  2667. X    }
  2668. X    wl_free(&wl);
  2669. X    project_free(pp);
  2670. X    change_free(cp);
  2671. X    user_free(up);
  2672. X    trace((/*{*/"}\n"));
  2673. X}
  2674. X
  2675. X
  2676. Xvoid
  2677. Xnew_file_undo()
  2678. X{
  2679. X    trace(("new_file_undo()\n{\n"/*}*/));
  2680. X    switch (arglex())
  2681. X    {
  2682. X    default:
  2683. X        new_file_undo_main();
  2684. X        break;
  2685. X
  2686. X    case arglex_token_help:
  2687. X        new_file_undo_help();
  2688. X        break;
  2689. X
  2690. X    case arglex_token_list:
  2691. X        new_file_undo_list();
  2692. X        break;
  2693. X    }
  2694. X    trace((/*{*/"}\n"));
  2695. X}
  2696. END_OF_FILE
  2697. if test 12929 -ne `wc -c <'aegis/aenfu.c'`; then
  2698.     echo shar: \"'aegis/aenfu.c'\" unpacked with wrong size!
  2699. fi
  2700. # end of 'aegis/aenfu.c'
  2701. fi
  2702. if test -f 'aegis/aerf.c' -a "${1}" != "-c" ; then 
  2703.   echo shar: Will not clobber existing file \"'aegis/aerf.c'\"
  2704. else
  2705. echo shar: Extracting \"'aegis/aerf.c'\" \(13632 characters\)
  2706. sed "s/^X//" >'aegis/aerf.c' <<'END_OF_FILE'
  2707. X/*
  2708. X *    aegis - project change supervisor
  2709. X *    Copyright (C) 1991, 1992, 1993 Peter Miller.
  2710. X *    All rights reserved.
  2711. X *
  2712. X *    This program is free software; you can redistribute it and/or modify
  2713. X *    it under the terms of the GNU General Public License as published by
  2714. X *    the Free Software Foundation; either version 2 of the License, or
  2715. X *    (at your option) any later version.
  2716. X *
  2717. X *    This program is distributed in the hope that it will be useful,
  2718. X *    but WITHOUT ANY WARRANTY; without even the implied warranty of
  2719. X *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  2720. X *    GNU General Public License for more details.
  2721. X *
  2722. X *    You should have received a copy of the GNU General Public License
  2723. X *    along with this program; if not, write to the Free Software
  2724. X *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  2725. X *
  2726. X * MANIFEST: functions to impliment review fail
  2727. X */
  2728. X
  2729. X#include <stdio.h>
  2730. X#include <stdlib.h>
  2731. X#include <sys/types.h>
  2732. X#include <sys/stat.h>
  2733. X
  2734. X#include <ael.h>
  2735. X#include <aerf.h>
  2736. X#include <arglex2.h>
  2737. X#include <change.h>
  2738. X#include <commit.h>
  2739. X#include <dir.h>
  2740. X#include <error.h>
  2741. X#include <file.h>
  2742. X#include <help.h>
  2743. X#include <lock.h>
  2744. X#include <mem.h>
  2745. X#include <option.h>
  2746. X#include <os.h>
  2747. X#include <project.h>
  2748. X#include <sub.h>
  2749. X#include <trace.h>
  2750. X#include <undo.h>
  2751. X#include <user.h>
  2752. X
  2753. X
  2754. Xstatic void review_fail_usage _((void));
  2755. X
  2756. Xstatic void
  2757. Xreview_fail_usage()
  2758. X{
  2759. X    char        *progname;
  2760. X
  2761. X    progname = option_progname_get();
  2762. X    fprintf(stderr, "usage: %s -Review_FAIL <reason-file> [ <option>... ]\n", progname);
  2763. X    fprintf(stderr, "       %s -Review_FAIL -Edit [ <option>... ]\n", progname);
  2764. X    fprintf(stderr, "       %s -Review_FAIL -List [ <option>... ]\n", progname);
  2765. X    fprintf(stderr, "       %s -Review_FAIL -Help\n", progname);
  2766. X    quit(1);
  2767. X}
  2768. X
  2769. X
  2770. Xstatic void review_fail_help _((void));
  2771. X
  2772. Xstatic void
  2773. Xreview_fail_help()
  2774. X{
  2775. X    static char *text[] =
  2776. X    {
  2777. X"NAME",
  2778. X"    %s -Review_FAIL - fail a change review",
  2779. X"",
  2780. X"SYNOPSIS",
  2781. X"    %s -Review_FAIL <reason-file> [ <option>... ]",
  2782. X"    %s -Review_FAIL -Edit [ <option>... ]",
  2783. X"    %s -Review_FAIL -List [ <option>... ]",
  2784. X"    %s -Review_FAIL -Help",
  2785. X"",
  2786. X"DESCRIPTION",
  2787. X"    The %s -Review_FAIL command is used to inform",
  2788. X"    %s that a change has failed review.",
  2789. X"",
  2790. X"    The change will be returned from the 'being_reviewed'",
  2791. X"    state to the 'being_developed' state.  The change will",
  2792. X"    cease to be assigned to the current user, and will be",
  2793. X"    reassigned to the originating developer.",
  2794. X"",
  2795. X"    The developer will be notified by mail.     See the",
  2796. X"    integrate_fail_notify_command in aepconf(5) for more",
  2797. X"    information.",
  2798. X"",
  2799. X"    The reason-file will contain a description of why the",
  2800. X"    change was failed.  The file is in plain text.    It is",
  2801. X"    recommened that you only use newline to terminate",
  2802. X"    paragraphs, as with will result in better formatting in",
  2803. X"    the various listings.",
  2804. X"",
  2805. X"OPTIONS",
  2806. X"    The following options are understood:",
  2807. X"",
  2808. X"    -Change <number>",
  2809. X"        This option may be used to specify a particular",
  2810. X"        change within a project.  When no -Change option is",
  2811. X"        specified, the AEGIS_CHANGE environment variable is",
  2812. X"        consulted.  If that does not exist, the user's",
  2813. X"        $HOME/.aegisrc file is examined for a default change",
  2814. X"        field (see aeuconf(5) for more information).  If",
  2815. X"        that does not exist, when the user is only working",
  2816. X"        on one change within a project, that is the default",
  2817. X"        change number.  Otherwise, it is an error.",
  2818. X"",
  2819. X"    -Edit",
  2820. X"        Edit the attributes with a text editor, this is",
  2821. X"        usually more convenient than supplying a text",
  2822. X"        file.  The EDITOR environment variable will be",
  2823. X"        consulted for the name of the editor to use;",
  2824. X"        defaults to vi(1) if not set.  Warning: not well",
  2825. X"        behaved when faced with errors, the temporary",
  2826. X"        file is always deleted.",
  2827. X"",
  2828. X"    -Help",
  2829. X"        This option may be used to obtain more",
  2830. X"        information about how to use the %s program.",
  2831. X"",
  2832. X"    -List",
  2833. X"        This option may be used to obtain a list of",
  2834. X"        suitable subjects for this command.  The list may",
  2835. X"        be more general than expected.",
  2836. X"",
  2837. X"    -Project <name>",
  2838. X"        This option may be used to select the project of",
  2839. X"        interest.  When no -Project option is specified, the",
  2840. X"        AEGIS_PROJECT environment variable is consulted.  If",
  2841. X"        that does not exist, the user's $HOME/.aegisrc file",
  2842. X"        is examined for a default project field (see",
  2843. X"        aeuconf(5) for more information).  If that does not",
  2844. X"        exist, when the user is only working on changes",
  2845. X"        within a single project, the project name defaults",
  2846. X"        to that project.  Otherwise, it is an error.",
  2847. X"",
  2848. X"    -TERse",
  2849. X"        This option may be used to cause listings to",
  2850. X"        produce the bare minimum of information.  It is",
  2851. X"        usually useful for shell scripts.",
  2852. X"",
  2853. X"    -Verbose",
  2854. X"        This option may be used to cause %s to produce",
  2855. X"        more output.  By default %s only produces",
  2856. X"        output on errors.  When used with the -List",
  2857. X"        option this option causes column headings to be",
  2858. X"        added.",
  2859. X"",
  2860. X"    All options may be abbreviated; the abbreviation is",
  2861. X"    documented as the upper case letters, all lower case",
  2862. X"    letters and underscores (_) are optional.  You must use",
  2863. X"    consecutive sequences of optional letters.",
  2864. X"",
  2865. X"    All options are case insensitive, you may type them in",
  2866. X"    upper case or lower case or a combination of both, case",
  2867. X"    is not important.",
  2868. X"",
  2869. X"    For example: the arguments \"-project, \"-PROJ\" and \"-p\"",
  2870. X"    are all interpreted to mean the -Project option.  The",
  2871. X"    argument \"-prj\" will not be understood, because",
  2872. X"    consecutive optional characters were not supplied.",
  2873. X"",
  2874. X"    Options and other command line arguments may be mixed",
  2875. X"    arbitrarily on the command line, after the function",
  2876. X"    selectors.",
  2877. X"",
  2878. X"    The GNU long option names are understood.  Since all",
  2879. X"    option names for aegis are long, this means ignoring the",
  2880. X"    extra leading '-'.  The \"--option=value\" convention is",
  2881. X"    also understood.",
  2882. X"",
  2883. X"RECOMMENDED ALIAS",
  2884. X"    The recommended alias for this command is",
  2885. X"    csh%%    alias aerf '%s -rf \\!* -v'",
  2886. X"    sh$    aerf(){%s -rf $* -v}",
  2887. X"",
  2888. X"ERRORS",
  2889. X"    It is an error if the change is not in the",
  2890. X"    'being_reviewed' state.",
  2891. X"    It is an error if the current user is not a reviewer for",
  2892. X"    the project.",
  2893. X"    It is an error if the current user developed the change",
  2894. X"    and the project is configured to disallow developers to",
  2895. X"    review their own changes (default).",
  2896. X"",
  2897. X"EXIT STATUS",
  2898. X"    The %s command will exit with a status of 1 on any",
  2899. X"    error.    The %s command will only exit with a status of",
  2900. X"    0 if there are no errors.",
  2901. X"",
  2902. X"COPYRIGHT",
  2903. X"    %C",
  2904. X"",
  2905. X"AUTHOR",
  2906. X"    %A",
  2907. X    };
  2908. X
  2909. X    help(text, SIZEOF(text), review_fail_usage);
  2910. X}
  2911. X
  2912. X
  2913. Xstatic void review_fail_list _((void (*usage)(void)));
  2914. X
  2915. Xstatic void
  2916. Xreview_fail_list(usage)
  2917. X    void        (*usage)_((void));
  2918. X{
  2919. X    string_ty    *project_name;
  2920. X
  2921. X    trace(("review_fail_list()\n{\n"/*}*/));
  2922. X    project_name = 0;
  2923. X    arglex();
  2924. X    while (arglex_token != arglex_token_eoln)
  2925. X    {
  2926. X        switch (arglex_token)
  2927. X        {
  2928. X        default:
  2929. X            generic_argument(usage);
  2930. X            continue;
  2931. X
  2932. X        case arglex_token_project:
  2933. X            if (arglex() != arglex_token_string)
  2934. X                usage();
  2935. X            /* fall through... */
  2936. X
  2937. X        case arglex_token_string:
  2938. X            if (project_name)
  2939. X                fatal("duplicate -Project option");
  2940. X            project_name = str_from_c(arglex_value.alv_string);
  2941. X            break;
  2942. X        }
  2943. X        arglex();
  2944. X    }
  2945. X    list_changes_in_state_mask
  2946. X    (
  2947. X        project_name,
  2948. X        1 << cstate_state_being_reviewed
  2949. X    );
  2950. X    if (project_name)
  2951. X        str_free(project_name);
  2952. X    trace((/*{*/"}\n"));
  2953. X}
  2954. X
  2955. X
  2956. Xstatic void repair_diff_time _((change_ty *, string_ty *));
  2957. X
  2958. Xstatic void
  2959. Xrepair_diff_time(cp, path)
  2960. X    change_ty    *cp;
  2961. X    string_ty    *path;
  2962. X{
  2963. X    string_ty    *s;
  2964. X    cstate_src    src_data;
  2965. X    string_ty    *s2;
  2966. X
  2967. X    s = os_below_dir(change_development_directory_get(cp, 1), path);
  2968. X    src_data = change_src_find(cp, s);
  2969. X    if (src_data)
  2970. X        src_data->diff_time = os_mtime(path);
  2971. X    else
  2972. X    {
  2973. X        if
  2974. X        (
  2975. X            s->str_length > 2
  2976. X        &&
  2977. X            !strcmp(s->str_text + s->str_length - 2, ",D")
  2978. X        )
  2979. X        {
  2980. X            s2 = str_n_from_c(s->str_text, s->str_length - 2);
  2981. X            src_data = change_src_find(cp, s2);
  2982. X            if (src_data)
  2983. X                src_data->diff_file_time = os_mtime(path);
  2984. X            str_free(s2);
  2985. X        }
  2986. X    }
  2987. X    str_free(s);
  2988. X}
  2989. X
  2990. X
  2991. Xstatic void rf_func _((void *, dir_walk_message_ty, string_ty *, struct stat *));
  2992. X
  2993. Xstatic void
  2994. Xrf_func(arg, message, path, st)
  2995. X    void        *arg;
  2996. X    dir_walk_message_ty message;
  2997. X    string_ty    *path;
  2998. X    struct stat    *st;
  2999. X{
  3000. X    change_ty    *cp;
  3001. X    int        uid;
  3002. X
  3003. X    trace(("rf_func(message = %d, path = %08lX, st = %08lX)\n{\n"/*}*/,
  3004. X        message, path, st));
  3005. X    cp = (change_ty *)arg;
  3006. X    trace_string(path->str_text);
  3007. X    switch (message)
  3008. X    {
  3009. X    case dir_walk_file:
  3010. X    case dir_walk_dir_before:
  3011. X        os_become_query(&uid, (int *)0, (int *)0);
  3012. X        if (st->st_uid == uid)
  3013. X        {
  3014. X            os_chmod(path, st->st_mode | 0200);
  3015. X            undo_chmod(path, st->st_mode);
  3016. X        }
  3017. X        repair_diff_time(cp, path);
  3018. X        break;
  3019. X
  3020. X    case dir_walk_dir_after:
  3021. X    case dir_walk_special:
  3022. X    case dir_walk_symlink:
  3023. X        break;
  3024. X    }
  3025. X    trace((/*{*/"}\n"));
  3026. X}
  3027. X
  3028. X
  3029. Xstatic void review_fail_main _((void));
  3030. X
  3031. Xstatic void
  3032. Xreview_fail_main()
  3033. X{
  3034. X    string_ty    *dd;
  3035. X    cstate        cstate_data;
  3036. X    pstate        pstate_data;
  3037. X    cstate_history    history_data;
  3038. X    string_ty    *comment = 0;
  3039. X    int        j;
  3040. X    string_ty    *project_name;
  3041. X    project_ty    *pp;
  3042. X    long        change_number;
  3043. X    change_ty    *cp;
  3044. X    user_ty        *up;
  3045. X    user_ty        *devup;
  3046. X    int        edit;
  3047. X
  3048. X    trace(("review_fail_main()\n{\n"/*}*/));
  3049. X    project_name = 0;
  3050. X    change_number = 0;
  3051. X    edit = 0;
  3052. X    while (arglex_token != arglex_token_eoln)
  3053. X    {
  3054. X        switch (arglex_token)
  3055. X        {
  3056. X        default:
  3057. X            generic_argument(review_fail_usage);
  3058. X            continue;
  3059. X
  3060. X        case arglex_token_string:
  3061. X            if (comment)
  3062. X                fatal("too many files named");
  3063. X            os_become_orig();
  3064. X            comment = read_whole_file(arglex_value.alv_string);
  3065. X            os_become_undo();
  3066. X            break;
  3067. X
  3068. X        case arglex_token_change:
  3069. X            if (arglex() != arglex_token_number)
  3070. X                review_fail_usage();
  3071. X            /* fall through... */
  3072. X
  3073. X        case arglex_token_number:
  3074. X            if (change_number)
  3075. X                fatal("duplicate -Change option");
  3076. X            change_number = arglex_value.alv_number;
  3077. X            if (change_number < 1)
  3078. X                fatal("change %ld out of range", change_number);
  3079. X            break;
  3080. X
  3081. X        case arglex_token_project:
  3082. X            if (arglex() != arglex_token_string)
  3083. X                review_fail_usage();
  3084. X            if (project_name)
  3085. X                fatal("duplicate -Project option");
  3086. X            project_name = str_from_c(arglex_value.alv_string);
  3087. X            break;
  3088. X
  3089. X        case arglex_token_edit:
  3090. X            if (edit)
  3091. X                fatal("duplicate %s option", arglex_value.alv_string);
  3092. X            edit++;
  3093. X            break;
  3094. X        }
  3095. X        arglex();
  3096. X    }
  3097. X    if (edit)
  3098. X    {
  3099. X        if (comment)
  3100. X            fatal("may not use -Edit and also name a comment file");
  3101. X        comment = os_edit_new();
  3102. X    }
  3103. X    if (!comment)
  3104. X        fatal("no comment file supplied");
  3105. X
  3106. X    /*
  3107. X     * locate project data
  3108. X     */
  3109. X    if (!project_name)
  3110. X        project_name = user_default_project();
  3111. X    pp = project_alloc(project_name);
  3112. X    str_free(project_name);
  3113. X    project_bind_existing(pp);
  3114. X
  3115. X    /*
  3116. X     * locate user data
  3117. X     */
  3118. X    up = user_executing(pp);
  3119. X
  3120. X    /*
  3121. X     * locate change data
  3122. X     */
  3123. X    if (!change_number)
  3124. X        change_number = user_default_change(up);
  3125. X    cp = change_alloc(pp, change_number);
  3126. X    change_bind_existing(cp);
  3127. X
  3128. X    /*
  3129. X     * lock the change for writing
  3130. X     */
  3131. X    project_pstate_lock_prepare(pp);
  3132. X    change_cstate_lock_prepare(cp);
  3133. X    lock_prepare_ustate_all(); /* we don't know which user until later */
  3134. X    lock_take();
  3135. X    cstate_data = change_cstate_get(cp);
  3136. X    pstate_data = project_pstate_get(pp);
  3137. X
  3138. X    /*
  3139. X     * it is an error if the change is not in the 'being_reviewed' state.
  3140. X     */
  3141. X    if (cstate_data->state != cstate_state_being_reviewed)
  3142. X        change_fatal(cp, "not in 'being_reviewed' state");
  3143. X    if (!project_reviewer_query(pp, user_name(up)))
  3144. X    {
  3145. X        project_fatal
  3146. X        (
  3147. X            pp,
  3148. X            "user \"%S\" is not a reviewer",
  3149. X            user_name(up)
  3150. X        );
  3151. X    }
  3152. X    if
  3153. X    (
  3154. X        !pstate_data->developer_may_review
  3155. X    &&
  3156. X        str_equal(change_developer_name(cp), user_name(up))
  3157. X    )
  3158. X        change_fatal(cp, "developer may not review");
  3159. X
  3160. X    /*
  3161. X     * change the state
  3162. X     * remember who reviewed it
  3163. X     * add to the change's history
  3164. X     */
  3165. X    cstate_data->state = cstate_state_being_developed;
  3166. X    history_data = change_history_new(cp, up);
  3167. X    history_data->what = cstate_history_what_review_fail;
  3168. X    history_data->why = comment;
  3169. X    cstate_data->build_time = 0;
  3170. X    cstate_data->test_time = 0;
  3171. X    cstate_data->test_baseline_time = 0;
  3172. X    cstate_data->regression_test_time = 0;
  3173. X
  3174. X    /*
  3175. X     * add it back into the user's change list
  3176. X     */
  3177. X    devup = user_symbolic(pp, change_developer_name(cp));
  3178. X    user_own_add(devup, project_name_get(pp), change_number);
  3179. X
  3180. X    /*
  3181. X     * Restore write permission to the change files
  3182. X     * and repair the diff time fields.
  3183. X     */
  3184. X    dd = change_development_directory_get(cp, 1);
  3185. X    user_become(devup);
  3186. X    dir_walk(dd, rf_func, cp);
  3187. X    os_become_undo();
  3188. X
  3189. X    /*
  3190. X     * go through the files in the change and unlock them
  3191. X     * in the baseline
  3192. X     */
  3193. X    for (j = 0; j < cstate_data->src->length; ++j)
  3194. X    {
  3195. X        cstate_src    c_src_data;
  3196. X        pstate_src    p_src_data;
  3197. X
  3198. X        c_src_data = cstate_data->src->list[j];
  3199. X        p_src_data = project_src_find(pp, c_src_data->file_name);
  3200. X        if (!p_src_data)
  3201. X            continue;
  3202. X        p_src_data->locked_by = 0;
  3203. X
  3204. X        /*
  3205. X         * Remove the file if it is about_to_be_created
  3206. X         * by the change we are rescinding.
  3207. X         */
  3208. X        if (p_src_data->about_to_be_created_by)
  3209. X        {
  3210. X            assert(p_src_data->about_to_be_created_by == change_number);
  3211. X            project_src_remove(pp, c_src_data->file_name);
  3212. X        }
  3213. X    }
  3214. X
  3215. X    /*
  3216. X     * write out the data and release the locks
  3217. X     */
  3218. X    project_pstate_write(pp);
  3219. X    change_cstate_write(cp);
  3220. X    user_ustate_write(devup);
  3221. X    commit();
  3222. X    lock_release();
  3223. X
  3224. X    /*
  3225. X     * run the notify command
  3226. X     */
  3227. X    change_run_review_fail_notify_command(cp);
  3228. X
  3229. X    /*
  3230. X     * verbose success message
  3231. X     */
  3232. X    change_verbose(cp, "failed review, returned to developer");
  3233. X    change_free(cp);
  3234. X    project_free(pp);
  3235. X    user_free(up);
  3236. X    user_free(devup);
  3237. X    trace((/*{*/"}\n"));
  3238. X}
  3239. X
  3240. X
  3241. Xvoid
  3242. Xreview_fail()
  3243. X{
  3244. X    trace(("review_fail()\n{\n"/*}*/));
  3245. X    switch (arglex())
  3246. X    {
  3247. X    default:
  3248. X        review_fail_main();
  3249. X        break;
  3250. X
  3251. X    case arglex_token_help:
  3252. X        review_fail_help();
  3253. X        break;
  3254. X
  3255. X    case arglex_token_list:
  3256. X        review_fail_list(review_fail_usage);
  3257. X        break;
  3258. X    }
  3259. X    trace((/*{*/"}\n"));
  3260. X}
  3261. END_OF_FILE
  3262. if test 13632 -ne `wc -c <'aegis/aerf.c'`; then
  3263.     echo shar: \"'aegis/aerf.c'\" unpacked with wrong size!
  3264. fi
  3265. # end of 'aegis/aerf.c'
  3266. fi
  3267. if test -f 'aegis/aerm.c' -a "${1}" != "-c" ; then 
  3268.   echo shar: Will not clobber existing file \"'aegis/aerm.c'\"
  3269. else
  3270. echo shar: Extracting \"'aegis/aerm.c'\" \(13356 characters\)
  3271. sed "s/^X//" >'aegis/aerm.c' <<'END_OF_FILE'
  3272. X/*
  3273. X *    aegis - project change supervisor
  3274. X *    Copyright (C) 1991, 1992, 1993 Peter Miller.
  3275. X *    All rights reserved.
  3276. X *
  3277. X *    This program is free software; you can redistribute it and/or modify
  3278. X *    it under the terms of the GNU General Public License as published by
  3279. X *    the Free Software Foundation; either version 2 of the License, or
  3280. X *    (at your option) any later version.
  3281. X *
  3282. X *    This program is distributed in the hope that it will be useful,
  3283. X *    but WITHOUT ANY WARRANTY; without even the implied warranty of
  3284. X *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  3285. X *    GNU General Public License for more details.
  3286. X *
  3287. X *    You should have received a copy of the GNU General Public License
  3288. X *    along with this program; if not, write to the Free Software
  3289. X *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  3290. X *
  3291. X * MANIFEST: functions to implement remove file
  3292. X */
  3293. X
  3294. X#include <stdio.h>
  3295. X#include <stdlib.h>
  3296. X
  3297. X#include <ael.h>
  3298. X#include <aerm.h>
  3299. X#include <arglex2.h>
  3300. X#include <change.h>
  3301. X#include <commit.h>
  3302. X#include <error.h>
  3303. X#include <help.h>
  3304. X#include <lock.h>
  3305. X#include <log.h>
  3306. X#include <option.h>
  3307. X#include <os.h>
  3308. X#include <project.h>
  3309. X#include <trace.h>
  3310. X#include <user.h>
  3311. X#include <word.h>
  3312. X
  3313. X
  3314. X/*
  3315. X * NAME
  3316. X *    remove_file_usage
  3317. X *
  3318. X * SYNOPSIS
  3319. X *    void remove_file_usage(void);
  3320. X *
  3321. X * DESCRIPTION
  3322. X *    The remove_file_usage function is used to
  3323. X *    tell the user how to use the 'aegis -ReMove_file' command.
  3324. X */
  3325. X
  3326. Xstatic void remove_file_usage _((void));
  3327. X
  3328. Xstatic void
  3329. Xremove_file_usage()
  3330. X{
  3331. X    char        *progname;
  3332. X
  3333. X    progname = option_progname_get();
  3334. X    fprintf(stderr, "usage: %s -ReMove_file <filename>... [ <option>... ]\n", progname);
  3335. X    fprintf(stderr, "       %s -ReMove_file -List [ <option>... ]\n", progname);
  3336. X    fprintf(stderr, "       %s -ReMove_file -Help\n", progname);
  3337. X    quit(1);
  3338. X}
  3339. X
  3340. X
  3341. X/*
  3342. X * NAME
  3343. X *    remove_file_help
  3344. X *
  3345. X * SYNOPSIS
  3346. X *    void remove_file_help(void);
  3347. X *
  3348. X * DESCRIPTION
  3349. X *    The remove_file_help function is used to
  3350. X *    describe the 'aegis -ReMove_file' command to the user.
  3351. X */
  3352. X
  3353. Xstatic void remove_file_help _((void));
  3354. X
  3355. Xstatic void
  3356. Xremove_file_help()
  3357. X{
  3358. X    static char *text[] =
  3359. X    {
  3360. X"NAME",
  3361. X"    %s -ReMove_file - add files to be deleted to a chasnge",
  3362. X"",
  3363. X"SYNOPSIS",
  3364. X"    %s -ReMove_file <filename>... [ <option>... ]",
  3365. X"    %s -ReMove_file -List [ <option>... ]",
  3366. X"    %s -ReMove_file -Help",
  3367. X"",
  3368. X"DESCRIPTION",
  3369. X"    The %s -ReMove_file command is used to add files to be",
  3370. X"    deleted to a change.",
  3371. X"",
  3372. X"    The %s program will attempt to intuit the file names",
  3373. X"    intended.  All file names are stored within %s as",
  3374. X"    relative to the root of the baseline directory tree.  The",
  3375. X"    development directory and the integration directory are",
  3376. X"    shadows of the baseline dirdctory, and so these relative",
  3377. X"    names aply there, too.  Files named on the command line",
  3378. X"    are first converted to absolute paths if necessary.  They",
  3379. X"    are then compared with the baseline path, and the",
  3380. X"    development directory path, and the integration directory",
  3381. X"    path, to determine a root-relative name.  It is an error",
  3382. X"    if the file named is outside one of these directory",
  3383. X"    trees.",
  3384. X"",
  3385. X"    The file will be added to the list of files in the",
  3386. X"    change, and will be remoed from the baseline at",
  3387. X"    integration time.",
  3388. X"",
  3389. X"OPTIONS",
  3390. X"    The following options are understood:",
  3391. X"",
  3392. X"    -Change <number>",
  3393. X"        This option may be used to specify a particular",
  3394. X"        change within a project.  When no -Change option is",
  3395. X"        specified, the AEGIS_CHANGE environment variable is",
  3396. X"        consulted.  If that does not exist, the user's",
  3397. X"        $HOME/.aegisrc file is examined for a default change",
  3398. X"        field (see aeuconf(5) for more information).  If",
  3399. X"        that does not exist, when the user is only working",
  3400. X"        on one change within a project, that is the default",
  3401. X"        change number.  Otherwise, it is an error.",
  3402. X"",
  3403. X"    -Help",
  3404. X"        This option may be used to obtain more",
  3405. X"        information about how to use the %s program.",
  3406. X"",
  3407. X"    -List",
  3408. X"        This option may be used to obtain a list of",
  3409. X"        suitable subjects for this command.  The list may",
  3410. X"        be more general than expected.",
  3411. X"",
  3412. X"    -Project <name>",
  3413. X"        This option may be used to select the project of",
  3414. X"        interest.  When no -Project option is specified, the",
  3415. X"        AEGIS_PROJECT environment variable is consulted.  If",
  3416. X"        that does not exist, the user's $HOME/.aegisrc file",
  3417. X"        is examined for a default project field (see",
  3418. X"        aeuconf(5) for more information).  If that does not",
  3419. X"        exist, when the user is only working on changes",
  3420. X"        within a single project, the project name defaults",
  3421. X"        to that project.  Otherwise, it is an error.",
  3422. X"",
  3423. X"    -TERse",
  3424. X"        This option may be used to cause listings to",
  3425. X"        produce the bare minimum of information.  It is",
  3426. X"        usually useful for shell scripts.",
  3427. X"",
  3428. X"    -Verbose",
  3429. X"        This option may be used to cause %s to produce",
  3430. X"        more output.  By default %s only produces",
  3431. X"        output on errors.  When used with the -List",
  3432. X"        option this option causes column headings to be",
  3433. X"        added.",
  3434. X"",
  3435. X"    All options may be abbreviated; the abbreviation is",
  3436. X"    documented as the upper case letters, all lower case",
  3437. X"    letters and underscores (_) are optional.  You must use",
  3438. X"    consecutive sequences of optional letters.",
  3439. X"",
  3440. X"    All options are case insensitive, you may type them in",
  3441. X"    upper case or lower case or a combination of both, case",
  3442. X"    is not important.",
  3443. X"",
  3444. X"    For example: the arguments \"-project, \"-PROJ\" and \"-p\"",
  3445. X"    are all interpreted to mean the -Project option.  The",
  3446. X"    argument \"-prj\" will not be understood, because",
  3447. X"    consecutive optional characters were not supplied.",
  3448. X"",
  3449. X"    Options and other command line arguments may be mixed",
  3450. X"    arbitrarily on the command line, after the function",
  3451. X"    selectors.",
  3452. X"",
  3453. X"    The GNU long option names are understood.  Since all",
  3454. X"    option names for aegis are long, this means ignoring the",
  3455. X"    extra leading '-'.  The \"--option=value\" convention is",
  3456. X"    also understood.",
  3457. X"",
  3458. X"RECOMMENDED ALIAS",
  3459. X"    The recommended alias for this command is",
  3460. X"    csh%%    alias aerm '%s -rm \\!* -v'",
  3461. X"    sh$    aerm(){%s -rm $* -v}",
  3462. X"",
  3463. X"ERRORS",
  3464. X"    It is an error if the change is not in the",
  3465. X"    'being_developed' state.",
  3466. X"    It is an error if the change is not assigned to the",
  3467. X"    current user.",
  3468. X"    It is an error if the filesa does not exist in the",
  3469. X"    baseline.",
  3470. X"    It is an error if the file is already part of the change.",
  3471. X"",
  3472. X"EXIT STATUS",
  3473. X"    The %s command will exit with a status of 1 on any",
  3474. X"    error.  The %s command will only exit with a status of",
  3475. X"    0 if there are no errors.",
  3476. X"",
  3477. X"COPYRIGHT",
  3478. X"    %C",
  3479. X"",
  3480. X"AUTHOR",
  3481. X"    %A",
  3482. X    };
  3483. X
  3484. X    help(text, SIZEOF(text), remove_file_usage);
  3485. X}
  3486. X
  3487. X
  3488. X/*
  3489. X * NAME
  3490. X *    remove_file_list
  3491. X *
  3492. X * SYNOPSIS
  3493. X *    void remove_file_list(void);
  3494. X *
  3495. X * DESCRIPTION
  3496. X *    The remove_file_list function is used to
  3497. X *    list the file the user may wish to add to the change
  3498. X *    as a deletion.  All project files are listed.
  3499. X */
  3500. X
  3501. Xstatic void remove_file_list _((void));
  3502. X
  3503. Xstatic void
  3504. Xremove_file_list()
  3505. X{
  3506. X    string_ty    *project_name;
  3507. X    long        change_number;
  3508. X
  3509. X    trace(("remove_file_list()\n{\n"/*}*/));
  3510. X    project_name = 0;
  3511. X    change_number = 0;
  3512. X    arglex();
  3513. X    while (arglex_token != arglex_token_eoln)
  3514. X    {
  3515. X        switch (arglex_token)
  3516. X        {
  3517. X        default:
  3518. X            generic_argument(remove_file_usage);
  3519. X            continue;
  3520. X
  3521. X        case arglex_token_change:
  3522. X            if (arglex() != arglex_token_number)
  3523. X                remove_file_usage();
  3524. X            /* fall through... */
  3525. X
  3526. X        case arglex_token_number:
  3527. X            if (change_number)
  3528. X                fatal("duplicate -Change option");
  3529. X            change_number = arglex_value.alv_number;
  3530. X            if (change_number < 1)
  3531. X                fatal("change %ld out of range", change_number);
  3532. X            break;
  3533. X
  3534. X        case arglex_token_project:
  3535. X            if (arglex() != arglex_token_string)
  3536. X                remove_file_usage();
  3537. X            if (project_name)
  3538. X                fatal("duplicate -Project option");
  3539. X            project_name = str_from_c(arglex_value.alv_string);
  3540. X            break;
  3541. X        }
  3542. X        arglex();
  3543. X    }
  3544. X    list_project_files(project_name, change_number);
  3545. X    if (project_name)
  3546. X        str_free(project_name);
  3547. X    trace((/*{*/"}\n"));
  3548. X}
  3549. X
  3550. X
  3551. X/*
  3552. X * NAME
  3553. X *    remove_file_main
  3554. X *
  3555. X * SYNOPSIS
  3556. X *    void remove_file_main(void);
  3557. X *
  3558. X * DESCRIPTION
  3559. X *    The remove_file_main function is used to
  3560. X *    add a file to a change as a deletion.
  3561. X *    The file will be deleted from the baseline on successful
  3562. X *    integration of the change.
  3563. X *
  3564. X *    The names of the relevant files are gleaned from the command line.
  3565. X */
  3566. X
  3567. Xstatic void remove_file_main _((void));
  3568. X
  3569. Xstatic void
  3570. Xremove_file_main()
  3571. X{
  3572. X    wlist        wl;
  3573. X    string_ty    *s1;
  3574. X    string_ty    *s2;
  3575. X    cstate        cstate_data;
  3576. X    cstate_src    c_src_data;
  3577. X    pstate_src    p_src_data;
  3578. X    int        j;
  3579. X    pconf        pconf_data;
  3580. X    pstate        pstate_data;
  3581. X    string_ty    *project_name;
  3582. X    project_ty    *pp;
  3583. X    long        change_number;
  3584. X    change_ty    *cp;
  3585. X    int        nolog;
  3586. X    user_ty        *up;
  3587. X    string_ty    *dd;
  3588. X    string_ty    *bl;
  3589. X
  3590. X    trace(("remove_file_main()\n{\n"/*}*/));
  3591. X    project_name = 0;
  3592. X    change_number = 0;
  3593. X    wl_zero(&wl);
  3594. X    nolog = 0;
  3595. X    while (arglex_token != arglex_token_eoln)
  3596. X    {
  3597. X        switch (arglex_token)
  3598. X        {
  3599. X        default:
  3600. X            generic_argument(remove_file_usage);
  3601. X            continue;
  3602. X
  3603. X        case arglex_token_string:
  3604. X            s1 = str_from_c(arglex_value.alv_string);
  3605. X            os_become_orig();
  3606. X            s2 = os_pathname(s1, 1);
  3607. X            os_become_undo();
  3608. X            if (wl_member(&wl, s2))
  3609. X                fatal("file \"%s\" named more than once", arglex_value.alv_string);
  3610. X            wl_append(&wl, s2);
  3611. X            str_free(s2);
  3612. X            str_free(s1);
  3613. X            break;
  3614. X
  3615. X        case arglex_token_change:
  3616. X            if (arglex() != arglex_token_number)
  3617. X                remove_file_usage();
  3618. X            /* fall through... */
  3619. X
  3620. X        case arglex_token_number:
  3621. X            if (change_number)
  3622. X                fatal("duplicate -Change option");
  3623. X            change_number = arglex_value.alv_number;
  3624. X            if (change_number < 1)
  3625. X                fatal("change %ld out of range", change_number);
  3626. X            break;
  3627. X
  3628. X        case arglex_token_project:
  3629. X            if (arglex() != arglex_token_string)
  3630. X                remove_file_usage();
  3631. X            if (project_name)
  3632. X                fatal("duplicate -Project option");
  3633. X            project_name = str_from_c(arglex_value.alv_string);
  3634. X            break;
  3635. X
  3636. X        case arglex_token_nolog:
  3637. X            if (nolog)
  3638. X                fatal("duplicate %s option", arglex_value.alv_string);
  3639. X            nolog = 1;
  3640. X            break;
  3641. X        }
  3642. X        arglex();
  3643. X    }
  3644. X    if (!wl.wl_nwords)
  3645. X        fatal("no files specified");
  3646. X
  3647. X    /*
  3648. X     * locate project data
  3649. X     */
  3650. X    if (!project_name)
  3651. X        project_name = user_default_project();
  3652. X    pp = project_alloc(project_name);
  3653. X    str_free(project_name);
  3654. X    project_bind_existing(pp);
  3655. X
  3656. X    /*
  3657. X     * locate user data
  3658. X     */
  3659. X    up = user_executing(pp);
  3660. X
  3661. X    /*
  3662. X     * locate change data
  3663. X     */
  3664. X    if (!change_number)
  3665. X        change_number = user_default_change(up);
  3666. X    cp = change_alloc(pp, change_number);
  3667. X    change_bind_existing(cp);
  3668. X
  3669. X    /*
  3670. X     * take the locks and read the change state
  3671. X     */
  3672. X    change_cstate_lock_prepare(cp);
  3673. X    lock_take();
  3674. X    cstate_data = change_cstate_get(cp);
  3675. X    pconf_data = change_pconf_get(cp);
  3676. X    pstate_data = project_pstate_get(pp);
  3677. X
  3678. X    /*
  3679. X     * It is an error if the change is not in the in_development state.
  3680. X     * It is an error if the change is not assigned to the current user.
  3681. X     */
  3682. X    if (cstate_data->state != cstate_state_being_developed)
  3683. X        change_fatal(cp, "not in 'being_developed' state");
  3684. X    if (!str_equal(change_developer_name(cp), user_name(up)))
  3685. X    {
  3686. X        change_fatal
  3687. X        (
  3688. X            cp,
  3689. X            "user \"%S\" is not the developer",
  3690. X            user_name(up)
  3691. X        );
  3692. X    }
  3693. X
  3694. X    /*
  3695. X     * resolve the path of each file
  3696. X     * 1.    the absolute path of the file name is obtained
  3697. X     * 2.    if the file is inside the development directory, ok
  3698. X     * 3.    if the file is inside the baseline, ok
  3699. X     * 4.    if neither, error
  3700. X     */
  3701. X    dd = change_development_directory_get(cp, 1);
  3702. X    bl = project_baseline_path_get(pp, 1);
  3703. X    for (j = 0; j < wl.wl_nwords; ++j)
  3704. X    {
  3705. X        s1 = wl.wl_word[j];
  3706. X        assert(s1->str_text[0] == '/');
  3707. X        s2 = os_below_dir(dd, s1);
  3708. X        if (!s2)
  3709. X            s2 = os_below_dir(bl, s1);
  3710. X        if (!s2)
  3711. X            change_fatal(cp, "path \"%S\" unrelated", s1);
  3712. X        str_free(s1);
  3713. X        wl.wl_word[j] = s2;
  3714. X    }
  3715. X
  3716. X    /*
  3717. X     * ensure that each file
  3718. X     * 1. is not already part of the change
  3719. X     * 2. is in the baseline
  3720. X     * add it to the change
  3721. X     */
  3722. X    for (j = 0; j < wl.wl_nwords; ++j)
  3723. X    {
  3724. X        s1 = wl.wl_word[j];
  3725. X        if (change_src_find(cp, s1))
  3726. X            change_fatal(cp, "file \"%S\" already in change", s1);
  3727. X        p_src_data = project_src_find(pp, s1);
  3728. X        if (!p_src_data || p_src_data->deleted_by)
  3729. X            project_fatal(pp, "file \"%S\" does not exist", s1);
  3730. X        c_src_data = change_src_new(cp);
  3731. X        c_src_data->file_name = str_copy(s1);
  3732. X        c_src_data->action = file_action_remove;
  3733. X        c_src_data->usage = p_src_data->usage;
  3734. X        c_src_data->edit_number = str_copy(p_src_data->edit_number);
  3735. X    }
  3736. X
  3737. X    /*
  3738. X     * the number of files changed, or the version did,
  3739. X     * so stomp on the validation fields.
  3740. X     */
  3741. X    cstate_data->build_time = 0;
  3742. X    cstate_data->test_time = 0;
  3743. X    cstate_data->test_baseline_time = 0;
  3744. X    cstate_data->regression_test_time = 0;
  3745. X
  3746. X    /*
  3747. X     * write the data and release the lock
  3748. X     */
  3749. X    change_cstate_write(cp);
  3750. X    commit();
  3751. X    lock_release();
  3752. X
  3753. X    /*
  3754. X     * run the change file command
  3755. X     */
  3756. X    if (!nolog)
  3757. X        log_open(change_logfile_get(cp), up);
  3758. X    change_run_change_file_command(cp, &wl, up);
  3759. X
  3760. X    /*
  3761. X     * verbose success message
  3762. X     */
  3763. X    for (j = 0; j < wl.wl_nwords; ++j)
  3764. X        change_verbose(cp, "file \"%S\" remove file", wl.wl_word[j]);
  3765. X    wl_free(&wl);
  3766. X    change_free(cp);
  3767. X    project_free(pp);
  3768. X    user_free(up);
  3769. X    trace((/*{*/"}\n"));
  3770. X}
  3771. X
  3772. X
  3773. X/*
  3774. X * NAME
  3775. X *    remove_file
  3776. X *
  3777. X * SYNOPSIS
  3778. X *    void remove_file(void);
  3779. X *
  3780. X * DESCRIPTION
  3781. X *    The remove_file function is used to
  3782. X *    dispatch the 'aegis -ReMove_file' command to the relevant
  3783. X *    function to do it's work.
  3784. X */
  3785. X
  3786. Xvoid
  3787. Xremove_file()
  3788. X{
  3789. X    trace(("remove_file()\n{\n"/*}*/));
  3790. X    switch (arglex())
  3791. X    {
  3792. X    default:
  3793. X        remove_file_main();
  3794. X        break;
  3795. X
  3796. X    case arglex_token_help:
  3797. X        remove_file_help();
  3798. X        break;
  3799. X
  3800. X    case arglex_token_list:
  3801. X        remove_file_list();
  3802. X        break;
  3803. X    }
  3804. X    trace((/*{*/"}\n"));
  3805. X}
  3806. END_OF_FILE
  3807. if test 13356 -ne `wc -c <'aegis/aerm.c'`; then
  3808.     echo shar: \"'aegis/aerm.c'\" unpacked with wrong size!
  3809. fi
  3810. # end of 'aegis/aerm.c'
  3811. fi
  3812. if test -f 'aegis/aermu.c' -a "${1}" != "-c" ; then 
  3813.   echo shar: Will not clobber existing file \"'aegis/aermu.c'\"
  3814. else
  3815. echo shar: Extracting \"'aegis/aermu.c'\" \(13459 characters\)
  3816. sed "s/^X//" >'aegis/aermu.c' <<'END_OF_FILE'
  3817. X/*
  3818. X *    aegis - project change supervisor
  3819. X *    Copyright (C) 1991, 1992, 1993 Peter Miller.
  3820. X *    All rights reserved.
  3821. X *
  3822. X *    This program is free software; you can redistribute it and/or modify
  3823. X *    it under the terms of the GNU General Public License as published by
  3824. X *    the Free Software Foundation; either version 2 of the License, or
  3825. X *    (at your option) any later version.
  3826. X *
  3827. X *    This program is distributed in the hope that it will be useful,
  3828. X *    but WITHOUT ANY WARRANTY; without even the implied warranty of
  3829. X *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  3830. X *    GNU General Public License for more details.
  3831. X *
  3832. X *    You should have received a copy of the GNU General Public License
  3833. X *    along with this program; if not, write to the Free Software
  3834. X *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  3835. X *
  3836. X * MANIFEST: functions to implement remove file undo
  3837. X */
  3838. X
  3839. X#include <stdio.h>
  3840. X#include <stdlib.h>
  3841. X
  3842. X#include <ael.h>
  3843. X#include <aermu.h>
  3844. X#include <arglex2.h>
  3845. X#include <change.h>
  3846. X#include <commit.h>
  3847. X#include <error.h>
  3848. X#include <help.h>
  3849. X#include <lock.h>
  3850. X#include <log.h>
  3851. X#include <option.h>
  3852. X#include <os.h>
  3853. X#include <project.h>
  3854. X#include <trace.h>
  3855. X#include <user.h>
  3856. X#include <word.h>
  3857. X
  3858. X
  3859. X/*
  3860. X * NAME
  3861. X *    remove_file_undo_usage
  3862. X *
  3863. X * SYNOPSIS
  3864. X *    void remove_file_undo_usage(void);
  3865. X *
  3866. X * DESCRIPTION
  3867. X *    The remove_file_undo_usage function is used to
  3868. X *    tell the user how to use the 'aegis -ReMove_file_Undo' command.
  3869. X */
  3870. X
  3871. Xstatic void remove_file_undo_usage _((void));
  3872. X
  3873. Xstatic void
  3874. Xremove_file_undo_usage()
  3875. X{
  3876. X    char        *progname;
  3877. X
  3878. X    progname = option_progname_get();
  3879. X    fprintf(stderr, "usage: %s -ReMove_file_Undo <filename>... [ <option>... ]\n", progname);
  3880. X    fprintf(stderr, "       %s -ReMove_file_Undo -List [ <option>... ]\n", progname);
  3881. X    fprintf(stderr, "       %s -ReMove_file_Undo -Help\n", progname);
  3882. X    quit(1);
  3883. X}
  3884. X
  3885. X
  3886. X/*
  3887. X * NAME
  3888. X *    remove_file_undo_help
  3889. X *
  3890. X * SYNOPSIS
  3891. X *    void remove_file_undo_help(void);
  3892. X *
  3893. X * DESCRIPTION
  3894. X *    The remove_file_undo_help function is used to
  3895. X *    describe the 'aegis -ReMove_file_undo' command to the user.
  3896. X */
  3897. X
  3898. Xstatic void remove_file_undo_help _((void));
  3899. X
  3900. Xstatic void
  3901. Xremove_file_undo_help()
  3902. X{
  3903. X    static char *text[] =
  3904. X    {
  3905. X"NAME",
  3906. X"    %s -ReMove_file_Undo - remove files to be deleted from",
  3907. X"    a change.",
  3908. X"",
  3909. X"SYNOPSIS",
  3910. X"    %s -ReMove_file_Undo <filename>... [ <option>... ]",
  3911. X"    %s -ReMove_file_Undo -List [ <option>... ]",
  3912. X"    %s -ReMove_file_Undo -Help",
  3913. X"",
  3914. X"DESCRIPTION",
  3915. X"    The %s -ReMove_file_Undo command is used to remove",
  3916. X"    filesa to be deleted from a change.",
  3917. X"",
  3918. X"    The %s program will attempt to intuit the file names",
  3919. X"    intended.  All file names are stored within %s as",
  3920. X"    relative to the root of the baseline directory tree.  The",
  3921. X"    development directory and the integration directory are",
  3922. X"    shadows of the baseline dirdctory, and so these relative",
  3923. X"    names aply there, too.  Files named on the command line",
  3924. X"    are first converted to absolute paths if necessary.  They",
  3925. X"    are then compared with the baseline path, and the",
  3926. X"    development directory path, and the integration directory",
  3927. X"    path, to determine a root-relative name.  It is an error",
  3928. X"    if the file named is outside one of these directory",
  3929. X"    trees.",
  3930. X"",
  3931. X"    The files is removed from the list of files in the",
  3932. X"    change.",
  3933. X"",
  3934. X"OPTIONS",
  3935. X"    The following options are understood:",
  3936. X"",
  3937. X"    -Change <number>",
  3938. X"        This option may be used to specify a particular",
  3939. X"        change within a project.  When no -Change option is",
  3940. X"        specified, the AEGIS_CHANGE environment variable is",
  3941. X"        consulted.  If that does not exist, the user's",
  3942. X"        $HOME/.aegisrc file is examined for a default change",
  3943. X"        field (see aeuconf(5) for more information).  If",
  3944. X"        that does not exist, when the user is only working",
  3945. X"        on one change within a project, that is the default",
  3946. X"        change number.  Otherwise, it is an error.",
  3947. X"",
  3948. X"    -Help",
  3949. X"        This option may be used to obtain more",
  3950. X"        information about how to use the %s program.",
  3951. X"",
  3952. X"    -List",
  3953. X"        This option may be used to obtain a list of",
  3954. X"        suitable subjects for this command.  The list may",
  3955. X"        be more general than expected.",
  3956. X"",
  3957. X"    -Project <name>",
  3958. X"        This option may be used to select the project of",
  3959. X"        interest.  When no -Project option is specified, the",
  3960. X"        AEGIS_PROJECT environment variable is consulted.  If",
  3961. X"        that does not exist, the user's $HOME/.aegisrc file",
  3962. X"        is examined for a default project field (see",
  3963. X"        aeuconf(5) for more information).  If that does not",
  3964. X"        exist, when the user is only working on changes",
  3965. X"        within a single project, the project name defaults",
  3966. X"        to that project.  Otherwise, it is an error.",
  3967. X"",
  3968. X"    -TERse",
  3969. X"        This option may be used to cause listings to",
  3970. X"        produce the bare minimum of information.  It is",
  3971. X"        usually useful for shell scripts.",
  3972. X"",
  3973. X"    -Verbose",
  3974. X"        This option may be used to cause %s to produce",
  3975. X"        more output.  By default %s only produces",
  3976. X"        output on errors.  When used with the -List",
  3977. X"        option this option causes column headings to be",
  3978. X"        added.",
  3979. X"",
  3980. X"    All options may be abbreviated; the abbreviation is",
  3981. X"    documented as the upper case letters, all lower case",
  3982. X"    letters and underscores (_) are optional.  You must use",
  3983. X"    consecutive sequences of optional letters.",
  3984. X"",
  3985. X"    All options are case insensitive, you may type them in",
  3986. X"    upper case or lower case or a combination of both, case",
  3987. X"    is not important.",
  3988. X"",
  3989. X"    For example: the arguments \"-project, \"-PROJ\" and \"-p\"",
  3990. X"    are all interpreted to mean the -Project option.  The",
  3991. X"    argument \"-prj\" will not be understood, because",
  3992. X"    consecutive optional characters were not supplied.",
  3993. X"",
  3994. X"    Options and other command line arguments may be mixed",
  3995. X"    arbitrarily on the command line, after the function",
  3996. X"    selectors.",
  3997. X"",
  3998. X"    The GNU long option names are understood.  Since all",
  3999. X"    option names for aegis are long, this means ignoring the",
  4000. X"    extra leading '-'.  The \"--option=value\" convention is",
  4001. X"    also understood.",
  4002. X"",
  4003. X"RECOMMENDED ALIAS",
  4004. X"    The recommended alias for this command is",
  4005. X"    csh%%    alias aermu '%s -rmu \\!* -v'",
  4006. X"    sh$    aermu(){%s -rmu $* -v}",
  4007. X"",
  4008. X"ERRORS",
  4009. X"    It is an error if the change is not in the",
  4010. X"    'being_developed' state.",
  4011. X"    It is an error if the change is not assigned to the",
  4012. X"    current user.",
  4013. X"    It is an error if the file is not in the change.",
  4014. X"    It is an error if the was not added to the change using",
  4015. X"    the %s -ReMove_file command.",
  4016. X"",
  4017. X"EXIT STATUS",
  4018. X"    The %s command will exit with a status of 1 on any",
  4019. X"    error.  The %s command will only exit with a status of",
  4020. X"    0 if there are no errors.",
  4021. X"",
  4022. X"COPYRIGHT",
  4023. X"    %C",
  4024. X"",
  4025. X"AUTHOR",
  4026. X"    %A",
  4027. X    };
  4028. X
  4029. X    help(text, SIZEOF(text), remove_file_undo_usage);
  4030. X}
  4031. X
  4032. X
  4033. X/*
  4034. X * NAME
  4035. X *    remove_file_undo_list
  4036. X *
  4037. X * SYNOPSIS
  4038. X *    void remove_file_undo_list(void);
  4039. X *
  4040. X * DESCRIPTION
  4041. X *    The remove_file_undo_list function is used to
  4042. X *    list the file the user may wish to remove from the change
  4043. X *    as a deletion.  All relevant change files are listed.
  4044. X */
  4045. X
  4046. Xstatic void remove_file_undo_list _((void));
  4047. X
  4048. Xstatic void
  4049. Xremove_file_undo_list()
  4050. X{
  4051. X    string_ty    *project_name;
  4052. X    long        change_number;
  4053. X
  4054. X    trace(("remove_file_undo_list()\n{\n"/*}*/));
  4055. X    project_name = 0;
  4056. X    change_number = 0;
  4057. X    arglex();
  4058. X    while (arglex_token != arglex_token_eoln)
  4059. X    {
  4060. X        switch (arglex_token)
  4061. X        {
  4062. X        default:
  4063. X            generic_argument(remove_file_undo_usage);
  4064. X            continue;
  4065. X
  4066. X        case arglex_token_change:
  4067. X            if (arglex() != arglex_token_number)
  4068. X                remove_file_undo_usage();
  4069. X            /* fall through... */
  4070. X
  4071. X        case arglex_token_number:
  4072. X            if (change_number)
  4073. X                fatal("duplicate -Change option");
  4074. X            change_number = arglex_value.alv_number;
  4075. X            if (change_number < 1)
  4076. X                fatal("change %ld out of range", change_number);
  4077. X            break;
  4078. X
  4079. X        case arglex_token_project:
  4080. X            if (arglex() != arglex_token_string)
  4081. X                remove_file_undo_usage();
  4082. X            if (project_name)
  4083. X                fatal("duplicate -Project option");
  4084. X            project_name = str_from_c(arglex_value.alv_string);
  4085. X            break;
  4086. X        }
  4087. X        arglex();
  4088. X    }
  4089. X    list_change_files(project_name, change_number);
  4090. X    if (project_name)
  4091. X        str_free(project_name);
  4092. X    trace((/*{*/"}\n"));
  4093. X}
  4094. X
  4095. X
  4096. X/*
  4097. X * NAME
  4098. X *    remove_undo_main
  4099. X *
  4100. X * SYNOPSIS
  4101. X *    void remove_undo_main(void);
  4102. X *
  4103. X * DESCRIPTION
  4104. X *    The remove_undo_main function is used to
  4105. X *    remove a file from a change as a deletion.
  4106. X *
  4107. X *    The names of the relevant files are gleaned from the command line.
  4108. X */
  4109. X
  4110. Xstatic void remove_file_undo_main _((void));
  4111. X
  4112. Xstatic void
  4113. Xremove_file_undo_main()
  4114. X{
  4115. X    wlist        wl;
  4116. X    string_ty    *s1;
  4117. X    string_ty    *s2;
  4118. X    int        j;
  4119. X    cstate        cstate_data;
  4120. X    pconf        pconf_data;
  4121. X    pstate        pstate_data;
  4122. X    string_ty    *project_name;
  4123. X    project_ty    *pp;
  4124. X    long        change_number;
  4125. X    change_ty    *cp;
  4126. X    int        nolog;
  4127. X    user_ty        *up;
  4128. X    string_ty    *dd;
  4129. X    string_ty    *bl;
  4130. X
  4131. X    trace(("remove_file_undo_main()\n{\n"/*}*/));
  4132. X    project_name = 0;
  4133. X    change_number = 0;
  4134. X    wl_zero(&wl);
  4135. X    nolog = 0;
  4136. X    while (arglex_token != arglex_token_eoln)
  4137. X    {
  4138. X        switch (arglex_token)
  4139. X        {
  4140. X        default:
  4141. X            generic_argument(remove_file_undo_usage);
  4142. X            continue;
  4143. X
  4144. X        case arglex_token_string:
  4145. X            s1 = str_from_c(arglex_value.alv_string);
  4146. X            os_become_orig();
  4147. X            s2 = os_pathname(s1, 1);
  4148. X            os_become_undo();
  4149. X            if (wl_member(&wl, s2))
  4150. X                fatal("file \"%s\" named more than once", arglex_value.alv_string);
  4151. X            wl_append(&wl, s2);
  4152. X            str_free(s2);
  4153. X            str_free(s1);
  4154. X            break;
  4155. X
  4156. X        case arglex_token_change:
  4157. X            if (arglex() != arglex_token_number)
  4158. X                remove_file_undo_usage();
  4159. X            /* fall through... */
  4160. X
  4161. X        case arglex_token_number:
  4162. X            if (change_number)
  4163. X                fatal("duplicate -Change option");
  4164. X            change_number = arglex_value.alv_number;
  4165. X            if (change_number < 1)
  4166. X                fatal("change %ld out of range", change_number);
  4167. X            break;
  4168. X
  4169. X        case arglex_token_project:
  4170. X            if (arglex() != arglex_token_string)
  4171. X                remove_file_undo_usage();
  4172. X            if (project_name)
  4173. X                fatal("duplicate -Project option");
  4174. X            project_name = str_from_c(arglex_value.alv_string);
  4175. X            break;
  4176. X
  4177. X        case arglex_token_nolog:
  4178. X            if (nolog)
  4179. X                fatal("duplicate %s option", arglex_value.alv_string);
  4180. X            nolog = 1;
  4181. X            break;
  4182. X        }
  4183. X        arglex();
  4184. X    }
  4185. X    if (!wl.wl_nwords)
  4186. X        fatal("no files specified");
  4187. X
  4188. X    /*
  4189. X     * locate project data
  4190. X     */
  4191. X    if (!project_name)
  4192. X        project_name = user_default_project();
  4193. X    pp = project_alloc(project_name);
  4194. X    str_free(project_name);
  4195. X    project_bind_existing(pp);
  4196. X
  4197. X    /*
  4198. X     * locate user data
  4199. X     */
  4200. X    up = user_executing(pp);
  4201. X
  4202. X    /*
  4203. X     * locate change data
  4204. X     */
  4205. X    if (!change_number)
  4206. X        change_number = user_default_change(up);
  4207. X    cp = change_alloc(pp, change_number);
  4208. X    change_bind_existing(cp);
  4209. X
  4210. X    /*
  4211. X     * take the locks and read the change state
  4212. X     */
  4213. X    change_cstate_lock_prepare(cp);
  4214. X    lock_take();
  4215. X    pstate_data = project_pstate_get(pp);
  4216. X    cstate_data = change_cstate_get(cp);
  4217. X    pconf_data = change_pconf_get(cp);
  4218. X
  4219. X    /*
  4220. X     * It is an error if the change is not in the in_development state.
  4221. X     * It is an error if the change is not assigned to the current user.
  4222. X     */
  4223. X    if (cstate_data->state != cstate_state_being_developed)
  4224. X        change_fatal(cp, "not in 'being_developed' state");
  4225. X    if (!str_equal(change_developer_name(cp), user_name(up)))
  4226. X    {
  4227. X        change_fatal
  4228. X        (
  4229. X            cp,
  4230. X            "user \"%S\" is not the developer",
  4231. X            user_name(up)
  4232. X        );
  4233. X    }
  4234. X
  4235. X    /*
  4236. X     * resolve the path of each file
  4237. X     * 1.    the absolute path of the file name is obtained
  4238. X     * 2.    if the file is inside the development directory, ok
  4239. X     * 3.    if the file is inside the baseline, ok
  4240. X     * 4.    if neither, error
  4241. X     */
  4242. X    dd = change_development_directory_get(cp, 1);
  4243. X    bl = project_baseline_path_get(pp, 1);
  4244. X    for (j = 0; j < wl.wl_nwords; ++j)
  4245. X    {
  4246. X        s1 = wl.wl_word[j];
  4247. X        assert(s1->str_text[0] == '/');
  4248. X        s2 = os_below_dir(dd, s1);
  4249. X        if (!s2)
  4250. X            s2 = os_below_dir(bl, s1);
  4251. X        if (!s2)
  4252. X            change_fatal(cp, "path \"%S\" unrelated", s1);
  4253. X        str_free(s1);
  4254. X        wl.wl_word[j] = s2;
  4255. X    }
  4256. X
  4257. X    /*
  4258. X     * ensure that each file is part of the change
  4259. X     */
  4260. X    for (j = 0; j < wl.wl_nwords; ++j)
  4261. X    {
  4262. X        cstate_src    c_src_data;
  4263. X
  4264. X        s1 = wl.wl_word[j];
  4265. X        c_src_data = change_src_find(cp, s1);
  4266. X        if (!c_src_data)
  4267. X            change_fatal(cp, "file \"%S\" not in change", s1);
  4268. X        if (c_src_data->action != file_action_remove)
  4269. X            change_fatal(cp, "file \"%S\" not -ReMove_file", s1);
  4270. X        change_src_remove(cp, s1);
  4271. X    }
  4272. X
  4273. X    /*
  4274. X     * Remove the difference files,
  4275. X     * if they exist.
  4276. X     */
  4277. X    user_become(up);
  4278. X    for (j = 0; j < wl.wl_nwords; ++j)
  4279. X    {
  4280. X        s1 = wl.wl_word[j];
  4281. X        s2 = str_format("%S/%S,D", dd, s1);
  4282. X        if (os_exists(s2))
  4283. X            commit_unlink_errok(s2);
  4284. X        str_free(s2);
  4285. X    }
  4286. X    os_become_undo();
  4287. X
  4288. X    /*
  4289. X     * the number of files changed, or the version did,
  4290. X     * so stomp on the validation fields.
  4291. X     */
  4292. X    cstate_data->build_time = 0;
  4293. X    cstate_data->test_time = 0;
  4294. X    cstate_data->test_baseline_time = 0;
  4295. X    cstate_data->regression_test_time = 0;
  4296. X
  4297. X    /*
  4298. X     * write the data and release the lock
  4299. X     */
  4300. X    change_cstate_write(cp);
  4301. X    commit();
  4302. X    lock_release();
  4303. X
  4304. X    /*
  4305. X     * run the change file command
  4306. X     */
  4307. X    if (!nolog)
  4308. X        log_open(change_logfile_get(cp), up);
  4309. X    change_run_change_file_command(cp, &wl, up);
  4310. X
  4311. X    /*
  4312. X     * verbose success message
  4313. X     */
  4314. X    for (j = 0; j < wl.wl_nwords; ++j)
  4315. X        change_verbose(cp, "file \"%S\" remove file undo", wl.wl_word[j]);
  4316. X    wl_free(&wl);
  4317. X    change_free(cp);
  4318. X    project_free(pp);
  4319. X    user_free(up);
  4320. X    trace((/*{*/"}\n"));
  4321. X}
  4322. X
  4323. X
  4324. X/*
  4325. X * NAME
  4326. X *    remove_file_undo
  4327. X *
  4328. X * SYNOPSIS
  4329. X *    void remove_file_undo(void);
  4330. X *
  4331. X * DESCRIPTION
  4332. X *    The remove_file_undo function is used to
  4333. X *    dispatch the 'aegis -ReMove_file_Undo' command to the relevant
  4334. X *    function to do it's work.
  4335. X */
  4336. X
  4337. Xvoid
  4338. Xremove_file_undo()
  4339. X{
  4340. X    trace(("remove_file_undo()\n{\n"/*}*/));
  4341. X    switch (arglex())
  4342. X    {
  4343. X    default:
  4344. X        remove_file_undo_main();
  4345. X        break;
  4346. X
  4347. X    case arglex_token_help:
  4348. X        remove_file_undo_help();
  4349. X        break;
  4350. X
  4351. X    case arglex_token_list:
  4352. X        remove_file_undo_list();
  4353. X        break;
  4354. X    }
  4355. X    trace((/*{*/"}\n"));
  4356. X}
  4357. END_OF_FILE
  4358. if test 13459 -ne `wc -c <'aegis/aermu.c'`; then
  4359.     echo shar: \"'aegis/aermu.c'\" unpacked with wrong size!
  4360. fi
  4361. # end of 'aegis/aermu.c'
  4362. fi
  4363. if test -f 'aegis/lock.c' -a "${1}" != "-c" ; then 
  4364.   echo shar: Will not clobber existing file \"'aegis/lock.c'\"
  4365. else
  4366. echo shar: Extracting \"'aegis/lock.c'\" \(14304 characters\)
  4367. sed "s/^X//" >'aegis/lock.c' <<'END_OF_FILE'
  4368. X/*
  4369. X *    aegis - project change supervisor
  4370. X *    Copyright (C) 1991, 1992, 1993 Peter Miller.
  4371. X *    All rights reserved.
  4372. X *
  4373. X *    This program is free software; you can redistribute it and/or modify
  4374. X *    it under the terms of the GNU General Public License as published by
  4375. X *    the Free Software Foundation; either version 2 of the License, or
  4376. X *    (at your option) any later version.
  4377. X *
  4378. X *    This program is distributed in the hope that it will be useful,
  4379. X *    but WITHOUT ANY WARRANTY; without even the implied warranty of
  4380. X *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  4381. X *    GNU General Public License for more details.
  4382. X *
  4383. X *    You should have received a copy of the GNU General Public License
  4384. X *    along with this program; if not, write to the Free Software
  4385. X *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  4386. X *
  4387. X * MANIFEST: functions to lock aegis' data
  4388. X */
  4389. X
  4390. X#include <errno.h>
  4391. X#include <fcntl.h>
  4392. X#include <stdio.h>
  4393. X#include <unistd.h>
  4394. X#include <string.h>
  4395. X#include <signal.h>
  4396. X
  4397. X#include <error.h>
  4398. X#include <glue.h>
  4399. X#include <gonzo.h>
  4400. X#include <lock.h>
  4401. X#include <mem.h>
  4402. X#include <os.h>
  4403. X#include <trace.h>
  4404. X
  4405. X
  4406. X/*
  4407. X * how many bits of the hash to use in the mux
  4408. X */
  4409. X#define BITS 16
  4410. X#define BITS_SIZE (1L << BITS)
  4411. X#define BITS_MASK (BITS_SIZE - 1)
  4412. X
  4413. Xenum lock_ty
  4414. X{
  4415. X    lock_master,
  4416. X    lock_gstate,
  4417. X    lock_MAX
  4418. X};
  4419. Xtypedef enum lock_ty lock_ty;
  4420. X
  4421. Xenum lock_mux_ty
  4422. X{
  4423. X    lock_mux_ustate,
  4424. X    lock_mux_pstate,
  4425. X    lock_mux_cstate,
  4426. X    lock_mux_build,
  4427. X    lock_mux_MAX
  4428. X};
  4429. Xtypedef enum lock_mux_ty lock_mux_ty;
  4430. X
  4431. X
  4432. Xstatic    string_ty    *path;
  4433. Xstatic    size_t        nplaces;
  4434. Xstatic    struct flock    *place;
  4435. Xstatic    int        fd = -1;
  4436. Xstatic    long        magic;
  4437. Xstatic    int         quitregd;
  4438. X
  4439. X
  4440. Xstatic void flock_construct _((struct flock *, int type, long start,
  4441. X    long length));
  4442. X
  4443. Xstatic void
  4444. Xflock_construct(p, type, start, length)
  4445. X    struct flock    *p;
  4446. X    int        type;
  4447. X    long        start;
  4448. X    long        length;
  4449. X{
  4450. X    /*
  4451. X     * the memset is here because some systems have
  4452. X     * extra fields in the flock structure.
  4453. X     * These fields are frequently undocumented,
  4454. X     * and yet these systems give "EINVAL" if the
  4455. X     * undocumented fields are not zero!
  4456. X     */
  4457. X    memset(p, 0, sizeof(*p));
  4458. X
  4459. X    assert(start >= 0);
  4460. X    assert(length > 0);
  4461. X    p->l_type = type;
  4462. X    p->l_whence = SEEK_SET;
  4463. X    p->l_start = start;
  4464. X    p->l_len = length;
  4465. X    p->l_pid = 0;
  4466. X}
  4467. X
  4468. X
  4469. Xstatic void lock_prepare _((long, long, int));
  4470. X
  4471. Xstatic void
  4472. Xlock_prepare(start, length, exclusive)
  4473. X    long        start;
  4474. X    long        length;
  4475. X    int        exclusive;
  4476. X{
  4477. X    struct flock    p;
  4478. X
  4479. X    trace(("lock_prepare(start = %ld, length = %ld, excl = %d)\n{\n"/*}*/,
  4480. X        start, length, exclusive));
  4481. X    assert(start > lock_master);
  4482. X    assert(length > 0);
  4483. X    flock_construct(&p, (exclusive ? F_WRLCK : F_RDLCK), start, length);
  4484. X    *(struct flock *)
  4485. X    enlarge(&nplaces, (char **)&place, sizeof(struct flock)) =
  4486. X        p;
  4487. X    trace((/*{*/"}\n"));
  4488. X}
  4489. X
  4490. X
  4491. Xvoid
  4492. Xlock_prepare_gstate()
  4493. X{
  4494. X    trace(("lock_prepare_gstate()\n{\n"/*}*/));
  4495. X    lock_prepare((long)lock_gstate, 1L, 1);
  4496. X    trace((/*{*/"}\n"));
  4497. X}
  4498. X
  4499. X
  4500. Xstatic void lock_prepare_mux _((lock_mux_ty, long, int));
  4501. X
  4502. Xstatic void
  4503. Xlock_prepare_mux(lock_mux, n, exclusive)
  4504. X    lock_mux_ty    lock_mux;
  4505. X    long        n;
  4506. X    int        exclusive;
  4507. X{
  4508. X    trace(("lock_prepare_mux(lock_mux = %d, n = %ld, excl = %d)\n{\n"/*}*/,
  4509. X        lock_mux, n, exclusive));
  4510. X    lock_prepare
  4511. X    (
  4512. X        ((lock_mux + 1L) << BITS) + (n & BITS_MASK),
  4513. X        1L,
  4514. X        exclusive
  4515. X    );
  4516. X    trace((/*{*/"}\n"));
  4517. X}
  4518. X
  4519. X
  4520. Xstatic void lock_prepare_mux_all _((lock_mux_ty, int));
  4521. X
  4522. Xstatic void
  4523. Xlock_prepare_mux_all(lock_mux, exclusive)
  4524. X    lock_mux_ty    lock_mux;
  4525. X    int        exclusive;
  4526. X{
  4527. X    trace(("lock_prepare_mux_all(lock_mux = %d)\n{\n"/*}*/, lock_mux));
  4528. X    lock_prepare(((lock_mux + 1L) << BITS), BITS_SIZE, exclusive);
  4529. X    trace((/*{*/"}\n"));
  4530. X}
  4531. X
  4532. X
  4533. Xvoid
  4534. Xlock_prepare_pstate(s)
  4535. X    string_ty    *s;
  4536. X{
  4537. X    trace(("lock_prepare_pstate(s = \"%s\")\n{\n"/*}*/, s->str_text));
  4538. X    lock_prepare_mux(lock_mux_pstate, (long)s->str_hash, 1);
  4539. X    trace((/*{*/"}\n"));
  4540. X}
  4541. X
  4542. X
  4543. Xvoid
  4544. Xlock_prepare_build_read(s)
  4545. X    string_ty    *s;
  4546. X{
  4547. X    trace(("lock_prepare_pstate(s = \"%s\")\n{\n"/*}*/, s->str_text));
  4548. X    lock_prepare_mux(lock_mux_build, (long)s->str_hash, 0);
  4549. X    trace((/*{*/"}\n"));
  4550. X}
  4551. X
  4552. X
  4553. Xvoid
  4554. Xlock_prepare_build_write(s)
  4555. X    string_ty    *s;
  4556. X{
  4557. X    trace(("lock_prepare_pstate(s = \"%s\")\n{\n"/*}*/, s->str_text));
  4558. X    lock_prepare_mux(lock_mux_build, (long)s->str_hash, 1);
  4559. X    trace((/*{*/"}\n"));
  4560. X}
  4561. X
  4562. X
  4563. Xvoid
  4564. Xlock_prepare_ustate(uid)
  4565. X    int        uid;
  4566. X{
  4567. X    trace(("lock_prepare_ustate()\n{\n"/*}*/));
  4568. X    lock_prepare_mux(lock_mux_ustate, (long)uid, 1);
  4569. X    trace((/*{*/"}\n"));
  4570. X}
  4571. X
  4572. X
  4573. Xvoid
  4574. Xlock_prepare_ustate_all()
  4575. X{
  4576. X    trace(("lock_prepare_ustate_all()\n{\n"/*}*/));
  4577. X    lock_prepare_mux_all(lock_mux_ustate, 1);
  4578. X    trace((/*{*/"}\n"));
  4579. X}
  4580. X
  4581. X
  4582. Xvoid
  4583. Xlock_prepare_cstate(project_name, change_number)
  4584. X    string_ty    *project_name;
  4585. X    long        change_number;
  4586. X{
  4587. X    trace(("lock_prepare_cstate(project_name = \"%s\", change_number = \
  4588. X%ld)\n{\n"/*}*/, project_name->str_text, change_number));
  4589. X    lock_prepare_mux
  4590. X    (
  4591. X        lock_mux_cstate,
  4592. X        change_number + project_name->str_hash,
  4593. X        1
  4594. X    );
  4595. X    trace((/*{*/"}\n"));
  4596. X}
  4597. X
  4598. X
  4599. Xstatic char *flock_type_string _((int));
  4600. X
  4601. Xstatic char *
  4602. Xflock_type_string(n)
  4603. X    int        n;
  4604. X{
  4605. X    switch (n)
  4606. X    {
  4607. X    case F_RDLCK:
  4608. X        return "F_RDLCK";
  4609. X
  4610. X    case F_WRLCK:
  4611. X        return "F_WRLCK";
  4612. X
  4613. X    case F_UNLCK:
  4614. X        return "F_UNLCK";
  4615. X    }
  4616. X    return "unknown";
  4617. X}
  4618. X
  4619. X
  4620. Xstatic char *flock_whence_string _((int));
  4621. X
  4622. Xstatic char *
  4623. Xflock_whence_string(n)
  4624. X    int        n;
  4625. X{
  4626. X    switch (n)
  4627. X    {
  4628. X    case SEEK_SET:
  4629. X        return "SEEK_SET";
  4630. X
  4631. X    case SEEK_CUR:
  4632. X        return "SEEK_CUR";
  4633. X
  4634. X    case SEEK_END:
  4635. X        return "SEEK_END";
  4636. X    }
  4637. X    return "unknown";
  4638. X}
  4639. X
  4640. X
  4641. Xstatic char *flock_string _((struct flock *));
  4642. X
  4643. Xstatic char *
  4644. Xflock_string(p)
  4645. X    struct flock    *p;
  4646. X{
  4647. X    static char    buffer[120];
  4648. X
  4649. X    sprintf
  4650. X    (
  4651. X        buffer,
  4652. X        "&{type = %s, whence = %s, start = %ld, len = %ld, pid = %d}",
  4653. X        flock_type_string(p->l_type),
  4654. X        flock_whence_string(p->l_whence),
  4655. X        p->l_start,
  4656. X        p->l_len,
  4657. X        p->l_pid
  4658. X    );
  4659. X    return buffer;
  4660. X}
  4661. X
  4662. X
  4663. Xstatic char *lock_description _((struct flock *));
  4664. X
  4665. Xstatic char *
  4666. Xlock_description(p)
  4667. X    struct flock    *p;
  4668. X{
  4669. X    switch (p->l_start)
  4670. X    {
  4671. X    case lock_master:
  4672. X        return "master";
  4673. X
  4674. X    case lock_gstate:
  4675. X        return "global state";
  4676. X    }
  4677. X    switch ((p->l_start >> BITS) - 1)
  4678. X    {
  4679. X    case lock_mux_ustate:
  4680. X        return "user";
  4681. X
  4682. X    case lock_mux_cstate:
  4683. X        return "change";
  4684. X
  4685. X    case lock_mux_pstate:
  4686. X        return "project";
  4687. X
  4688. X    case lock_mux_build:
  4689. X        return "build";
  4690. X    }
  4691. X    return "unknown";
  4692. X}
  4693. X
  4694. X
  4695. Xstatic void quitter _((int));
  4696. X
  4697. Xstatic void
  4698. Xquitter(n)
  4699. X    int    n;
  4700. X{
  4701. X    if (fd >= 0)
  4702. X    {
  4703. X        while (os_become_active())
  4704. X            os_become_undo();
  4705. X        lock_release();
  4706. X    }
  4707. X}
  4708. X
  4709. X
  4710. Xvoid
  4711. Xlock_take()
  4712. X{
  4713. X    int        flags;
  4714. X    struct flock    p;
  4715. X    int        j, k;
  4716. X
  4717. X    /*
  4718. X     * get the file descriptor of the lock file
  4719. X     *
  4720. X     * If it isn't there, create it.  If it is there, truncate it (prevent
  4721. X     * abuse of universally writable file).
  4722. X     */
  4723. X    trace(("lock_take()\n{\n"/*}*/));
  4724. X    assert(fd < 0);
  4725. X    assert(nplaces);
  4726. X    if (!quitregd)
  4727. X    {
  4728. X        quitregd = 1;
  4729. X        quit_register(quitter);
  4730. X    }
  4731. X    if (!path)
  4732. X        path = gonzo_lockpath_get();
  4733. X    gonzo_become();
  4734. X    fd = glue_open(path->str_text, O_RDWR | O_CREAT | O_TRUNC, 0600);
  4735. X    if (fd < 0)
  4736. X        nfatal("open(\"%s\")", path->str_text);
  4737. X    trace_int(fd);
  4738. X
  4739. X    /*
  4740. X     * make sure the file is closed when a child exec's
  4741. X     */
  4742. X#ifndef CONF_NO_seteuid
  4743. X    if (fcntl(fd, F_GETFD, &flags))
  4744. X        nfatal("fcntl(\"%s\", F_GETFD)", path->str_text);
  4745. X    flags |= 1;
  4746. X    if (fcntl(fd, F_SETFD, flags))
  4747. X        nfatal("fcntl(\"%s\", F_SETFD, %d)", path->str_text, flags);
  4748. X    trace(("mark\n"));
  4749. X#endif
  4750. X
  4751. X    /*
  4752. X     * Block for the master lock.
  4753. X     * Take the locks we really want.
  4754. X     * If we got them, release master and return.
  4755. X     * If did not get all of the locks,
  4756. X     * release the locks we could get and then the master.
  4757. X     * Block on the lock we could not get,
  4758. X     * release that lock and start again.
  4759. X     *
  4760. X     * Unfortunately, this scheme isn't fair
  4761. X     * (i.e. no guarantee of success in finite time)
  4762. X     * it would be nice if I could atomically lock (and block)
  4763. X     * an entire vector of locks.  (vfcntl like berkeley's vwrite?)
  4764. X     */
  4765. X    for (;;)
  4766. X    {
  4767. X        /*
  4768. X         * get the master lock
  4769. X         * (block if necessary,
  4770. X         * it should never be held for long)
  4771. X         */
  4772. X        trace(("mark\n"));
  4773. X        flock_construct(&p, F_WRLCK, (long)lock_master, 1L);
  4774. X        if (glue_fcntl(fd, F_SETLKW, &p))
  4775. X        {
  4776. X            nfatal
  4777. X            (
  4778. X                "fcntl(\"%s\", F_SETLKW, %s)",
  4779. X                path->str_text,
  4780. X                flock_string(&p)
  4781. X            );
  4782. X        }
  4783. X
  4784. X        /*
  4785. X         * get each of the locks we really wanted
  4786. X         */
  4787. X        for (j = 0; j < nplaces; ++j)
  4788. X        {
  4789. X            trace(("mark\n"));
  4790. X            p = place[j];
  4791. X            if (glue_fcntl(fd, F_SETLK, &p))
  4792. X            {
  4793. X                if (errno != EACCES && errno != EAGAIN)
  4794. X                {
  4795. X                    nfatal
  4796. X                    (
  4797. X                        "fcntl(\"%s\", F_SETLK, %s)",
  4798. X                        path->str_text,
  4799. X                        flock_string(&p)
  4800. X                    );
  4801. X                }
  4802. X                break;
  4803. X            }
  4804. X        }
  4805. X
  4806. X        /*
  4807. X         * return if were successful.
  4808. X         */
  4809. X        if (j >= nplaces)
  4810. X        {
  4811. X            trace(("mark\n"));
  4812. X            flock_construct(&p, F_UNLCK, (long)lock_master, 1L);
  4813. X            if (glue_fcntl(fd, F_SETLKW, &p))
  4814. X            {
  4815. X                nfatal
  4816. X                (
  4817. X                    "fcntl(\"%s\", F_SETLKW, %s)",
  4818. X                    path->str_text,
  4819. X                    flock_string(&p)
  4820. X                );
  4821. X            }
  4822. X            break;
  4823. X        }
  4824. X
  4825. X        /*
  4826. X         * give all the locks back
  4827. X         * that we got so far
  4828. X         */
  4829. X        for (k = 0; k < j; ++k)
  4830. X        {
  4831. X            trace(("mark\n"));
  4832. X            p = place[k];
  4833. X            p.l_type = F_UNLCK;
  4834. X            if (glue_fcntl(fd, F_SETLKW, &p))
  4835. X            {
  4836. X                nfatal
  4837. X                (
  4838. X                    "fcntl(\"%s\", F_SETLKW, %s)",
  4839. X                    path->str_text,
  4840. X                    flock_string(&p)
  4841. X                );
  4842. X            }
  4843. X        }
  4844. X
  4845. X        /*
  4846. X         * release the master lock
  4847. X         */
  4848. X        flock_construct(&p, F_UNLCK, (long)lock_master, 1L);
  4849. X        if (glue_fcntl(fd, F_SETLKW, &p))
  4850. X        {
  4851. X            nfatal
  4852. X            (
  4853. X                "fcntl(\"%s\", F_SETLKW, %s)",
  4854. X                path->str_text,
  4855. X                flock_string(&p)
  4856. X            );
  4857. X        }
  4858. X        trace(("mark\n"));
  4859. X
  4860. X        /*
  4861. X         * verbose message about why we are blocking
  4862. X         */
  4863. X        p = place[j];
  4864. X        verbose("waiting for %s lock", lock_description(&p));
  4865. X
  4866. X        /*
  4867. X         * block on the lock that stopped us before
  4868. X         */
  4869. X        if (glue_fcntl(fd, F_SETLKW, &p))
  4870. X        {
  4871. X            nfatal
  4872. X            (
  4873. X                "fcntl(\"%s\", F_SETLKW, %s)",
  4874. X                path->str_text,
  4875. X                flock_string(&p)
  4876. X            );
  4877. X        }
  4878. X
  4879. X        /*
  4880. X         * and then release it,
  4881. X         * before trying all over again.
  4882. X         */
  4883. X        p = place[j];
  4884. X        p.l_type = F_UNLCK;
  4885. X        if (glue_fcntl(fd, F_SETLKW, &p))
  4886. X        {
  4887. X            nfatal
  4888. X            (
  4889. X                "fcntl(\"%s\", F_SETLKW, %s)",
  4890. X                path->str_text,
  4891. X                flock_string(&p)
  4892. X            );
  4893. X        }
  4894. X        trace(("mark\n"));
  4895. X    }
  4896. X    gonzo_become_undo();
  4897. X    magic++;
  4898. X    trace((/*{*/"}\n"));
  4899. X}
  4900. X
  4901. X
  4902. Xvoid
  4903. Xlock_release()
  4904. X{
  4905. X    struct flock    p;
  4906. X    int        j;
  4907. X    int        fildes;
  4908. X
  4909. X    /*
  4910. X     * set the file descriptor to -1
  4911. X     * so that we will not be invoked again should
  4912. X     * a fatal error happen here.
  4913. X     */
  4914. X    trace(("lock_release()\n{\n"/*}*/));
  4915. X    trace_int(fd);
  4916. X    assert(fd >= 0);
  4917. X    assert(nplaces);
  4918. X    assert(place);
  4919. X    assert(path);
  4920. X    gonzo_become();
  4921. X    fildes = fd;
  4922. X    fd = -1;
  4923. X
  4924. X    /*
  4925. X     * Release each of the locks.
  4926. X     * This should be unnecessary, because we then close the file,
  4927. X     * but SunOS hangs onto some of them, even after the process dies.
  4928. X     */
  4929. X    for (j = 0; j < nplaces; ++j)
  4930. X    {
  4931. X        p = place[j];
  4932. X        p.l_type = F_UNLCK;
  4933. X        if (glue_fcntl(fildes, F_SETLKW, &p))
  4934. X        {
  4935. X            nfatal
  4936. X            (
  4937. X                "fcntl(\"%s\", F_SETLKW, %s)",
  4938. X                path->str_text,
  4939. X                flock_string(&p)
  4940. X            );
  4941. X        }
  4942. X    }
  4943. X
  4944. X    /*
  4945. X     * close the file
  4946. X     * (this *should* have been enough)
  4947. X     */
  4948. X    glue_close(fildes);
  4949. X    gonzo_become_undo();
  4950. X    nplaces = 0;
  4951. X    mem_free((char *)place);
  4952. X    place = 0;
  4953. X    trace((/*{*/"}\n"));
  4954. X}
  4955. X
  4956. X
  4957. Xlong
  4958. Xlock_magic()
  4959. X{
  4960. X    return magic;
  4961. X}
  4962. X
  4963. X
  4964. Xstatic void lock_walk_hunt _((long, long, lock_walk_callback));
  4965. X
  4966. Xstatic void
  4967. Xlock_walk_hunt(min, max, callback)
  4968. X    long        min;
  4969. X    long        max;
  4970. X    lock_walk_callback callback;
  4971. X{
  4972. X    struct flock    flock;
  4973. X    int        j;
  4974. X    lock_walk_found    found;
  4975. X
  4976. X    /*
  4977. X     * look for a lock in the given range
  4978. X     */
  4979. X    flock.l_type = F_WRLCK;
  4980. X    flock.l_whence = SEEK_SET;
  4981. X    flock.l_start = min;
  4982. X    flock.l_len = max - min;
  4983. X    flock.l_pid = 0;
  4984. X    gonzo_become();
  4985. X    if (glue_fcntl(fd, F_GETLK, &flock))
  4986. X        nfatal("getlock \"%s\"", path->str_text);
  4987. X    gonzo_become_undo();
  4988. X    if (flock.l_type == F_UNLCK)
  4989. X        return;
  4990. X
  4991. X    /*
  4992. X     * aegis only uses byte locks,
  4993. X     * so multi-byte ranges are separate locks
  4994. X     */
  4995. X    for (j = 0; j < flock.l_len; ++j)
  4996. X    {
  4997. X        /*
  4998. X         * figure the name and address
  4999. X         */
  5000. X        found.address = flock.l_start + j;
  5001. X        found.subset = 0;
  5002. X        switch (found.address)
  5003. X        {
  5004. X        case lock_master:
  5005. X            found.name = lock_walk_name_master;
  5006. X            break;
  5007. X
  5008. X        case lock_gstate:
  5009. X            found.name = lock_walk_name_gstate;
  5010. X            break;
  5011. X
  5012. X        default:
  5013. X            switch ((found.address >> BITS) - 1)
  5014. X            {
  5015. X            case lock_mux_ustate:
  5016. X                found.name = lock_walk_name_ustate;
  5017. X                found.subset = found.address & BITS_MASK;
  5018. X                break;
  5019. X
  5020. X            case lock_mux_pstate:
  5021. X                found.name = lock_walk_name_ustate;
  5022. X                found.subset = found.address & BITS_MASK;
  5023. X                break;
  5024. X
  5025. X            case lock_mux_cstate:
  5026. X                found.name = lock_walk_name_cstate;
  5027. X                found.subset = found.address & BITS_MASK;
  5028. X                break;
  5029. X
  5030. X            case lock_mux_build:
  5031. X                found.name = lock_walk_name_build;
  5032. X                found.subset = found.address & BITS_MASK;
  5033. X                break;
  5034. X
  5035. X            default:
  5036. X                found.name = lock_walk_name_unknown;
  5037. X                break;
  5038. X            }
  5039. X        }
  5040. X
  5041. X        /*
  5042. X         * figure the type
  5043. X         */
  5044. X        switch (flock.l_type)
  5045. X        {
  5046. X        case F_RDLCK:
  5047. X            found.type = lock_walk_type_shared;
  5048. X            break;
  5049. X
  5050. X        case F_WRLCK:
  5051. X            found.type = lock_walk_type_exclusive;
  5052. X            break;
  5053. X
  5054. X        default:
  5055. X            found.type = lock_walk_type_unknown;
  5056. X            break;
  5057. X        }
  5058. X
  5059. X        /*
  5060. X         * Process holding the lock.
  5061. X         * Workout if it is local or remote.
  5062. X         */
  5063. X        found.pid = flock.l_pid;
  5064. X        if (kill(found.pid, 0))
  5065. X        {
  5066. X            switch (errno)
  5067. X            {
  5068. X            default:
  5069. X                fatal("kill(%d, 0)", found.pid);
  5070. X
  5071. X            case EPERM:
  5072. X                found.pid_is_local = 1;
  5073. X                break;
  5074. X
  5075. X            case ESRCH:
  5076. X                found.pid_is_local = 0;
  5077. X                break;
  5078. X            }
  5079. X        }
  5080. X        else
  5081. X            found.pid_is_local = 1;
  5082. X
  5083. X        /*
  5084. X         * do something with it
  5085. X         */
  5086. X        callback(&found);
  5087. X    }
  5088. X
  5089. X    /*
  5090. X     * look for more locks on either side
  5091. X     */
  5092. X    if (flock.l_start)
  5093. X        lock_walk_hunt(min, flock.l_start, callback);
  5094. X    if (flock.l_len)
  5095. X        lock_walk_hunt(flock.l_start + flock.l_len, max, callback);
  5096. X}
  5097. X
  5098. X
  5099. Xvoid
  5100. Xlock_walk(callback)
  5101. X    lock_walk_callback callback;
  5102. X{
  5103. X    int    flags;
  5104. X    int    fildes;
  5105. X
  5106. X    trace(("lock_walk()\n{\n"/*}*/));
  5107. X    assert(fd < 0);
  5108. X    assert(!nplaces);
  5109. X    if (!quitregd)
  5110. X    {
  5111. X        quitregd = 1;
  5112. X        quit_register(quitter);
  5113. X    }
  5114. X    if (!path)
  5115. X        path = gonzo_lockpath_get();
  5116. X    gonzo_become();
  5117. X    fd = glue_open(path->str_text, O_RDWR | O_CREAT | O_TRUNC, 0600);
  5118. X    if (fd < 0)
  5119. X        nfatal("open(\"%s\")", path->str_text);
  5120. X    trace_int(fd);
  5121. X
  5122. X    /*
  5123. X     * make sure the file is closed when a child exec's
  5124. X     */
  5125. X#ifndef CONF_NO_seteuid
  5126. X    if (fcntl(fd, F_GETFD, &flags))
  5127. X        nfatal("fcntl(\"%s\", F_GETFD)", path->str_text);
  5128. X    flags |= 1;
  5129. X    if (fcntl(fd, F_SETFD, flags))
  5130. X        nfatal("fcntl(\"%s\", F_SETFD, %d)", path->str_text, flags);
  5131. X    trace(("mark\n"));
  5132. X#endif
  5133. X    gonzo_become_undo();
  5134. X
  5135. X    /*
  5136. X     * chase all of the locks
  5137. X     */
  5138. X    lock_walk_hunt(0L, ((lock_mux_MAX + 1) << BITS), callback);
  5139. X
  5140. X    /*
  5141. X     * close the file
  5142. X     */
  5143. X    gonzo_become();
  5144. X    trace_int(fd);
  5145. X    assert(fd >= 0);
  5146. X    assert(path);
  5147. X    fildes = fd;
  5148. X    fd = -1;
  5149. X    glue_close(fildes);
  5150. X    gonzo_become_undo();
  5151. X    trace((/*{*/"}\n"));
  5152. X}
  5153. END_OF_FILE
  5154. if test 14304 -ne `wc -c <'aegis/lock.c'`; then
  5155.     echo shar: \"'aegis/lock.c'\" unpacked with wrong size!
  5156. fi
  5157. # end of 'aegis/lock.c'
  5158. fi
  5159. if test -f 'aux/CHANGES.1.1' -a "${1}" != "-c" ; then 
  5160.   echo shar: Will not clobber existing file \"'aux/CHANGES.1.1'\"
  5161. else
  5162. echo shar: Extracting \"'aux/CHANGES.1.1'\" \(12490 characters\)
  5163. sed "s/^X//" >'aux/CHANGES.1.1' <<'END_OF_FILE'
  5164. XChange    State        Description
  5165. X------- -------        -------------
  5166. X1    completed    New release derived from aegis.
  5167. X2    completed    generated Makefile with absolute dependencies
  5168. X3    being_        the project does not yet make
  5169. X    integrated
  5170. X
  5171. XIDENTIFICATION
  5172. X    Project "aegis.1.1", change 1.
  5173. X
  5174. XSUMMARY
  5175. X    New release derived from aegis.
  5176. X
  5177. XDESCRIPTION
  5178. X    New release derived from aegis.
  5179. X
  5180. XCAUSE
  5181. X    internal_enhancement
  5182. X
  5183. XFILES
  5184. X    Type    Action    Edit    File Name
  5185. X    ------- ------- ------- -----------
  5186. X    source    create    1    ALPHA.NOTICE
  5187. X    source    create    1    BUILDING
  5188. X    source    create    1    CHANGES.sh
  5189. X    source    create    1    COPYING
  5190. X    source    create    1    Howto.cook
  5191. X    source    create    1    Makefile.awk
  5192. X    source    create    1    Makefile.sh
  5193. X    source    create    1    README
  5194. X    source    create    1    aegis/administ.c
  5195. X    source    create    1    aegis/administ.h
  5196. X    source    create    1    aegis/ansi.c
  5197. X    source    create    1    aegis/archaeol.c
  5198. X    source    create    1    aegis/archaeol.h
  5199. X    source    create    1    aegis/arglex.c
  5200. X    source    create    1    aegis/arglex.h
  5201. X    source    create    1    aegis/build.c
  5202. X    source    create    1    aegis/build.h
  5203. X    source    create    1    aegis/cattr.def
  5204. X    source    create    1    aegis/cattr_ed.c
  5205. X    source    create    1    aegis/cattr_ed.h
  5206. X    source    create    1    aegis/change.c
  5207. X    source    create    1    aegis/change.h
  5208. X    source    create    1    aegis/chdir.c
  5209. X    source    create    1    aegis/chdir.h
  5210. X    source    create    1    aegis/col.c
  5211. X    source    create    1    aegis/col.h
  5212. X    source    create    1    aegis/commit.c
  5213. X    source    create    1    aegis/commit.h
  5214. X    source    create    1    aegis/common.def
  5215. X    source    create    1    aegis/copyfile.c
  5216. X    source    create    1    aegis/copyfile.h
  5217. X    source    create    1    aegis/cstate.def
  5218. X    source    create    1    aegis/defaults.c
  5219. X    source    create    1    aegis/defaults.h
  5220. X    source    create    1    aegis/develop1.c
  5221. X    source    create    1    aegis/develop1.h
  5222. X    source    create    1    aegis/develop2.c
  5223. X    source    create    1    aegis/develop2.h
  5224. X    source    create    1    aegis/diff.c
  5225. X    source    create    1    aegis/diff.h
  5226. X    source    create    1    aegis/dir.c
  5227. X    source    create    1    aegis/dir.h
  5228. X    source    create    1    aegis/error.c
  5229. X    source    create    1    aegis/error.h
  5230. X    source    create    1    aegis/file.c
  5231. X    source    create    1    aegis/file.h
  5232. X    source    create    1    aegis/gate.h
  5233. X    source    create    1    aegis/gonzo.c
  5234. X    source    create    1    aegis/gonzo.h
  5235. X    source    create    1    aegis/gram.y
  5236. X    source    create    1    aegis/gstate.def
  5237. X    source    create    1    aegis/help.c
  5238. X    source    create    1    aegis/help.h
  5239. X    source    create    1    aegis/indent.c
  5240. X    source    create    1    aegis/indent.h
  5241. X    source    create    1    aegis/integra1.c
  5242. X    source    create    1    aegis/integra1.h
  5243. X    source    create    1    aegis/integra2.c
  5244. X    source    create    1    aegis/integra2.h
  5245. X    source    create    1    aegis/io.c
  5246. X    source    create    1    aegis/io.h
  5247. X    source    create    1    aegis/lex.c
  5248. X    source    create    1    aegis/lex.h
  5249. X    source    create    1    aegis/list.c
  5250. X    source    create    1    aegis/list.h
  5251. X    source    create    1    aegis/lock.c
  5252. X    source    create    1    aegis/lock.h
  5253. X    source    create    1    aegis/log.c
  5254. X    source    create    1    aegis/log.h
  5255. X    source    create    1    aegis/main.c
  5256. X    source    create    1    aegis/mem.c
  5257. X    source    create    1    aegis/mem.h
  5258. X    source    create    1    aegis/new_chan.c
  5259. X    source    create    1    aegis/new_chan.h
  5260. X    source    create    1    aegis/new_file.c
  5261. X    source    create    1    aegis/new_file.h
  5262. X    source    create    1    aegis/new_proj.c
  5263. X    source    create    1    aegis/new_proj.h
  5264. X    source    create    1    aegis/new_rele.c
  5265. X    source    create    1    aegis/new_rele.h
  5266. X    source    create    1    aegis/new_test.c
  5267. X    source    create    1    aegis/new_test.h
  5268. X    source    create    1    aegis/option.c
  5269. X    source    create    1    aegis/option.h
  5270. X    source    create    1    aegis/os.c
  5271. X    source    create    1    aegis/os.h
  5272. X    source    create    1    aegis/parse.c
  5273. X    source    create    1    aegis/parse.h
  5274. X    source    create    1    aegis/pattr.def
  5275. X    source    create    1    aegis/pattr_ed.c
  5276. X    source    create    1    aegis/pattr_ed.h
  5277. X    source    create    1    aegis/pconf.def
  5278. X    source    create    1    aegis/project.c
  5279. X    source    create    1    aegis/project.h
  5280. X    source    create    1    aegis/pstate.def
  5281. X    source    create    1    aegis/rem_file.c
  5282. X    source    create    1    aegis/rem_file.h
  5283. X    source    create    1    aegis/review.c
  5284. X    source    create    1    aegis/review.h
  5285. X    source    create    1    aegis/reviewer.c
  5286. X    source    create    1    aegis/reviewer.h
  5287. X    source    create    1    aegis/str.c
  5288. X    source    create    1    aegis/str.h
  5289. X    source    create    1    aegis/sub.c
  5290. X    source    create    1    aegis/sub.h
  5291. X    source    create    1    aegis/test.c
  5292. X    source    create    1    aegis/test.h
  5293. X    source    create    1    aegis/trace.c
  5294. X    source    create    1    aegis/trace.h
  5295. X    source    create    1    aegis/tree.c
  5296. X    source    create    1    aegis/tree.h
  5297. X    source    create    1    aegis/type.c
  5298. X    source    create    1    aegis/type.h
  5299. X    source    create    1    aegis/uconf.def
  5300. X    source    create    1    aegis/undo.c
  5301. X    source    create    1    aegis/undo.h
  5302. X    source    create    1    aegis/user.c
  5303. X    source    create    1    aegis/user.h
  5304. X    source    create    1    aegis/ustate.def
  5305. X    source    create    1    aegis/version.c
  5306. X    source    create    1    aegis/version.h
  5307. X    source    create    1    aegis/word.c
  5308. X    source    create    1    aegis/word.h
  5309. X    source    create    1    common/main.h
  5310. X    source    create    1    config
  5311. X    source    create    1    doc/aegis.mm
  5312. X    source    create    1    doc/c1.0.so
  5313. X    source    create    1    doc/c1.1.so
  5314. X    source    create    1    doc/c1.2.so
  5315. X    source    create    1    doc/c1.3.so
  5316. X    source    create    1    doc/c2.0.so
  5317. X    source    create    1    doc/c2.1.so
  5318. X    source    create    1    doc/c2.2.so
  5319. X    source    create    1    doc/c2.3.so
  5320. X    source    create    1    doc/c2.4.so
  5321. X    source    create    1    doc/c3.0.so
  5322. X    source    create    1    doc/c4.0.so
  5323. X    source    create    1    doc/c5.0.so
  5324. X    source    create    1    doc/c6.0.so
  5325. X    source    create    1    doc/c7.0.so
  5326. X    source    create    1    doc/c7.1.so
  5327. X    source    create    1    doc/c7.2.so
  5328. X    source    create    1    doc/cA.0.so
  5329. X    source    create    1    dot.cshrc
  5330. X    source    create    1    dot.profile
  5331. X    source    create    1    fmtgen/ansi.c
  5332. X    source    create    1    fmtgen/arglex.c
  5333. X    source    create    1    fmtgen/arglex.h
  5334. X    source    create    1    fmtgen/error.c
  5335. X    source    create    1    fmtgen/error.h
  5336. X    source    create    1    fmtgen/id.c
  5337. X    source    create    1    fmtgen/id.h
  5338. X    source    create    1    fmtgen/indent.c
  5339. X    source    create    1    fmtgen/indent.h
  5340. X    source    create    1    fmtgen/lex.c
  5341. X    source    create    1    fmtgen/lex.h
  5342. X    source    create    1    fmtgen/main.c
  5343. X    source    create    1    fmtgen/mem.c
  5344. X    source    create    1    fmtgen/mem.h
  5345. X    source    create    1    fmtgen/parse.y
  5346. X    source    create    1    fmtgen/str.c
  5347. X    source    create    1    fmtgen/str.h
  5348. X    source    create    1    fmtgen/type.c
  5349. X    source    create    1    fmtgen/type.h
  5350. X    source    create    1    fmtgen/type_enum.c
  5351. X    source    create    1    fmtgen/type_integ.c
  5352. X    source    create    1    fmtgen/type_list.c
  5353. X    source    create    1    fmtgen/type_ref.c
  5354. X    source    create    1    fmtgen/type_strin.c
  5355. X    source    create    1    fmtgen/type_struc.c
  5356. X    source    create    1    fmtgen/word.c
  5357. X    source    create    1    fmtgen/word.h
  5358. X    source    create    1    h/stdarg.h
  5359. X    source    create    1    h/stddef.h
  5360. X    source    create    1    h/stdlib.h
  5361. X    source    create    1    man1/aea.1
  5362. X    source    create    1    man1/aeb.1
  5363. X    source    create    1    man1/aeca.1
  5364. X    source    create    1    man1/aecd.1
  5365. X    source    create    1    man1/aecp.1
  5366. X    source    create    1    man1/aecpu.1
  5367. X    source    create    1    man1/aed.1
  5368. X    source    create    1    man1/aedb.1
  5369. X    source    create    1    man1/aedbu.1
  5370. X    source    create    1    man1/aede.1
  5371. X    source    create    1    man1/aedeu.1
  5372. X    source    create    1    man1/aega.1
  5373. X    source    create    1    man1/aegis.1
  5374. X    source    create    1    man1/aeib.1
  5375. X    source    create    1    man1/aeibu.1
  5376. X    source    create    1    man1/aeif.1
  5377. X    source    create    1    man1/aeip.1
  5378. X    source    create    1    man1/ael.1
  5379. X    source    create    1    man1/aena.1
  5380. X    source    create    1    man1/aenc.1
  5381. X    source    create    1    man1/aencu.1
  5382. X    source    create    1    man1/aend.1
  5383. X    source    create    1    man1/aenf.1
  5384. X    source    create    1    man1/aenfu.1
  5385. X    source    create    1    man1/aeni.1
  5386. X    source    create    1    man1/aenpr.1
  5387. X    source    create    1    man1/aenrls.1
  5388. X    source    create    1    man1/aenrv.1
  5389. X    source    create    1    man1/aent.1
  5390. X    source    create    1    man1/aentu.1
  5391. X    source    create    1    man1/aepa.1
  5392. X    source    create    1    man1/aera.1
  5393. X    source    create    1    man1/aerd.1
  5394. X    source    create    1    man1/aerf.1
  5395. X    source    create    1    man1/aeri.1
  5396. X    source    create    1    man1/aerm.1
  5397. X    source    create    1    man1/aermu.1
  5398. X    source    create    1    man1/aerp.1
  5399. X    source    create    1    man1/aerpr.1
  5400. X    source    create    1    man1/aerpu.1
  5401. X    source    create    1    man1/aerrv.1
  5402. X    source    create    1    man1/aet.1
  5403. X    source    create    1    man1/aeua.1
  5404. X    source    create    1    man1/aev.1
  5405. X    source    create    1    man1/o__rules.so
  5406. X    source    create    1    man1/o_anticip.so
  5407. X    source    create    1    man1/o_auto.so
  5408. X    source    create    1    man1/o_baselin.so
  5409. X    source    create    1    man1/o_change.so
  5410. X    source    create    1    man1/o_devdir.so
  5411. X    source    create    1    man1/o_dir.so
  5412. X    source    create    1    man1/o_help.so
  5413. X    source    create    1    man1/o_indep.so
  5414. X    source    create    1    man1/o_keep.so
  5415. X    source    create    1    man1/o_lib.so
  5416. X    source    create    1    man1/o_list.so
  5417. X    source    create    1    man1/o_major.so
  5418. X    source    create    1    man1/o_manual.so
  5419. X    source    create    1    man1/o_min.so
  5420. X    source    create    1    man1/o_minor.so
  5421. X    source    create    1    man1/o_nolog.so
  5422. X    source    create    1    man1/o_overw.so
  5423. X    source    create    1    man1/o_page.so
  5424. X    source    create    1    man1/o_project.so
  5425. X    source    create    1    man1/o_terse.so
  5426. X    source    create    1    man1/o_verbose.so
  5427. X    source    create    1    man1/z_cr.so
  5428. X    source    create    1    man1/z_exit.so
  5429. X    source    create    1    man1/z_intuit.so
  5430. X    source    create    1    man1/z_name.so
  5431. X    source    create    1    man5/aecattr.5
  5432. X    source    create    1    man5/aecstate.5
  5433. X    source    create    1    man5/aedir.5
  5434. X    source    create    1    man5/aegis.5
  5435. X    source    create    1    man5/aegstate.5
  5436. X    source    create    1    man5/aepattr.5
  5437. X    source    create    1    man5/aepconf.5
  5438. X    source    create    1    man5/aepstate.5
  5439. X    source    create    1    man5/aeuconf.5
  5440. X    source    create    1    man5/aeustate.5
  5441. X    source    create    1    man5/z_cr.so
  5442. X    source    create    1    man5/z_name.so
  5443. X    source    create    1    notify/de.sh
  5444. X    source    create    1    notify/deu.sh
  5445. X    source    create    1    notify/if.sh
  5446. X    source    create    1    notify/ip.sh
  5447. X    source    create    1    notify/rf.sh
  5448. X    source    create    1    notify/rp.sh
  5449. X    source    create    1    notify/rpu.sh
  5450. X    test    create    1    test/00/t0001a.sh
  5451. X    test    create    1    test/00/t0002a.sh
  5452. X    test    create    1    test/00/t0003a.sh
  5453. X    test    create    1    test/00/t0004a.sh
  5454. X    test    create    1    test/00/t0005a.sh
  5455. X    test    create    1    test/00/t0006a.sh
  5456. X    test    create    1    test/00/t0007a.sh
  5457. X    test    create    1    test/00/t0008a.sh
  5458. X    test    create    1    test/00/t0009a.sh
  5459. X    test    create    1    test/00/t0010a.sh
  5460. X    test    create    1    test/00/t0011a.sh
  5461. X
  5462. XHISTORY
  5463. X    What        When        Who    Comment
  5464. X    ------        ------        -----    ---------
  5465. X    new_change    Wed Jun 17    pmiller Elapsed time: 0.000 days.
  5466. X            10:01:50 1992
  5467. X    develop_begin    Wed Jun 17    pmiller Elapsed time: 0.000 days.
  5468. X            10:01:50 1992
  5469. X    develop_end    Wed Jun 17    pmiller Elapsed time: 0.000 days.
  5470. X            10:01:50 1992
  5471. X    review_pass    Wed Jun 17    pmiller Elapsed time: 0.000 days.
  5472. X            10:01:50 1992
  5473. X    integrate_begin Wed Jun 17    pmiller Elapsed time: 0.015 days.
  5474. X            10:01:50 1992
  5475. X    integrate_pass    Wed Jun 17    pmiller
  5476. X            10:08:27 1992
  5477. X
  5478. XIDENTIFICATION
  5479. X    Project "aegis.1.1", build 2, change 2.
  5480. X
  5481. XSUMMARY
  5482. X    generated Makefile with absolute dependencies
  5483. X
  5484. XDESCRIPTION
  5485. X    1. A number of problems were found with the Makefile: it contained
  5486. X    absolute path name dependencies, it did not include any tests.
  5487. X    2. The build instructions are completely inadequate.
  5488. X    3. come kind of config include is required.
  5489. X    4. some way to test before making it set-uid-root is needed.
  5490. X    5. the tests use fcomp and sc!
  5491. X    6. some systems don't have the tcgetpgrp function.
  5492. X
  5493. X    My thanks to Peter Chubb <peterc@suite.sw.oz.au> for reporting these
  5494. X    problems.
  5495. X
  5496. XCAUSE
  5497. X    external_bug
  5498. X
  5499. XFILES
  5500. X    Type    Action    Edit    File Name
  5501. X    ------- ------- ------- -----------
  5502. X    source    remove    1    BUILDING
  5503. X    source    modify    2    Howto.cook
  5504. X    source    modify    2    Makefile.sh
  5505. X    source    remove    1    aegis/ansi.c
  5506. X    source    modify    2    aegis/commit.c
  5507. X    source    modify    2    aegis/gate.h
  5508. X    source    modify    2    aegis/gonzo.c
  5509. X    source    modify    2    aegis/log.c
  5510. X    source    modify    2    aegis/os.c
  5511. X    source    modify    2    aegis/os.h
  5512. X    source    create    1    common/ansi.c
  5513. X    source    create    1    conf/SunOS-4.1.2
  5514. X    source    create    1    conf/SysV-4.0
  5515. X    source    create    1    doc/build.man
  5516. X    source    remove    1    fmtgen/ansi.c
  5517. X    source    modify    2    man1/aegis.1
  5518. X    source    create    1    man1/install.sh
  5519. X    source    modify    2    man5/aeustate.5
  5520. X    source    create    1    man5/install.sh
  5521. X    test    modify    2    test/00/t0002a.sh
  5522. X    test    modify    2    test/00/t0004a.sh
  5523. X    test    modify    2    test/00/t0005a.sh
  5524. X    test    modify    2    test/00/t0006a.sh
  5525. X    test    modify    2    test/00/t0007a.sh
  5526. X    test    modify    2    test/00/t0009a.sh
  5527. X    test    modify    2    test/00/t0010a.sh
  5528. X    test    modify    2    test/00/t0011a.sh
  5529. X
  5530. XHISTORY
  5531. X    What        When        Who    Comment
  5532. X    ------        ------        -----    ---------
  5533. X    new_change    Wed Jun 17    pmiller Elapsed time: 0.001 days.
  5534. X            13:11:31 1992
  5535. X    develop_begin    Wed Jun 17    pmiller Elapsed time: 0.884 days.
  5536. X            13:12:03 1992
  5537. X    develop_end    Thu Jun 18    pmiller Elapsed time: 0.002 days.
  5538. X            12:19:56 1992
  5539. X    review_pass    Thu Jun 18    pmiller Elapsed time: 0.001 days.
  5540. X            12:20:37 1992
  5541. X    integrate_begin Thu Jun 18    pmiller Elapsed time: 0.226 days.
  5542. X            12:21:11 1992
  5543. X    integrate_pass    Thu Jun 18    pmiller
  5544. X            14:03:04 1992
  5545. X
  5546. XIDENTIFICATION
  5547. X    Project "aegis.1.1", build 3, change 3.
  5548. X
  5549. XSUMMARY
  5550. X    the project does not yet make
  5551. X
  5552. XDESCRIPTION
  5553. X    1. There are flaws in the generated Makefile which result in the make
  5554. X    failing.
  5555. X    2. There are flaws on some tests which make them behave differently
  5556. X    under make athan aet.
  5557. X
  5558. XCAUSE
  5559. X    internal_bug
  5560. X
  5561. XSTATE
  5562. X    being_integrated
  5563. X
  5564. XFILES
  5565. X    Type    Action    Edit    File Name
  5566. X    ------- ------- ------- -----------
  5567. X    source    modify    2    Makefile.sh
  5568. X    source    modify    2    aegis/os.c
  5569. X    test    modify    1    test/00/t0001a.sh
  5570. X    test    modify    1    test/00/t0003a.sh
  5571. X
  5572. XHISTORY
  5573. X    What        When        Who    Comment
  5574. X    ------        ------        -----    ---------
  5575. X    new_change    Fri Jun 19    pmiller Elapsed time: 0.001 days.
  5576. X            09:11:25 1992
  5577. X    develop_begin    Fri Jun 19    pmiller Elapsed time: 0.212 days.
  5578. X            09:11:51 1992
  5579. X    develop_end    Fri Jun 19    pmiller Elapsed time: 0.006 days.
  5580. X            10:47:05 1992
  5581. X    review_pass    Fri Jun 19    pmiller Elapsed time: 0.001 days.
  5582. X            10:49:50 1992
  5583. X    integrate_begin Fri Jun 19    pmiller Elapsed time: 0.244 days.
  5584. X            10:50:24 1992
  5585. END_OF_FILE
  5586. if test 12490 -ne `wc -c <'aux/CHANGES.1.1'`; then
  5587.     echo shar: \"'aux/CHANGES.1.1'\" unpacked with wrong size!
  5588. fi
  5589. # end of 'aux/CHANGES.1.1'
  5590. fi
  5591. if test -f 'doc/c6.0.so' -a "${1}" != "-c" ; then 
  5592.   echo shar: Will not clobber existing file \"'doc/c6.0.so'\"
  5593. else
  5594. echo shar: Extracting \"'doc/c6.0.so'\" \(13918 characters\)
  5595. sed "s/^X//" >'doc/c6.0.so' <<'END_OF_FILE'
  5596. X.\"
  5597. X.\"    aegis - project change supervisor
  5598. X.\"    Copyright (C) 1991, 1992, 1993 Peter Miller.
  5599. X.\"    All rights reserved.
  5600. X.\"
  5601. X.\"    This program is free software; you can redistribute it and/or modify
  5602. X.\"    it under the terms of the GNU General Public License as published by
  5603. X.\"    the Free Software Foundation; either version 2 of the License, or
  5604. X.\"    (at your option) any later version.
  5605. X.\"
  5606. X.\"    This program is distributed in the hope that it will be useful,
  5607. X.\"    but WITHOUT ANY WARRANTY; without even the implied warranty of
  5608. X.\"    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  5609. X.\"    GNU General Public License for more details.
  5610. X.\"
  5611. X.\"    You should have received a copy of the GNU General Public License
  5612. X.\"    along with this program; if not, write to the Free Software
  5613. X.\"    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  5614. X.\"
  5615. X.\" MANIFEST: User Guide, Tips and Traps
  5616. X.\"
  5617. X.bp
  5618. X.2C
  5619. X.nh 1 "Tips and Traps"
  5620. X.LP
  5621. XThis chapter contains hints for how to use the aegis program
  5622. Xmore efficiently
  5623. Xand documents a number of pitfalls you may encounter.
  5624. X.LP
  5625. XThis chapter is at present very "ad hoc" with no particular ordering.
  5626. XFortunately, it is, as yet, rather small.
  5627. XThe final size of this chapter is expected to be quite large.
  5628. X.nh 2 "C Include Semantics"
  5629. X.LP
  5630. XThe semantics of C include directives make the
  5631. X.E(
  5632. X#include "\fIfilename\fP"
  5633. X.E)
  5634. Xdirective dangerous in a project developed with the aegis program.
  5635. X.LP
  5636. XDepending on the age of your compiler,
  5637. Xwhether it is AT&T traditional C or newer ANSI C,
  5638. Xthis form of directive will search first in the current directory and then
  5639. Xalong the search path,
  5640. Xor in the directory of the including file and then along the search path.
  5641. X.LP
  5642. XThe first case is fairly benign,
  5643. Xexcept that compilers are rapidly becoming ANSI C compliant,
  5644. Xand an operating system upgrade could result in a nasty surprise.
  5645. X.LP
  5646. XThe second case is bad news.
  5647. XIf the source file is in the baseline and the include file is in the change,
  5648. Xyou don't want the source file to use the include file in the baseline.
  5649. X.LP
  5650. XAlways use the
  5651. X.E(
  5652. X#include <\fIfilename\fP>
  5653. X.E)
  5654. Xform of the include directive,
  5655. Xand set the include search path explicitly on the command line
  5656. Xused by the dependency maintenance tool.
  5657. X.LP
  5658. XThe dependency maintenance tool needs to be able to dynamically adapt
  5659. Xto include file dependencies,
  5660. Xbecause they are not static.
  5661. XThe presence of an include file in a change
  5662. Xmeans that any file which includes this include file,
  5663. Xwhether that source file is in the baseline or in the change,
  5664. Xmust have a dependency on the change's include file.
  5665. XPotentially,
  5666. Xfiles in the baseline will need to be recompiled,
  5667. Xand the object file stored in the change,
  5668. Xnot the baseline.
  5669. XSubsequent linking needs to pick up the object file
  5670. Xin the change, not from the baseline.
  5671. X.nh 2 "Renaming Include Files"
  5672. X.LP
  5673. XRenaming include files can be a disaster,
  5674. Xeither finding all of the clients,
  5675. Xor making sure the new copy is used rather than the old copy
  5676. Xstill in the baseline.
  5677. X.LP
  5678. XIf an include file is to be completely renamed,
  5679. Xnot moved to another directory
  5680. Xbut retain the same basename,
  5681. Xthen create a file in the development directory (\fIwithout\fP telling aegis)
  5682. Xwith the old name,
  5683. Xand put a syntax error in it.
  5684. XCompiles will fail very diagnostically,
  5685. Xand you can change the reference in the source file,
  5686. Xprobably after \fIaecp\fP(1)ing it first.
  5687. X.LP
  5688. XIf you are moving an include file from one directory to another,
  5689. Xbut leaving the basename unchanged,
  5690. Xcreate a link\**
  5691. X.FS
  5692. XA hard link uses fewer disk blocks.
  5693. XSymbolic links survive the subject file being deleted and recreated.
  5694. X.FE
  5695. Xbetween the new and old names,
  5696. Xbut only in the development directory.
  5697. XCreate the link after \fIaenf\fP(1)ing the new name.
  5698. XThis insulates you from a number of nasty Catch-22 situations
  5699. Xin writing the dependency maintenance tool's rules file.
  5700. X.nh 2 "Writing Tests"
  5701. X.LP
  5702. XThis section describes a number of things you can do to write better tests,
  5703. Xand some pitfalls to be avoided.
  5704. X.LP
  5705. XThe are a number of suggestions for portability of tests;
  5706. Xthis will definitely be important if you are writing software
  5707. Xto publish on USENET or for FTP.
  5708. XPortability is often require
  5709. X.I within
  5710. Xan organization, also.
  5711. XExamples include a change in company policy from one 386 
  5712. X.UX
  5713. Xto another
  5714. X(e.g. company doesn't like Linux, now you must use AT&T's SVR4 offering),
  5715. Xor the development team use
  5716. X.I gcc
  5717. Xuntil the company finds out and forces you to use the prototype-less
  5718. Xcompiler supplied with the operating system.
  5719. XThings like this really have happened to the author!
  5720. X.nh 3 "Bourne Shell"
  5721. X.LP
  5722. XThe aegis program mandates that all tests be Bourne shell scripts.
  5723. XThis is because this shell is available on all flavours of the
  5724. X.UX
  5725. Xoperating system.
  5726. XThe script files need not have execute permissions set,
  5727. Xbecause the aegis program always invokes them as
  5728. X.E(
  5729. Xsh \fIfilename\fP
  5730. X.E)
  5731. Xso tests should not expect command line arguments.
  5732. XThe test is not passed the name of the project nor the number of the change.
  5733. X.LP
  5734. XThis means that if you can write in in a shell script,
  5735. Xyou can test it.
  5736. XThis includes such things as client-server model interfaces,
  5737. Xand multi-user synchronization testing.
  5738. X.LP
  5739. XSome indication that the test script is a Bourne shell script is
  5740. Xa good idea.
  5741. XWhile many systems accept that a first line starting with a colon is a
  5742. XBourne shell "magic number",
  5743. Xa more widely understood "magic number" is
  5744. X.E(
  5745. X#! /bin/sh
  5746. X.E)
  5747. Xas the first line of the script file.
  5748. X.nh 3 "Current Directory"
  5749. X.LP
  5750. XTests are always run with the current directory set to either the
  5751. Xdevelopment directory
  5752. Xchange under test when testing a change,
  5753. Xor the integration directory when integrating a change,
  5754. Xor the baseline when performing independent tests.
  5755. X.LP
  5756. XA test must not make assumptions about where it is being executed from,
  5757. Xexcept to the extent that it is somewhere a build has been performed.
  5758. XA test must not assume that the current directory is writable,
  5759. Xand must not try to write to it,
  5760. Xas this could damage the source code of a change
  5761. Xunder development,
  5762. Xpotentially destroying weeks of work.
  5763. X.nh 3 "Check Exit Status"
  5764. X.LP
  5765. XA test script should check the exit status of every single command,
  5766. Xeven those which cannot fail.
  5767. XDo not rely on, or use, the
  5768. X.I "set -e"
  5769. Xshell option (it provides no ability to clean up on error).
  5770. X.LP
  5771. XChecking the exit status involves testing the contents of the
  5772. X.B $?
  5773. Xshell variable.
  5774. XDo not use an
  5775. X.I if
  5776. Xstatement wrapped around an execution of the program under test
  5777. Xas this will miss core dumps and other terminations caused by signals.
  5778. X.LP
  5779. XChecking the exit status of every command in the script
  5780. Xensures that strange permission settings,
  5781. Xor disk space problems,
  5782. Xwill cause the test to fail,
  5783. Xrather than plow on and produce spurious results.
  5784. X.nh 3 "Trap Interrupts"
  5785. X.LP
  5786. XUse the
  5787. X.I trap
  5788. Xstatement to catch interrupts 1 2 3 and 15 an cause the test to fail.
  5789. XThis should perform any cleanup the test requires
  5790. X(such as removing the temporary directory; see next item).
  5791. X.nh 3 "Temporary Directory"
  5792. X.LP
  5793. XTests should create a temporary directory in
  5794. X.I /tmp
  5795. Xand then
  5796. X.I cd
  5797. Xinto this directory.
  5798. X.LP
  5799. XThis tends to isolate any vandalism that the program under test may indulge in,
  5800. Xand serves as a place to write temporary files.
  5801. XAt the end of the test, it is sufficient to
  5802. X.I cd
  5803. Xout of the temporary directory and then
  5804. X.I "rm -rf"
  5805. Xit,
  5806. Xrather than track and remove all test files which may or may not be created.
  5807. X.nh 3 "PAGER"
  5808. X.LP
  5809. XIf the program under test invokes pagers on its output,
  5810. Xa la \fImore\fP(1) et al,
  5811. Xit should be coded to use the PAGER
  5812. Xenvironment variable.
  5813. XTests of such programs should always set PAGER to
  5814. X.I cat
  5815. Xso that tests always behave the same,
  5816. Xirrespective of invocation method (either by aegis or from the command line).
  5817. X.nh 3 "[ test ]"
  5818. X.LP
  5819. XYou should always use the
  5820. X.I test
  5821. Xcommand,
  5822. Xrather than the square bracket form,
  5823. Xas many systems do not have the square bracket form,
  5824. Xif you publish to USENET or for FTP.
  5825. X.nh 3 "Auxiliary Files"
  5826. X.LP
  5827. XIf a test requires extra files as input or output to a command,
  5828. Xit must construct them itself,
  5829. Xusing \fIhere\fP documents (see \fIsh\fP(1) for more information).
  5830. X.LP
  5831. XIt is almost impossible to determine the location of an auxiliary file,
  5832. Xif that auxiliary file is part of the project source.
  5833. XIt could be in either the change under test or the baseline.
  5834. X.nh 3 "New Test Templates"
  5835. X.LP
  5836. XIt is possible to specify most of the repetitious
  5837. Xitems above in a
  5838. X.I "file template"
  5839. Xused every time a user creates a new test.
  5840. XSee the \fIaent\fP(1) command for more information.
  5841. X.LP
  5842. XHaving the machine do it for you
  5843. Xmeans that you are more likely to do it.
  5844. X.nh 2 "Symbolic Links"
  5845. X.LP
  5846. XIf you are on a flavour of 
  5847. X.UX
  5848. Xwhich has symbolic links,
  5849. Xit is often useful to create a symbolic link from the development directory
  5850. Xto the baseline.
  5851. XThis can make browsing the baseline very simple.
  5852. X.LP
  5853. XAssuming that the project and change defaults are appropriate,
  5854. Xthe following command
  5855. X.E(
  5856. Xln -s `aegis -cd -bl` bl
  5857. X.E)
  5858. Xis all that is required to create a symbolic link called
  5859. X.I bl
  5860. Xpointing to the baseline.
  5861. XNote that the
  5862. X.I aecd
  5863. Xalias is inappropriate in this case.
  5864. X.LP
  5865. XThis can be done automatically for every change,
  5866. Xby placing the line
  5867. X.E(
  5868. Xdevelop_begin_command =
  5869. X    "ln -s $baseline bl";
  5870. X.E)
  5871. Xinto the
  5872. X.I config
  5873. Xfile.
  5874. X.nh 2 "User Setup"
  5875. X.LP
  5876. XThere are a number of things which users
  5877. Xof aegis can do to make it more useful,
  5878. Xor more user friendly.
  5879. XThis section describes just a few of them.
  5880. X.nh 3 "\&.cshrc"
  5881. X.LP
  5882. XThe aliases for the various user commands used throughout this manual
  5883. Xare obtained by appending a line of the form
  5884. X.E(
  5885. X.ps -2
  5886. Xsource /usr/local/lib/aegis/cshrc
  5887. X.ps +2
  5888. X.E)
  5889. Xto the
  5890. X.I \&.cshrc
  5891. Xfile in the user's home directory.
  5892. X.nh 3 "The AEGIS environment variable"
  5893. X.LP
  5894. XIf users wish to use aegis for their own projects,
  5895. Xin addition to the "system" projects,
  5896. Xthe
  5897. XAEGIS
  5898. Xenvironment variable forms a colon separated search path
  5899. Xof aegis "library" directories.
  5900. XThe
  5901. X.I /usr/local/lib/aegis
  5902. Xdirectory is always implicitly added to this list.
  5903. X.LP
  5904. XThe user should not create this library directory,
  5905. Xbut let aegis do this for itself (otherwise you will get an error message).
  5906. X.LP
  5907. XThe
  5908. X.I AEGIS
  5909. Xenvironment variable should be set in the
  5910. X.I \&.cshrc
  5911. Xfile in the user's home directory.
  5912. XTypical setting is
  5913. X.E(
  5914. Xsetenv AEGIS ~/lib/aegis
  5915. X.E)
  5916. X.nh 3 "The \&.aegisrc file"
  5917. X.LP
  5918. XThe
  5919. X.I \&.aegisrc
  5920. Xfile in the user's home directory
  5921. Xcontains a number of useful fields.
  5922. XSee
  5923. X.I aeuconf (5)
  5924. Xfor more information.
  5925. X.nh 3 "The defaulting mechanism"
  5926. X.LP
  5927. XIn order for you to specify the minimum possible information
  5928. Xon the command line,
  5929. Xaegis has been designed to work most of it out itself.
  5930. X.LP
  5931. XThe default project is the project which you are working on changes for,
  5932. Xif there is only one, otherwise it is gleaned from the
  5933. X.I \&.aegisrc
  5934. Xfile.
  5935. XThe command line overrides any default.
  5936. X.LP
  5937. XThe default change is the one you are
  5938. Xworking on within the (default or specified) project,
  5939. Xif there is only one.
  5940. XThe command line overrides any default.
  5941. X.nh 2 "The Project Owner"
  5942. X.LP
  5943. XFor the greatest protection from accidental change,
  5944. Xit is best if the project is owned by a
  5945. X.UX
  5946. Xaccount which is none of the staff.
  5947. XThis account is often named the same as the project,
  5948. Xor sometimes there is a single umbrella account for all projects.
  5949. X.LP
  5950. XWhen an aegis project is created,
  5951. Xthe owner is the user creating the project,
  5952. Xand the group is the user's default group.
  5953. XThe creating user is installed as the project's first administrator.
  5954. X.LP
  5955. XA new project administrator should be created - an actual user account.
  5956. XThe
  5957. X.UX
  5958. Xpassword should then be disabled on the project
  5959. Xaccount - it will never be necessary to use it again.\**
  5960. X.FS
  5961. XUnless bugs in aegis corrupt the database,
  5962. Xin which case repairs can be accomplished as
  5963. Xthe project account using a text editor.
  5964. X.FE
  5965. X.LP
  5966. XThe user nominated as project administrator many then assign
  5967. Xall of the other staff roles.
  5968. XAegis takes care of ensuring that the baseline is owned by the project account,
  5969. Xnot any of the other staff,
  5970. Xwhile development directories always belong to the developer
  5971. X(but the group will always be the project group,
  5972. Xirrespective of the developer's default group).
  5973. X.LP
  5974. XAll of the staff working on a project should be members of the
  5975. Xproject's group,
  5976. Xto be able to browse the baseline,
  5977. Xfor reviewers to be able to review changes.
  5978. XThis use of
  5979. X.UX
  5980. Xgroups means that projects may be as secure or open as desired.
  5981. X.nh 2 "USENET Publication Standards"
  5982. X.LP
  5983. XIf you are writing software to publish on USENET,
  5984. Xa number of the source newsgroups have publication standards.
  5985. XThis section describes ways of generating the following files,
  5986. Xrequired by many of the newsgroups' moderators:
  5987. X.TS
  5988. Xtab(;);
  5989. Xl lw(1.5i).
  5990. XMANIFEST;T{
  5991. XList of files in the distribution.
  5992. XT}
  5993. XMakefile;T{
  5994. XHow to build the distribution.
  5995. XT}
  5996. XCHANGES;T{
  5997. XWhat happened for this distribution.
  5998. XT}
  5999. Xpatchlevel.h;T{
  6000. XAn identification of this distribution.
  6001. XT}
  6002. X.TE
  6003. X.LP
  6004. XEach of these files may be generated from information
  6005. Xknown to aegis,
  6006. Xwith the aid of some fairly simple shell scripts.
  6007. X.nh 3 "CHANGES"
  6008. X.LP
  6009. XWrite this section.
  6010. X.LP
  6011. XLook in the
  6012. X.I aux/CHANGES.sh
  6013. Xfile included in the aegis distribution
  6014. Xfor an example of one way to do this.
  6015. X.nh 3 "MANIFEST"
  6016. X.LP
  6017. XWrite this section.
  6018. X.LP
  6019. XLook in the
  6020. X.I aux/MANIFEST.sh
  6021. Xand
  6022. X.I aux/MANIFEST.awk
  6023. Xfiles included in the aegis distribution
  6024. Xfor an example of one way to do this.
  6025. X.nh 3 "Makefile"
  6026. X.LP
  6027. XWrite this section.
  6028. X.LP
  6029. XLook in the
  6030. X.I aux/Makefile.sh
  6031. Xand
  6032. X.I aux/Makefile.awk
  6033. Xfiles included in the aegis distribution
  6034. Xfor an example of one way to do this.
  6035. X.nh 3 "patchlevel.h"
  6036. X.LP
  6037. XWrite this section.
  6038. X.LP
  6039. XLook in the
  6040. X.I aux/Howto.cook
  6041. Xfile included in the aegis distribution
  6042. Xfor an example of one way to do this.
  6043. X.nh 3 "Building Patch Files"
  6044. X.LP
  6045. XThe
  6046. X.I patch
  6047. Xprogram by Larry Wall is one of the enduring marvels of USENET.
  6048. XThis section describes how to build input files
  6049. Xfor this miracle program.
  6050. X.LP
  6051. XWrite this section.
  6052. X.LP
  6053. XLook in the
  6054. X.I aux/patches.sh
  6055. Xfile included in the aegis distribution
  6056. Xfor an example of one way to do this.
  6057. X.1C
  6058. END_OF_FILE
  6059. if test 13918 -ne `wc -c <'doc/c6.0.so'`; then
  6060.     echo shar: \"'doc/c6.0.so'\" unpacked with wrong size!
  6061. fi
  6062. # end of 'doc/c6.0.so'
  6063. fi
  6064. echo shar: End of archive 9 \(of 19\).
  6065. cp /dev/null ark9isdone
  6066. MISSING=""
  6067. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ; do
  6068.     if test ! -f ark${I}isdone ; then
  6069.     MISSING="${MISSING} ${I}"
  6070.     fi
  6071. done
  6072. if test "${MISSING}" = "" ; then
  6073.     echo You have unpacked all 19 archives.
  6074.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  6075. else
  6076.     echo You still need to unpack the following archives:
  6077.     echo "        " ${MISSING}
  6078. fi
  6079. ##  End of shell archive.
  6080. exit 0
  6081.