home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume3 / rcsit / rcsit.c < prev   
Encoding:
C/C++ Source or Header  |  1986-11-30  |  14.5 KB  |  653 lines

  1. /*
  2.  * $Header: rcsit.c,v 1.18 85/11/26 17:03:32 mcooper Exp $
  3.  *---------------------------------------------------------
  4.  * $Source: /u/mcooper/src/rcsit/RCS/rcsit.c,v $
  5.  * $Revision: 1.18 $
  6.  * $Date: 85/11/26 17:03:32 $
  7.  * $State: Exp $
  8.  * $Author: mcooper $
  9.  * $Locker: mcooper $
  10.  *---------------------------------------------------------
  11.  * Michael Cooper (mcooper@usc-oberon.arpa)
  12.  * University of Southern California,
  13.  * University Computing Services,
  14.  * Los Angeles, California,   90089-0251
  15.  * (213) 743-3469
  16.  *---------------------------------------------------------
  17.  *
  18.  * $Log:    rcsit.c,v $
  19.  * Revision 1.18  85/11/26  17:03:32  mcooper
  20.  * Change message telling of what header was added.
  21.  * 
  22.  * Revision 1.17  85/11/26  16:40:55  mcooper
  23.  * Changed the default -t option to FALSE.
  24.  * Added specifying directory to look for .template.*
  25.  * files in via -tdirectory.
  26.  * 
  27.  * Revision 1.16  85/11/11  21:35:34  mcooper
  28.  * Added call to access() to see if the file
  29.  * could be read.
  30.  * 
  31.  * Revision 1.15  85/11/11  21:22:33  mcooper
  32.  * Changed comment char for fortran files
  33.  * from "*" to "c".  This is what RCS uses.
  34.  * 
  35.  * Revision 1.14  85/11/11  20:08:43  mcooper
  36.  * Added descriptions for fortran (.f) files.
  37.  * 
  38.  * Revision 1.13  85/11/11  19:52:17  mcooper
  39.  * Modified default header templates to not bother specifying
  40.  * the RCS file name of the file.  co(1) worries about it.
  41.  * 
  42.  * Revision 1.12  85/10/27  19:10:07  mcooper
  43.  * Fixed bug that would not use template files if a file
  44.  * type was forced with -c, -h, etc.
  45.  * 
  46.  * Revision 1.11  85/10/27  18:48:27  mcooper
  47.  * Extended template file.  You can now have template
  48.  * files describing all the types of files that
  49.  * rcsit "knows" about.  The file $HOME/.template.*
  50.  * (where ``*'' is a ``.'' suffix rcsit can guess at or
  51.  * the type of file that is specified with an override)
  52.  * is checked for existance.  If not present, the default
  53.  * header (built into rcsit) will be used.
  54.  * 
  55.  * Revision 1.10  85/10/27  16:15:53  mcooper
  56.  * Added printing of what rcsit is doing if tflag is
  57.  * true.  Also added new headers.
  58.  * 
  59.  * Revision 1.9  85/10/27  14:47:39  mcooper
  60.  * Added new template feature.  If the file
  61.  * .template exists in the users HOME directory,
  62.  * then that file is used as the header file instead
  63.  * of the defaults for each type of file.  This can
  64.  * be disabled with the -t option in case the file
  65.  * is say a shell script.  With the template feature
  66.  * turned off, the auto guessing is re-inabled.
  67.  * Also, rcsit now removes its temporary files.
  68.  * 
  69.  * Revision 1.8  85/09/28  14:11:45  mcooper
  70.  * Added feature: if the environment variable RCSDIR is
  71.  * present, rcsit will attempt to make a symbolic
  72.  * link to the directory when the -I flag is used.
  73.  * This is done only when -I is specified AND the 
  74.  * directory RCS is not present.  You may disable this
  75.  * feature with the -d option.  Note also that if RCSDIR
  76.  * is not in the environment and the above conditions
  77.  * are true, that a normal directory called RCS will
  78.  * be created.
  79.  * 
  80.  * Revision 1.7  85/09/19  15:59:53  mcooper
  81.  * Kludge part 2 -- If you specify a ci -l of a
  82.  * man file, then the header is messed up. 
  83.  * Fix: After initializing the comment string,
  84.  * unlink the file and then run co -l.
  85.  * 
  86.  * Revision 1.6  85/09/19  15:39:57  mcooper
  87.  * Now knows about ``Manual'' type files.
  88.  * 
  89.  * Revision 1.5  85/09/19  14:23:24  mcooper
  90.  * Added lineprint() function to print things out
  91.  * nicely.  Fixed bug for Manual type files.  Due
  92.  * to the fact that RCS does not not the suffixes of
  93.  * manuals, it therefor does not know what kind of
  94.  * comment string to use.  Thus, I kludge by running
  95.  * a ``rcs -c`... ' file'' to tell rcs the comment
  96.  * string.
  97.  * 
  98.  * Revision 1.4  85/09/19  13:28:22  mcooper
  99.  * Fixed bug in auto_guess.  Would not continue through function
  100.  * when file type was ``Makefile''.
  101.  * 
  102.  * Revision 1.3  85/09/19  13:19:50  mcooper
  103.  * Added ``Shell Script'' file type.
  104.  * 
  105.  * Revision 1.2  85/09/19  10:08:36  mcooper
  106.  * Added code to run RCS commands (rcs & ci) on files.
  107.  * Fixed bug that limited number of command line files specified to
  108.  * nine.  Several other minor fixes and improvements.
  109.  * 
  110.  * Revision 1.1  85/09/17  11:33:33  mcooper
  111.  * Initial revision
  112.  * 
  113.  */
  114.  
  115. /*
  116.  * rcsit --     Prepare files for RCS.  rcsit puts the correct headings
  117.  *        at the top of files to prepare them for RCS headings
  118.  *        and log tracking.
  119.  *
  120.  * Michael Cooper    (mcooper@usc-oberon.arpa)
  121.  * University Computing Services, USC
  122.  *
  123.  * 9-16-85
  124.  */
  125.  
  126. #include <stdio.h>
  127. #include <ctype.h>
  128. #include <sys/file.h>
  129.  
  130. #ifdef NULL
  131. #undef NULL
  132. #endif
  133. #define NULL        '\0'
  134. #define LENGTH        132        /* length of line */
  135. #define TRUE        1
  136. #define FALSE        0
  137.  
  138. #ifdef DEBUG
  139.  int debugon = TRUE;
  140. #else
  141.  int debugon = FALSE;
  142. #endif
  143.  
  144. static char     *progname;        /* program name */
  145. static char     *rcsdir;
  146.  
  147. /*
  148.  * Messages to be printed for the user.
  149.  */
  150. static char    *msg_name;        
  151. static char     *m_stdc = "Standard C",
  152.         *m_include = "C Include",
  153.         *m_fortran = "Fortran",
  154.         *m_pascal = "Pascal",
  155.         *m_make    = "Makefile",
  156.         *m_shell = "Shell Script",
  157.         *m_manual = "Manual";
  158.  
  159. /*
  160.  * The headers to put at the beginning of the file(s).
  161.  * Notice that the words Header and Log do not appear here
  162.  * because RCS will put in the keyword substitutions when rcsit.c
  163.  * is co'ed.
  164.  */
  165. static char    *header;
  166. static char    *h_stdc = 
  167.     "static char *RCSid = \"$%s$\";\n\n/*\n * $%s$\n */\n\n";
  168. static char    *h_include = 
  169.     "/*\n * $%s$\n *\n * $%s$\n */\n\n";
  170. static char    *h_make =
  171.     "#\n# $%s$\n#\n# $%s$\n#\n";
  172. static char     *h_manual =
  173.     "...\n... $%s$\n... \n... $%s$\n...\n";
  174. static char     *h_fortran =
  175.     "c\nc $%s$\nc\nc $%s$\nc\n";
  176.  
  177. /*
  178.  * Template file names
  179.  */
  180. static char    *template_c     = ".template.c";    /* .c template */
  181. static char     *template_h     = ".template.h";    /* .h template */
  182. static char     *template_f     = ".template.f";    /* .f template */
  183. static char     *template_p     = ".template.p";    /* .p template */
  184. static char     *template_man     = ".template.man";    /* man template */
  185. static char    *template_make    = ".template.make";    /* make template */
  186. static char    *template_sh    = ".template.sh";    /* sh script template */
  187. static char    *tpath;                    /* path to template */
  188. static char    tfile[BUFSIZ];                /* template file */
  189. static char    tbuf[BUFSIZ];                /* current tfile */
  190.  
  191. /*
  192.  * Command line flags
  193.  */
  194. int    Iflag    = FALSE;            /* run ci(1) */
  195. int    rcsflag = FALSE;            /* run rcs(1) */
  196. int    aflag    = TRUE;                /* do auto guess */
  197. int    dflag    = TRUE;                /* creat RCS dir. */
  198. int    qflag    = FALSE;            /* be quiet! */
  199. int     cflag    = FALSE;            /* std c file */
  200. int    fflag    = FALSE;            /* fortran file */
  201. int    pflag    = FALSE;            /* pascal file */
  202. int    hflag    = FALSE;            /* include file */
  203. int    sflag    = FALSE;            /* shell script */
  204. int     mflag    = FALSE;            /* Makefile */
  205. int    Mflag    = FALSE;            /* manual */
  206. int    tflag    = FALSE;            /* template flag */
  207.  
  208. main(argc, argv)
  209. int    argc;
  210. char     *argv[];
  211. {
  212.     int x;
  213.     char    tmp[LENGTH];
  214.     char    *file;
  215.     char    *flags;
  216.     char     *tmpfile = "/tmp/rcsitXXXXXX";
  217.     char     *mktemp();
  218.     char    *gettmp();
  219.     char    *getenv();
  220.     FILE     *fd, 
  221.         *fdtmp,
  222.         *fopen();
  223.  
  224.     progname = *argv;
  225.     for (x = 1; x < argc; x++) {
  226.         if (argv[x][0] != '-')
  227.             break;
  228.         switch (argv[x][1]) {
  229.             case 'a':
  230.                 aflag = FALSE;
  231.                 break;
  232.             case 'q':
  233.                 qflag = TRUE;
  234.                 break;
  235.             case 'd':
  236.                 dflag = FALSE;
  237.                 break;
  238.             case 'f':
  239.                 fflag = TRUE;
  240.                 break;
  241.             case 'h':
  242.                 hflag = TRUE;
  243.                 break;
  244.             case 's':
  245.                 sflag = TRUE;    
  246.                 break;
  247.             case 'm':
  248.                 mflag = TRUE;
  249.                 break;
  250.             case 'M':
  251.                 Mflag = TRUE;
  252.                 break;
  253.             case 'i':
  254.             case 'I':
  255.                 Iflag = TRUE;
  256.                 flags = &argv[x][2];
  257.                 break;
  258.             case 'r':
  259.             case 'R':
  260.                 rcsflag = TRUE;
  261.                 flags = &argv[x][2];
  262.                 break;
  263.             case 't':
  264.                 tflag = TRUE;
  265.                 tpath = &argv[x][2];
  266.                 break;
  267.             case 'c':
  268.                 cflag = TRUE;
  269.                 break;
  270.             default:
  271.                 fatal("Unknown flag %s.",argv);
  272.         }
  273.     }
  274.     argc -= (x - 1);
  275.     argv += (x - 1);
  276.  
  277.     if((hflag && (mflag || Mflag || cflag)) ||
  278.         (mflag && (hflag || cflag || Mflag)) ||
  279.         (Mflag && (cflag || hflag || mflag)) ||
  280.         (cflag && (hflag || Mflag || mflag))) {
  281.             fatal("Only ONE of -c,-f,-m,-M,-h,-s may be specified.");
  282.     }
  283.     if(Iflag && rcsflag) {
  284.             fatal("Only ONE of ``-i'' and ``-r'' may be specified.");
  285.     }
  286.  
  287.     if(cflag || hflag || mflag || Mflag || fflag || sflag)
  288.         aflag = FALSE;
  289.  
  290.     if((rcsdir = getenv("RCSDIR")) == NULL)
  291.         rcsdir = "RCS";
  292.     if(Iflag && dflag)
  293.         checkdir();    /* Make RCS directory for ci */
  294.  
  295.     if((*tpath == NULL) && ((tpath = getenv("TEMPLATE")) == NULL))
  296.         if((tpath = getenv("HOME")) == NULL)
  297.             fatal("Cannot find environment variable HOME or TEMPLATE");
  298.  
  299.     /*
  300.      * make tmp file once.
  301.      */
  302.     mktemp(tmpfile);
  303.  
  304.     while (--argc) {    /* Main loop */
  305.         file = *++argv;
  306.         debug(sprintf(tmp, "...file (*++argv) = %s...", file));
  307.  
  308.         if(access(file, 4) != 0)
  309.             fatal("Cannot access %s.  No read permission OR file does not exist.",
  310.                 file);
  311.         if((fdtmp = fopen(tmpfile, "w")) == NULL) {
  312.             fatal("Cannot open tmpfile (%s).", tmpfile);
  313.         }
  314.  
  315.         if(aflag)
  316.             auto_guess(file); /* try and guess file type */
  317.         else
  318.             set_flags();      /* check and set flags */
  319.  
  320.         if(tflag) {
  321.             /*
  322.              * first get names of templates, then create
  323.              * path name to it.
  324.              */
  325.             get_temp();
  326.             sprintf(tfile, "%s/%s", tpath, tbuf);
  327.         }
  328.         if(access(tfile, 0) == 0 && tflag) {
  329.             if(!qflag || debugon)
  330.                 printf("Adding %s header file to %s...",
  331.                     msg_name, file);
  332.             copy(tfile, tmpfile, "w");
  333.             copy(file, tmpfile, "a");
  334.         } else {
  335.             if(!qflag || debugon)
  336.                 printf(
  337.                 "Adding default header (%s format) to %s...",
  338.                     msg_name, file);
  339.             /*
  340.              * put the Keywords into header string
  341.              */
  342.             sprintf(tmp, header, "Header", "Log");
  343.             fputs(tmp, fdtmp);
  344.             /*
  345.              * fclose'em, just in case.
  346.              */
  347.             fclose(fdtmp);
  348.             copy(file, tmpfile, "a");
  349.         }
  350.         unlink(file);
  351.         copy(tmpfile, file, "w");
  352.         unlink(tmpfile);
  353.  
  354.         if(!qflag || debugon)
  355.             printf("done.\n");
  356.  
  357.         if(Iflag){
  358.             rcs("ci", file, flags);
  359.             if(Mflag){    /* kludge to tell rcs about manuals */
  360.                 rcs("rcs", file, "c'... '");
  361.                 /*
  362.                  * kludge part 2 - if the user tried a ci
  363.                  * with a -l option, then the header is
  364.                  * messed up in the currently checked out
  365.                  * man file.  So we have to co the file to 
  366.                  * clean up the header.  Plus we use the
  367.                  * -l option of co to insure file locking.
  368.                  */
  369.                 if(checkfor("l", flags)){
  370.                     unlink(file);
  371.                     rcs("co", file, "l");
  372.                 }
  373.             }
  374.         }
  375.         if(rcsflag)
  376.             rcs("rcs", file, flags);
  377.     }
  378. }
  379.  
  380. /*
  381.  * debug - print (useless) debugging info.
  382.  */
  383.  
  384. debug(msg)
  385. char *msg;
  386. {
  387. #ifdef DEBUG
  388.     fprintf(stderr, msg);
  389.     putchar ('\n');
  390. #endif
  391. }
  392.  
  393. /*
  394.  * auto_guess - try and be intelligent and guess type of file
  395.  *        by looking at the suffix or the whole name
  396.  *        in the case of a makefile.
  397.  */
  398.  
  399. auto_guess(file)
  400. char    *file;
  401. {
  402.     char *suffix;
  403.     char *rindex();
  404.  
  405.     suffix = rindex(file, '.')+1;
  406.     if((strcmp(file, "makefile") == 0) || (strcmp(file, "Makefile") == 0) ||
  407.         (strcmp(suffix, "mk") == 0)) {    /* sys V std suffix */
  408.         mflag = TRUE;
  409.         sflag = FALSE;
  410.         cflag = FALSE;
  411.         hflag = FALSE;
  412.         Mflag = FALSE;
  413.         fflag = FALSE;
  414.     }
  415.     if((strcmp(suffix, "sh") == 0) || (strcmp(suffix, "csh") == 0)) {
  416.         sflag = TRUE;
  417.         cflag = FALSE;
  418.         hflag = FALSE;
  419.         mflag = FALSE;
  420.         Mflag = FALSE;
  421.         fflag = FALSE;
  422.     }
  423.     if(strcmp(suffix, "c") == 0){
  424.         cflag = TRUE;
  425.         hflag = FALSE;
  426.         mflag = FALSE;
  427.         Mflag = FALSE;
  428.         sflag = FALSE;
  429.         fflag = FALSE;
  430.     }
  431.     if(strcmp(suffix, "h") == 0){
  432.         hflag = TRUE;
  433.         cflag = FALSE;
  434.         mflag = FALSE;
  435.         Mflag = FALSE;
  436.         sflag = FALSE;
  437.         fflag = FALSE;
  438.     }
  439.     if(strcmp(suffix, "f") == 0){
  440.         fflag = TRUE;
  441.         hflag = FALSE;
  442.         cflag = FALSE;
  443.         mflag = FALSE;
  444.         Mflag = FALSE;
  445.         sflag = FALSE;
  446.     }
  447.     if(isdigit(*suffix) != 0) {
  448.         Mflag = TRUE;
  449.         hflag = FALSE;
  450.         cflag = FALSE;
  451.         mflag = FALSE;
  452.         sflag = FALSE;
  453.         fflag = FALSE;
  454.     }
  455.     set_flags();
  456.     if(!qflag || debugon)
  457.         printf("Hmm.  This file looks like a %s file.\n", msg_name);
  458. }
  459.  
  460. /*
  461.  * set_flags - set & check flags
  462.  */
  463.  
  464. set_flags()
  465. {
  466.     if(cflag || hflag || mflag || Mflag || sflag || fflag) {
  467.         if(cflag) {
  468.             msg_name = m_stdc;
  469.             header = h_stdc;
  470.         }
  471.         if(hflag) {
  472.             msg_name = m_include;
  473.             header = h_include;
  474.         }
  475.         if(mflag) {
  476.             msg_name = m_make;
  477.             header = h_make;
  478.         }
  479.         if(Mflag) {
  480.             msg_name = m_manual;
  481.             header = h_manual;
  482.         }
  483.         if(sflag) {
  484.             msg_name = m_shell;
  485.             header = h_make;
  486.         }
  487.         if(fflag) {
  488.             msg_name = m_fortran;
  489.             header = h_fortran;
  490.         }
  491.     } else {
  492.         cflag = TRUE;
  493.         set_flags();
  494.     }
  495. }
  496.  
  497. /*
  498.  * copy from -> to
  499.  */
  500.  
  501. copy(from, to, mode)
  502. char *from;
  503. char *to;
  504. char *mode;
  505. {
  506.     FILE *fdfrom, *fdto, *fopen();
  507.     char tmp[LENGTH];
  508.     char s[LENGTH];
  509.  
  510.     if((fdfrom = fopen(from, "r")) == NULL) {
  511.         fatal("Cannot open %s for reading.",from);
  512.     }
  513.     if((fdto = fopen(to, mode)) == NULL) {
  514.         fatal("Cannot open %s for \"%s\".",to,mode);
  515.     }
  516.     while(fgets(s, sizeof(s), fdfrom) != NULL)
  517.         fputs(s, fdto);
  518.     fclose(fdfrom);
  519.     fclose(fdto);
  520. }
  521.  
  522. /*
  523.  * Run RCS's rcsprog on file with flags.
  524.  */
  525.  
  526. rcs(rcsprog, file, flags)
  527. char *rcsprog;
  528. char *file;
  529. char *flags;
  530. {
  531.     char buf[LENGTH];
  532.     char tmp[LENGTH];
  533.  
  534.     if(!checkfor("q", flags) && qflag)
  535.         flags = "q";
  536.     if(strcmp(flags, NULL) == 0)
  537.         sprintf(buf, "%s %s", rcsprog, file);
  538.     else
  539.         sprintf(buf, "%s -%s %s", rcsprog, flags, file);
  540.     debug(sprintf(tmp,"Running ``%s''...\n", buf));
  541.     if(!qflag)
  542.         lineprint(sprintf(tmp, "Start of ``%s''", buf));
  543.     system(buf);
  544.     if(!qflag)
  545.         lineprint(sprintf(tmp, "End of ``%s''", buf));
  546. }
  547.  
  548. /*
  549.  * checkdir - make RCS directory if not present.
  550.  */
  551.  
  552. checkdir()
  553. {
  554.     if(access("RCS", 0) != 0){
  555.         if(!qflag || debugon)
  556.             printf("Cannot find \"RCS\" directory.  Creating...\n");
  557.         if(strcmp(rcsdir, "RCS") != 0) { 
  558.             if(symlink(rcsdir, "RCS") != 0)
  559.                 fatal("Symbolic link of %s to RCS failed.", 
  560.                     rcsdir);
  561.         } else {
  562.             if(mkdir(rcsdir, 0755) != 0)
  563.                 fatal("Cannot create \"%s\" directory.", 
  564.                     rcsdir);
  565.         }
  566.     }
  567. }
  568.  
  569. /*
  570.  * checkfor(x, str) -- check for x in str.  Return 1 (TRUE) if exists.
  571.  *            Otherwise 0 (FALSE).
  572.  */
  573.  
  574. checkfor(x, str)
  575. char     *x;
  576. char     *str;
  577. {
  578.     while(*str) {
  579.         if(strcmp(str, x) == 0)
  580.             return(TRUE);
  581.         *str++;
  582.     }
  583.     return(FALSE);
  584. }
  585.  
  586. /*
  587.  * lineprint - print msg in a nice line
  588.  */
  589.  
  590. lineprint(msg)
  591. char *msg;
  592. {
  593.     int len, left, right, x;
  594.  
  595.     len = strlen(msg);
  596.     right = (75-len)/2;
  597.     left = right;
  598.     for(x = 0; x < right; ++x)
  599.         putchar('-');
  600.     printf("[ %s ]", msg);
  601.     for(x = 0; x < left; ++x)
  602.         putchar('-');
  603.     putchar('\n');
  604. }
  605.  
  606. /*
  607.  * fatal - print error and then exit(1).
  608.  */
  609. fatal(format, str)
  610. char *format;
  611. {
  612.     static char namefmt[100];
  613.  
  614.     sprintf(namefmt, "%s: %s\n", progname, format);
  615.     _doprnt(namefmt, &str, stderr);
  616.     exit(1);
  617. }
  618.  
  619. /*
  620.  * zap str with NULL's
  621.  */
  622.  
  623. zap(str)
  624. char str[];
  625. {
  626.     int i, x;
  627.  
  628.     i = strlen(str);
  629.     for(x = 0; x <= i; )
  630.         str[x++] = NULL;
  631. }
  632.  
  633. /*
  634.  * get template names
  635.  */
  636.  
  637. get_temp()
  638. {
  639.     zap(tbuf);
  640.     if(mflag)
  641.         strcpy(tbuf, template_make);
  642.     if(Mflag)
  643.         strcpy(tbuf, template_man);
  644.     if(hflag)
  645.         strcpy(tbuf, template_h);
  646.     if(cflag)
  647.         strcpy(tbuf, template_c);
  648.     if(sflag)
  649.         strcpy(tbuf, template_sh);
  650.     if(fflag)
  651.         strcpy(tbuf, template_f);
  652. }
  653.