home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OS9000 / APPS / rcs.lzh / rcs1 / srcin.c < prev    next >
C/C++ Source or Header  |  1996-04-22  |  22KB  |  809 lines

  1. static char RCSid[]="$Header: srcin.c_v 1.11 96/04/23 01:59:03 hiro Exp $";
  2. /************************************************************************
  3. Copyright (c) 1993 ARK Systems USA
  4. All rights reserved.
  5.  
  6. Program: srcin - "ci" check-in utility
  7.    File: srcin.c
  8.  
  9. $Date: 96/04/23 01:59:03 $
  10. $Revision: 1.11 $
  11.  
  12. $Log:    srcin.c_v $
  13.  * Revision 1.11  96/04/23  01:59:03  hiro
  14.  * Excluded inclusion of <stdlib.h> for OS-9.
  15.  * 
  16.  * Revision 1.10  96/04/21  01:20:58  hiro
  17.  * Ported to OS-9000.
  18.  * 
  19.  * Revision 1.9  96/04/07  00:29:24  hiro
  20.  * Ported to OS-9000.
  21.  * 
  22.  * Revision 1.8  94/05/29  16:59:31  hiro
  23.  * Update
  24.  * ================================================================
  25.  * Added -r option for forced revision number.
  26.  * ================================================================
  27.  * 
  28.  * Revision 1.7  93/12/09  01:59:48  hiro
  29.  * Prototype
  30.  * ================================================================
  31.  * Added automatic update of edition numbers.
  32.  * ================================================================
  33.  * 
  34.  * Revision 1.6  93/10/31  22:28:25  hiro
  35.  * Prototype
  36.  * ================================================================
  37.  * Added $(ENV_PREFIX)_float treatment.
  38.  * -N and -n options are no longer valid.
  39.  * ================================================================
  40.  * 
  41.  * Revision 1.5  93/04/06  22:23:05  hiro
  42.  * Prototype
  43.  * ================================================================
  44.  * Added -n/-N option that is passed to ci.
  45.  * ================================================================
  46.  * 
  47.  * Revision 1.4  93/04/03  01:23:41  hiro
  48.  * Update
  49.  * ================================================================
  50.  * 1. Refined copyright message for initial check-in.
  51.  * 2. Temporarily removed original modification time stamp recovery
  52.  *    logic.
  53.  * ================================================================
  54.  * 
  55.  * Revision 1.4  93/04/03  01:21:09  hiro
  56.  * Update
  57.  * ================================================================
  58.  * 1. Refined copyright message for initial check-in.
  59.  * 2. Temporariry removed original modification recovery.
  60.  * ================================================================
  61.  * 
  62. ************************************************************************/
  63. #ifdef _UCC
  64. _asm("_sysedit: equ 3");
  65. #else
  66. @_sysedit: equ 3
  67. #define remove unlink
  68. #endif
  69.  
  70. #ifdef _OS9000
  71. #include <io.h>
  72. #else
  73. #include <sysio.h>
  74. #endif
  75.  
  76. #include <stdio.h>
  77. #if defined(__STDC__) || defined(_OS9000)
  78. #include <stdlib.h>
  79. #else
  80. extern void *malloc();
  81. extern char *getenv();
  82. #endif
  83. #include <strings.h>
  84. #include <ctype.h>
  85. #include <time.h>
  86. #include <errno.h>
  87.  
  88. #include <modes.h>
  89. #include <rbf.h>
  90.  
  91. FILE *namefile;
  92. char **files;
  93. char *nextfile();
  94. extern   char *_prgname();
  95.  
  96. #ifdef _OS9000
  97. #define environ    _environ
  98. #define mod_exec mh_com
  99. extern   int  _os_fork();
  100. #else
  101. extern   int  os9forkc();
  102. #endif
  103. extern   mod_exec *modlink(), *modloadp();
  104.  
  105. #ifdef __STDC__
  106. extern   char *tmpnam();
  107. #else
  108. #define tmpnam(s)    mktemp(strcpy((s),"_srcin$XXXXXX"))
  109. extern   char *mktemp();
  110. #endif
  111.  
  112. #ifndef SEEK_SET
  113. #define SEEK_SET    0
  114. #define SEEK_CUR    1
  115. #define SEEK_END    2
  116. #endif
  117.  
  118. #ifndef EXEC_
  119. #define READ_    S_IREAD
  120. #define EXEC_    S_IEXEC
  121. #endif
  122.  
  123. #ifndef L_tmpnam
  124. #define L_tmpnam    14
  125. #endif
  126.  
  127. extern   char *environ;
  128.  
  129. #define  CIPROG   "ci"
  130. #define  RLPROG   "rlog"
  131.  
  132. char *ENVFILENAME = "ENVIRONMENT";
  133.  
  134. char *ENV_PREFIX;
  135.  
  136. char tfname[L_tmpnam], *logmsg, *nopt;
  137. mod_exec *cimp, *edmp, *rlmp;
  138. int  stop;
  139.  
  140. char revision[80];
  141.  
  142. /*---------------------------------------------------------
  143. ! clean-up procedure at exit
  144. */
  145. void cleanup(err, cstr, a)
  146.      int  err;
  147.      char *cstr, *a;
  148. {
  149.      if (tfname[0])
  150.           remove(tfname);
  151.      if (cimp)
  152.           munlink(cimp);
  153.      if (edmp)
  154.           munlink(edmp);
  155.      if (cstr)
  156.           exit(_errmsg(err, cstr, a));
  157.      else exit(err);
  158. }
  159.  
  160. /*---------------------------------------------------------
  161. ! fork and wait a program
  162. */
  163. int  runprog(args)
  164.      char *args[];
  165. {
  166. int  status;
  167. #ifdef _OS9000
  168. process_id pid;
  169.  
  170.      if (errno = os9kexec(_os_fork, 0, 3, *args, args, environ,
  171.                              0, &pid, mktypelang(MT_PROGRAM, ML_OBJECT), 0))
  172. #else
  173. int pid;
  174.  
  175.      if ((pid = os9exec(os9forkc, *args, args, environ, 0, 0, 3)) == -1)
  176. #endif
  177.           cleanup(errno, "can't fork \"%s\". ", *args);
  178.      while (wait(&status) != pid)
  179.           ;
  180.      return status;
  181. }
  182.  
  183. /*---------------------------------------------------------
  184. ! fork and wait ci program
  185. */
  186. int  runci(opt1, opt2, file)
  187. char *opt1, *opt2, *file;
  188. {
  189. static char *args[] = {CIPROG, "-u", NULL, NULL, NULL, NULL, NULL, NULL, NULL};
  190. int  i;
  191. char floatbuf[256];
  192.  
  193.      args[2] = opt1;
  194.      if (args[i = 3] = opt2)
  195.           i++;
  196.      sprintf(floatbuf, "-N%s_float", ENV_PREFIX);
  197.      if (revision[0])
  198.          args[i++] = revision;
  199.      args[i++] = floatbuf;
  200.      args[i++] = file;
  201.      args[i++] = NULL;
  202.      return runprog(args);
  203. }
  204.  
  205. /*---------------------------------------------------------
  206. ! initial check-in
  207. */
  208. void initci(file)
  209. register char *file;
  210. {
  211. static char *dirbuf = NULL, buf[256], desc[L_tmpnam+10];
  212. static int  numdirs;
  213. FILE *fp;
  214. register int i, dfsize;
  215. register char *p;
  216.  
  217.      fputs("Is this a new check-in? [yn Esc to abort] (y) ", stderr);
  218.      fflush(stderr);
  219.      if (!fgets(buf, sizeof buf, stdin))
  220.           cleanup(0, "Aborted.\n", NULL);
  221.      if (toupper(buf[0]) != 'Y' && buf[0] != '\n')
  222.      {
  223.           fprintf(stderr, "** \"%s\" skipped... **\n", file);
  224.           return;
  225.      }
  226.  
  227.   /* set up RCS directory list if this is the first time */
  228.      if (!dirbuf)
  229.           if (fp = fopen("RCSDIR", "r"))
  230.           {
  231.                fseek(fp, 0L, SEEK_END);
  232.                dfsize = ftell(fp);
  233.                if (!(dirbuf = malloc(dfsize + 10)))
  234.                     cleanup(errno, "can't allocate directory name buffer. ", NULL);
  235.                rewind(fp);
  236.                for (p = dirbuf, numdirs = 1; fgets(p, dfsize, fp); )
  237.                     if (*p && *p != '#' && *p != '*' && !isspace(*p))
  238.                     {
  239.                          p += strlen(p);
  240.                          if (*(p - 1) == '\n')
  241.                               *(p - 1) = '\0';
  242.                          else p++;
  243.                          numdirs++;
  244.                     }
  245.                fclose(fp);
  246.                strcpy(p, "RCS");
  247.           }
  248.           else
  249.           {
  250.                dirbuf = "RCS";
  251.                numdirs = 1;
  252.           }
  253.  
  254.   /* choose a directory to check-in into */
  255.      for (p = dirbuf, i = numdirs; i > 0; p += strlen(p) + 1, i--)
  256.      {
  257.           do
  258.           {
  259.                fprintf(stderr, "Check-in into directory \"%s\"? [yn] (y) ", p);
  260.                fflush(stderr);
  261.           } while (!fgets(buf, sizeof buf, stdin));
  262.  
  263.           if (toupper(buf[0]) == 'Y' || buf[0] == '\n')
  264.           {
  265.                if (!tfname[0])
  266.                {/* set up description file */
  267.                time_t today;
  268.  
  269.                     if (!(fp = fopen(tmpnam(tfname), "w")))
  270.                     {
  271.                          _errmsg(errno, "can't create descrition temporary file \"%s\".\n",
  272.                                  tfname);
  273.                          tfname[0] = '\0';
  274.                          goto failed;
  275.                     }
  276.                     time(&today);
  277. #ifdef __STDC__
  278.                     strftime(buf, sizeof buf, "%Y", localtime(&today));
  279. #else
  280.                     sprintf(buf, "%d", localtime(&today)->tm_year + 1900);
  281. #endif
  282.         fprintf(fp, "*******************************************\n\n");
  283.         fprintf(fp, "  Unless otherwise noted, this program is:\n\n");
  284.         fprintf(fp, "       Copyright %s ARK Systems USA\n", buf);
  285.         fprintf(fp, "            All rights reserved.\n");
  286.         fprintf(fp, "*******************************************\n");
  287.                     fclose(fp);
  288.                     sprintf(desc, "-t%s", tfname);
  289.                }
  290.  
  291.                sprintf(buf, "%s/%s_v", p, file);
  292.                runci(desc, nopt, buf);
  293.                return;
  294.           }
  295.      }
  296. failed:
  297.      fprintf(stderr, "** \"%s\" was not checked-in **\n", file);
  298. }
  299.  
  300. /*---------------------------------------------------------
  301. ! check-in into existing RCS file
  302. */
  303. void doci(file)
  304. register char *file;
  305. {
  306.      runci(logmsg, NULL, file);
  307. }
  308.  
  309. /*---------------------------------------------------------
  310.  * look for 2 tokens from the beginning
  311.  * return location of 3rd token (must be a number)
  312.  */
  313. char *gettokens(buf, tok1, tok2)
  314. register char *buf, *tok1, *tok2;
  315. {
  316. int tlen;
  317.  
  318.     if (strncmp(buf, tok1, tlen = strlen(tok1)))
  319.         return NULL;
  320.     buf += tlen;
  321.     if (!isspace(*buf))
  322.         return NULL;
  323.     do
  324.         buf++;
  325.     while (isspace(*buf));
  326.     if (strncmp(buf, tok2, tlen = strlen(tok2)))
  327.         return NULL;
  328.     buf += tlen;
  329.     if (!isspace(*buf))
  330.         return NULL;
  331.     do
  332.         buf++;
  333.     while (isspace(*buf));
  334.     return isdigit(*buf) ? buf : NULL;
  335. }
  336.  
  337. /*---------------------------------------------------------
  338.  * look for possible token and return edition number position
  339.  */
  340. char *foundit(buf, fname)
  341. char *buf, *fname;
  342. {
  343. register char *p;
  344.  
  345.     if (!strcmp(fname + strlen(fname) - 2, ".a"))
  346.     {
  347.         if (p = gettokens(buf, "edition", "equ"))
  348.             return p;
  349.         if (p = gettokens(buf, "edition:", "equ"))
  350.             return p;
  351.         if (p = gettokens(buf, "Edition", "equ"))
  352.             return p;
  353.         if (p = gettokens(buf, "Edition:", "equ"))
  354.             return p;
  355.         return NULL;
  356.     }
  357.  
  358.     if (!strcmp(fname + strlen(fname) - 2, ".c"))
  359.     {
  360.     /* first, check old CC style #asm and @ */
  361.         if (p = gettokens(buf, "_sysedit:", "equ"))
  362.             return p;
  363.         if (p = gettokens(buf, "@_sysedit:", "equ"))
  364.             return p;
  365.     /* next, check UCC style _asm() */
  366.         while (isspace(*buf))
  367.             buf++;    /* skip leading spaces */
  368.         if (strncmp(buf, "_asm", 4))
  369.             return NULL;
  370.         buf += 4;
  371.         while (isspace(*buf))
  372.             buf++;
  373.         if (*buf != '(')
  374.             return NULL;
  375.         do
  376.             buf++;
  377.         while (isspace(*buf));
  378.         return gettokens(buf, "\"_sysedit:", "equ");
  379.     }
  380.     return NULL;
  381. }
  382.  
  383. /*---------------------------------------------------------
  384.  * update edition number
  385.  */
  386. char *updateit(fname, buf, p)
  387. register char *fname, *buf, *p;
  388. {
  389. int edition = atoi(p) + 1;
  390. char tbuf[10];
  391.  
  392.     fprintf(stderr, "`%.*s' -> ", strlen(buf) - 1, buf);
  393.     if (edition == 10 || edition == 100 || edition == 1000 || edition == 10000)
  394.         memcpy(p + 1, p, strlen(p));    /* make more room */
  395.     sprintf(tbuf, "%d", edition);
  396.     memcpy(p, tbuf, strlen(tbuf));
  397.     fprintf(stderr, "`%s\'.\n", tbuf);
  398.     return buf;
  399. }
  400.  
  401. /*---------------------------------------------------------
  402.  * process edition number in a file
  403.  */
  404. void procedition(fname)
  405. register  char *fname;
  406. {
  407. register  FILE *fp, *tfp;
  408. register  char *p, *tname;
  409. char buf[256], answer[10];
  410. int updated = 0;
  411.  
  412. #ifdef __STDC__
  413.     tname = tmpnam(NULL);
  414. #else
  415. static char template[] = "srcin$XXXXXX";
  416.  
  417.     tname = mktemp(template);
  418. #endif
  419.     if (!(tfp = fopen(tname, "w")))
  420.         exit(_errmsg(errno, "can't open temporary file \"%s\". ", tname));
  421.     if (!(fp = fopen(fname, "r")))
  422.         exit(_errmsg(errno, "can't open \"%s\". ", fname));
  423.  
  424.     /* process each line */
  425.     while (fgets(buf, sizeof buf, fp))
  426.     {
  427.         if (p = foundit(buf, fname))
  428.         {
  429.             fprintf(stderr, "%s: `%.*s' found; update? ([y]/n) ",
  430.                         fname, strlen(buf) - 1, buf);
  431.             fflush(stderr);
  432.             if (fgets(answer, sizeof answer, stdin)
  433.                 && toupper(answer[0]) != 'N')
  434.             {
  435.                 updateit(fname, buf, p);
  436.                 updated++;
  437.             }
  438.         }
  439.         fputs(buf, tfp);
  440.     }
  441.     /*
  442.     if (updated)
  443.         _ss_attr(fileno(fp), _gs_attr(fileno(fp))|S_IWRITE|S_PWRITE);
  444.     */
  445.     fclose(fp);
  446.     fclose(tfp);
  447.  
  448.     if (updated) {
  449.         fprintf(stderr, "%s: updating edition number...\n", fname);
  450.         if (rename(tname, fname))
  451.             exit(_errmsg(errno, "can't rename \"%s\" to \"%s\". ",tname,fname));
  452.         putc('\n', stderr);
  453.     }
  454.     else {
  455.         if (remove(tname))
  456.             exit(_errmsg(errno, "can't remove \"%s\". ", tname));
  457.     }
  458. }
  459. /*---------------------------------------------------------
  460. ! process each file
  461. */
  462. void process(file)
  463. register char *file;
  464. {
  465. static char *args[4] = {RLPROG, "-b%w: %r", NULL, NULL};
  466. register char *p;
  467. int  pn;
  468. #if 0
  469. struct fd orgfd, tmpfd;
  470.  
  471.      if ((pn = open(file, 0)) == -1)
  472.      {
  473.           fprintf(stderr, "** \"%s\" not found. Skipped... **\n", file);
  474.           return;
  475.      }
  476.      _gs_gfd(pn, &orgfd, 16);
  477.      close(pn);
  478. #endif
  479.      procedition(file);
  480.      args[2] = file;
  481.      if (runprog(args))
  482.           initci(file);
  483.      else doci(file);
  484.  
  485. #if 0
  486.   /* recover original modified date/time */
  487.      if (!(orgfd.fd_att & S_IWRITE))
  488.      {
  489.           if ((pn = open(file, 0)) == -1)
  490.           {
  491.                fprintf(stderr, "** \"%s\" was found but now not. Strange... **\n", file);
  492.                goto failed;
  493.           }
  494.           _ss_attr(pn, orgfd.fd_att | S_IWRITE);
  495.           close(pn);
  496.      }
  497.  
  498.      if ((pn = open(file, S_IREAD+S_IWRITE)) == -1)
  499.      {
  500.           fprintf(stderr, "** \"%s\" can't be opened for date/time recovery **\n", file);
  501.           goto failed;
  502.      }
  503.  
  504.      _gs_gfd(pn, &tmpfd, 16);
  505.      memcpy(&orgfd.fd_own, &tmpfd.fd_own, 2);
  506.      _ss_pfd(pn, &orgfd, 16);
  507.      _ss_attr(pn, orgfd.fd_att);
  508.      close(pn);
  509. failed:
  510. #endif
  511.      if (stop)
  512.           cleanup(stop, "Stopped by signal.\n", NULL);
  513. }
  514.  
  515. mod_exec *mlinkload(mod)
  516. char *mod;
  517. {
  518. mod_exec *mp;
  519.  
  520.      if ((int)(mp = modlink(mod, mktypelang(MT_PROGRAM, ML_OBJECT))) == -1 &&
  521.          (int)(mp = modloadp(mod, EXEC_, NULL)) == -1 && 
  522.          (int)(mp = modloadp(mod, READ_, NULL)) == -1)
  523.           cleanup(errno, "can't find \"%s\". ", mod);
  524. }
  525.  
  526. void put_env(pp, p)
  527. char **pp, *p;
  528. {
  529.      if (!(*pp = malloc(strlen(p)+1)))
  530.           exit(_errmsg(errno, "can't allocate buffer. "));
  531.      strcpy(*pp, p);
  532. }
  533.  
  534. void getenvironment()
  535. {
  536. register FILE *fp;
  537. register char *p;
  538. char buf[256];
  539.  
  540.      if (!(fp = fopen(ENVFILENAME, "r")))
  541.           exit(_errmsg(errno, "can't open environment file \"%s\". ", ENVFILENAME));
  542.      while ((p = fgets(buf, sizeof buf, fp)))
  543.      {
  544.           if (p[strlen(p) - 1] == '\n')
  545.                p[strlen(p) - 1] = '\0';
  546.           if (!strncmp(p, "ENV_PREFIX=", 11) && isalpha(p[1]))
  547.                put_env(&ENV_PREFIX, p + 11);
  548.      }
  549.      if (!ENV_PREFIX)
  550.           exit(_errmsg(1, "can't find ENV_PREFIX.\n"));
  551.      fclose(fp);
  552. }
  553.  
  554. void intcpt(sig)
  555. {
  556.      stop = sig;
  557. }
  558.  
  559. main(argc, argv)
  560. int  argc;
  561. char *argv[];
  562. {
  563. register char *file, *cstr = NULL, *editor = NULL;
  564. register char *p, **fpp;
  565. register int  ch, waseq = 0;
  566. long tfsize;
  567. register FILE *cfp = NULL, *tfp;
  568. char buf[80], *args[3];
  569.  
  570.      files = fpp = argv;
  571.      while (--argc)
  572.      {
  573.           if (*(p = *++argv) == '-')
  574.           {
  575.                ++p;
  576.                while (ch = *p++)
  577.                {
  578.                     waseq = *p == '=';
  579.                     if (waseq)
  580.                          ++p;
  581.                     switch (ch)
  582.                     {
  583.                     case 'c':
  584.                          if (cstr)
  585.                               exit(_errmsg(1, "only one log comment string allowed.\n"));
  586.                          else if (cfp)
  587.                               exit(_errmsg(1, "either comment string or file allowed.\n"));
  588.                          else if (!*(cstr = p))
  589.                               exit(_errmsg(1, "empty log comment string.\n"));
  590.                          break;
  591.                     case 'C':
  592.                          if (cfp)
  593.                               exit(_errmsg(1, "only one log comment file allowed.\n"));
  594.                          else if (cstr)
  595.                               exit(_errmsg(1, "either comment string or file allowed.\n"));
  596.                          else if (!(cfp = fopen(p, "r")))
  597.                               exit(_errmsg(errno, "can't open log comment file \"%s\". ", p));
  598.                          break;
  599.                     case 'n':
  600.                     case 'N':
  601.                          if (waseq)
  602.                               exit(_errmsg(1, "n/N options can't have '='.\n"));
  603.                          nopt = p - 2;
  604.                          break;
  605.                     case 'r':
  606.                          sprintf(revision, "-u%s", p);
  607.                          break;
  608.                     case 'e':
  609.                          editor = p;
  610.                          break;
  611.                     case 'z':
  612.                          if (namefile)
  613.                               exit(_errmsg(
  614.                                     1,"only one file of names allowed.\n"));
  615.                          if (waseq)
  616.                          {
  617.                               if ((namefile = fopen(p,"r")) == NULL)
  618.                                    exit(_errmsg(errno,
  619.                                                 "can't open \"%s\". ",p));
  620.                          }
  621.                          else
  622.                          {
  623.                               namefile = stdin;
  624.                               continue;
  625.                          }
  626.                          break;
  627.                     default:
  628.                          prtuse(_errmsg(1,"unknown option '%c'.\n\n",ch));
  629.                     case '?':
  630.                          prtuse(0);
  631.                     }
  632.                     break;
  633.                }
  634.           }
  635.           else *fpp++ = p;
  636.      }
  637.      *fpp = NULL;
  638.  
  639.      if (fpp == files && namefile == NULL)
  640.           exit(_errmsg(1, "no files to check in.\n"));
  641.      else if (!editor && !(editor = getenv("EDITOR")))
  642.           exit(_errmsg(1, "no editor selected.\n"));
  643.  
  644.      getenvironment();
  645.  
  646.      cimp = mlinkload(CIPROG);
  647.      edmp = mlinkload(editor);
  648.      rlmp = mlinkload(RLPROG);
  649.  
  650.   /* set up comment file */
  651.      if (!(tfp = fopen(tmpnam(tfname), "w+")))
  652.           exit(_errmsg(errno, "can't create comment temporary file \"%s\". ", tfname));
  653.   /* ask for reason to change interactively */
  654.      fputs("\nReason for change:\n\n", stderr);
  655.      fputs("  P - Prototype\n  B - Bug fix\n  E - Enhancement\n  R - Code review\n", stderr);
  656.      fputs("  U - Update\n  A - Abort\n\n", stderr);
  657.      while (1)
  658.      {
  659.           fputs("Enter P, B, E, R, U, or A: ", stderr);
  660.           fflush(stderr);
  661.           fgets(buf, sizeof(buf), stdin);
  662.           switch (toupper(*buf))
  663.           {
  664.           case 'P':
  665.                fputs("Prototype\n", tfp); break;
  666.           case 'B':
  667.                fputs("Bug Fix #\n", tfp); break;
  668.           case 'E':
  669.                fputs("Enhancement\n", tfp); break;
  670.           case 'R':
  671.                fputs("Code Review\n", tfp); break;
  672.           case 'U':
  673.                fputs("Update\n", tfp); break;
  674.           case 'A':
  675.                cleanup(0, NULL, NULL);
  676.           default:
  677.                continue;
  678.           }
  679.           break;
  680.      }
  681.  
  682.      fputs("================================================================\n", tfp);
  683.      if (cstr)
  684.           fprintf(tfp, "%s\n", cstr);
  685.      else if (cfp)
  686.      {
  687.           while ((ch = getc(cfp)) != EOF)
  688.                putc(ch, tfp);
  689.           putc('\n', tfp);
  690.           fclose(cfp);
  691.      }
  692.      fseek(tfp, 0L, SEEK_END);
  693.      tfsize = ftell(tfp);
  694.      fclose(tfp);
  695.  
  696.   /* invoke editor */
  697.      args[0] = editor;
  698.      args[1] = tfname;
  699.      args[2] = NULL;
  700.      do
  701.      {
  702.           if (ch = runprog(args))
  703.                cleanup(ch, NULL, NULL);
  704.           while (1)
  705.           {
  706.                fputs("Abort, Edit, Continue? (C) ", stderr);
  707.                fflush(stderr);
  708.                fgets(buf, sizeof(buf), stdin);
  709.                switch (toupper(*buf))
  710.                {
  711.                case 'A':
  712.                     cleanup(0, NULL, NULL);
  713.                case 'E':
  714.                case 'C':
  715.                     break;
  716.                default:
  717.                     continue;
  718.                }
  719.                break;
  720.           }
  721.      } while (toupper(*buf) != 'C');
  722.  
  723.      if (!(tfp = fopen(tfname, "r+")))
  724.           cleanup(errno, "can't create log message temporary file \"%s\". ", tfname);
  725.      fseek(tfp, 0L, SEEK_END);
  726.      if (tfsize == ftell(tfp))
  727.      {/* size not changed */
  728.           fprintf(stderr, "\nNo log message entered - Forced check-in.\n");
  729.           logmsg = "-mForced check-in.\n";
  730.      }
  731.      else
  732.      {
  733.           fseek(tfp, -1, SEEK_END);
  734.           if (getc(tfp) != '\n')
  735.                putc('\n', tfp);
  736.           fputs("================================================================\n", tfp);
  737.           fseek(tfp, 0L, SEEK_END);
  738.           if (!(logmsg = malloc((ch = ftell(tfp)) + 10)))
  739.           cleanup(errno, "can't alloacte logmessage buffer. ", NULL);
  740.           strcpy(logmsg, "-m");
  741.           rewind(tfp);
  742.           fread(logmsg + 2, ch, 1, tfp);
  743.           logmsg[ch + 2] = '\0';
  744.      }
  745.      fclose(tfp);
  746.      remove(tfname);
  747.      tfname[0] = '\0';
  748.  
  749.      while (file = nextfile())
  750.           process(file);
  751.      cleanup(0, NULL, NULL);
  752. }
  753.  
  754.  
  755. char *nextfile()
  756. {
  757. register char *file = NULL;
  758. static char nambuf[120];
  759.  
  760.      if (file = *files)
  761.           ++files;
  762.      else if (namefile)
  763.      {
  764.           if ((file = fgets(nambuf,sizeof nambuf,namefile)) == NULL)
  765.           {
  766.                if (ferror(namefile))
  767.                     exit(_errmsg(errno,"can't read name file.\n"));
  768.                fclose(namefile);
  769.                namefile = NULL;
  770.           }
  771.           else *(file + strlen(file) - 1) = '\0';
  772.      }
  773.  
  774.      return file;
  775. }
  776.  
  777.  
  778. /**--------------------------------------------------------------
  779. !    cmds[] - array of pointers to strings of help text
  780. !*/
  781. static char *cmds[] = {
  782.        "Function: check in files\n",
  783.        "Options:\n",
  784.        "    -c=<log>      log comment string\n",
  785.        "    -C=<file>     read log comment strings from file\n",
  786.        "    -e=<editor>   use <editor> instead of $EDITOR\n",
  787. #if 0  /* removed for ***_float is introduced */
  788.        "    -n<symbolic label> assign <symbolic label> to this revision\n",
  789.        "    -N<symbolic label> force to assign <symbolic label> to this revision\n",
  790. #endif
  791.        "    -r<revision>  check in as <revision>\n",
  792.        "    -z[=<file>]   read list of files from standard input or <file>\n"
  793. };
  794.  
  795. /**--------------------------------------------------------------
  796. !    printuse - print the help text to standard error.
  797. !*/
  798. static prtuse(stat)
  799.      int stat;
  800. {
  801. register char **p = cmds,
  802.               **e = cmds + sizeof cmds / sizeof (char *);
  803.  
  804.      fprintf(stderr,"Syntax: %s {<opts>} [<file>] {<opts>}\n", _prgname());
  805.      while (p < e)
  806.           fputs(*p++,stderr);
  807.      exit(stat);
  808. }
  809.