home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / vim42os2.zip / vim-4.2 / tools / mvi / mvi.c < prev   
C/C++ Source or Header  |  1996-06-18  |  13KB  |  370 lines

  1. /* 
  2.  
  3. From: tye@spillman.uucp (E. Tye McQueen)
  4. Subject: Re: Using 'rename'
  5. Date: Fri, 05 Jun 1992 19:11:16 GMT
  6. Distribution: comp.lang.perl
  7. Organization: Spillman Data Systems
  8. Followup-To: alt.sources.d
  9. Lines: 357
  10.  
  11. tchrist@convex.COM (Tom Christiansen) writes:
  12. )From the keyboard of glenn@clsi.COM (Glenn Boysko):
  13. ):  % ls -1 | perl -ne 'print "Failed: $_" unless rename($_, s/foo/bar/);'
  14. )
  15. )Substitute returns not the new string, but the count of successful 
  16. )substitutions.
  17.  
  18. No, it's not Perl (it was written long before I'd heard of Perl),
  19. but it is very handy for this.  [Cross-post to alt.sources with
  20. follow-up directed to alt.sources.d]  It hasn't needed other than
  21. minor changes for years so the design and coding style are old and
  22. not defended by the author (me).
  23.  
  24. */
  25.  
  26. /* mvi.c -- mv (rename) files using vi (visual editor).
  27.  *      by Tye McQueen
  28.  */
  29.  
  30. #include <ctype.h>      /* ispunct() */
  31. #include <errno.h>      /* errno */
  32. #include <setjmp.h>     /* jmp_buf setjmp() longjmp() */
  33. #include <signal.h>     /* signal() SIG_DFL SIG_IGN */
  34. #include <stdio.h>      /* FILE f*() */
  35.  
  36. extern char *getenv();
  37. static int rmtmp= 0;        /* If tmp needs to be deleted */
  38. static jmp_buf death;      /* Place to jump to to have tmp deleted */
  39. static char *Self;         /* Program name (argument zero) */
  40. static int Verbose= 0;     /* If we echo each renaming to stderr */
  41. static char *Editor= NULL; /* Editor to use to edit file names... */
  42. static char **Eargs= NULL; /* ...and arguments to pass to it */
  43.  
  44. #define  Fprintf  (void) fprintf
  45. #define  Sprintf  (void) sprintf
  46. #define  Signal   (void) signal
  47. #define  Wait     (void) wait
  48.  
  49. static void
  50. die( text )
  51.   char *text;
  52. {
  53.         if(  ispunct( text[strlen(text)-1] )  ) {
  54.                 Fprintf( stderr, "%s: %s\n", Self, text );
  55.         } else {
  56.                 Fprintf( stderr, "%s: %s%c\n", Self, text, errno ? ':' : '.' );
  57.                 if(  0 != errno  )
  58.                         perror( Self );
  59.         }
  60.         if(  rmtmp  )
  61.                 longjmp( death, 1 );
  62.         exit( 1 );
  63. }
  64. static void
  65. Unlink( name )
  66.   char *name;
  67. {
  68.         errno= 0;
  69.         if(  0 != unlink(name)  ) {
  70.           char msg[255];
  71.                 Sprintf( msg, "Error deleting `%s'", name );
  72.                 die( msg );
  73.         }
  74. }
  75. static FILE *
  76. Fopen( name, acc )
  77.   char *name;
  78.   char *acc;
  79. {
  80.   FILE *fp;
  81.         errno= 0;
  82.         if(  NULL == ( fp= fopen(name,acc) )  ) {
  83.           char msg[255];
  84.                 Sprintf( msg, "Error opening `%s' for `%s' access", name, acc );
  85.                 die( msg );
  86.         }
  87.         return( fp );
  88. }
  89. static void
  90. Fclose( fp )
  91.   FILE *fp;
  92. {
  93.         errno= 0;
  94.         if(  0 != fclose(fp)  )
  95.                 die( "Error closing file" );
  96. }
  97.  
  98. static void
  99. usage()
  100. {
  101.         Fprintf( stderr,
  102.           "usage: %s [-v] [-e editor [options -e]] wildcard(s)\n", Self );
  103.         Fprintf( stderr, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
  104.           " -v  Verbose- echo each name change as it is done.",
  105.           " -e  Editor - specifies an alternate editor to use (instead of that",
  106.           "       specified by environment variable VISUAL or EDITOR or just",
  107.           "       vi) and optionally specifies command line arguments for it.",
  108.           " --  Quotes a `-' at the front of an argument.  After the first",
  109.           "       argument that cannot be an option, this quoting is ignored.",
  110.           "       Note that using `-e editor' witout a closing `-e' means",
  111.           "       all arguments must be checked.",
  112.           " Examples:" );
  113.         Fprintf( stderr, "   %s -e myed --e -e *\n", Self );
  114.         Fprintf( stderr, "%s\n%s\n",
  115.           "     uses `myed -e /tmp/mvi????' to edit the names of all files in",
  116.           "     the current working directory." );
  117.         Fprintf( stderr, "   %s -e ex --file1- --file2-\n", Self );
  118.         Fprintf( stderr, "   %s -e ex -e --file1- -file2-\n", Self );
  119.         Fprintf( stderr,
  120.           "     both use `ex' to edit the names of `-file1-' and `-file2-'\n" );
  121.         exit( 1 );
  122. }
  123.  
  124. static char **
  125. flags( argc, argv )
  126.   int *argc;
  127.   char **argv;
  128. {
  129.         Self= *argv;
  130.         while(  --*argc &&  '-' == **++argv  ) {
  131.                 switch(  *++*argv  ) {
  132.                   case 'e':  case 'E':
  133.                         --*argc;
  134.                         if(  NULL == *( Eargs= ++argv )  )
  135.                                 die( "Name of editor must follow -e." );
  136.                         Editor= *Eargs;
  137.                         while(  --*argc,  *++argv  ) {
  138.                                 if(  '-' == **argv  )
  139.                                         switch( argv[0][1]  ) {
  140.                                           case '-':
  141.                                                 if( '\0' == *++*argv  )   die(
  142.                                                   "Invalid argument: -" );
  143.                                                 break;
  144.                                           case 'e':  case 'E':
  145.                                                 *argv= NULL;
  146.                                                 break;
  147.                                         }
  148.                                 if(  NULL == *argv  )
  149.                                         break;
  150.                         }
  151.                         break;
  152.                   case 'v':  case 'V':
  153.                         Verbose= !Verbose;
  154.                         break;
  155.                   case '-':
  156.                         ++*argv;
  157.                         return( argv );
  158.                   default:
  159.                     { char msg[255];
  160.                         Sprintf( msg, "Unknown switch `-%s'.", *argv );
  161.                         die( msg );
  162.                     }
  163.                 }
  164.         }
  165.         if(  NULL == Editor  ) {
  166.                 Editor= getenv("VISUAL");
  167.                 if(  NULL == Editor  )
  168.                         Editor= getenv("EDITOR");
  169.                 if(  NULL == Editor  )
  170.                         Editor= "vi";
  171.         }
  172.         return( argv );
  173. }
  174.  
  175. static void
  176. writemp( tmp, head, argv )
  177.   char *tmp;
  178.   char *head;
  179.   char **argv;
  180. {
  181.   FILE *fp= Fopen( tmp, "w" );
  182.         rmtmp= 1;
  183.         Fprintf( fp, head );
  184.         while(  *argv  )
  185.                 Fprintf( fp, "%s\n", *(argv++) );
  186.         Fclose( fp );
  187. }
  188.  
  189. static void
  190. editemp( tmp )
  191.   char *tmp;
  192. {
  193.   char **larg;
  194.         switch(  fork()  ) {
  195.           case 0:       /* Subprocess */
  196.                 if(  NULL != Eargs  ) {
  197.                         larg= Eargs;
  198.                         while(  *larg  )
  199.                                 ++larg;
  200.                         *larg= tmp;
  201.                         *++larg= NULL;
  202.                         execvp( Editor, Eargs );
  203.                 } else
  204.                         execlp( Editor, Editor, tmp, (char *)0 );
  205.                 /* Fall through if error */
  206.           case -1:      /* Error */
  207.                 Fprintf( stderr, "%s: can't exec %s\n", Self, Editor );
  208.                 Unlink( tmp );
  209.                 exit( 1 );
  210.         }
  211.         Signal( SIGINT, SIG_IGN );
  212.         Signal( SIGQUIT, SIG_IGN );
  213.         Wait( (int *)0 );
  214.         Signal( SIGINT, SIG_DFL );
  215.         Signal( SIGQUIT, SIG_DFL );
  216. }
  217.  
  218. static void
  219. chktemp( tmp, head, argv )
  220.   char *tmp;
  221.   char *head;
  222.   char **argv;
  223. {
  224.   char new[255], *cp;
  225.   FILE *fp= Fopen( tmp, "r" );
  226.         for(  cp= head;  *cp;  cp++  )
  227.                 if(  fgetc(fp) != *cp  )
  228.                         die( "First line modified.  Abort." );
  229.         for(  ;  fgets(new,sizeof(new),fp);  argv++  ) {
  230.                 cp= new + strlen(new) - 1;
  231.                 if(  '\n' != *cp  ) {
  232.                   char msg[128];
  233.                         Sprintf( msg, "New name is longer than %u characters.",
  234.                           sizeof(new) );
  235.                         die( msg );
  236.                 }
  237.                 *cp= '\0';
  238.                 if(  NULL == argv  )
  239.                         die( "Extra line(s) added to file.  Abort." );
  240.         }
  241.         if(  NULL != *argv  )
  242.                 die( "Line(s) deleted from file.  Abort." );
  243.         Fclose( fp );
  244. }
  245.  
  246. static int cnt= 0, dcnt= 0, lcnt= 0;
  247.  
  248. static void
  249. domv( tmp, head, argv )
  250.   char *tmp;
  251.   char *head;
  252.   char **argv;
  253. {
  254.   char new[255], *cp;
  255.   FILE *fp= Fopen( tmp, "r" );
  256.         for(  cp= head;  *cp;  cp++  )
  257.                 if(  fgetc(fp) != *cp  )
  258.                         die( "First line modified.  Abort." );
  259.         for(  ;  fgets(new,sizeof(new),fp);  argv++  ) {
  260.                 cp= new + strlen(new) - 1;
  261.                 if(  '\n' != *cp  ) {
  262.                   char msg[128];
  263.                         Sprintf( msg, "New name is longer than %u characters.",
  264.                           sizeof(new) );
  265.                         die( msg );
  266.                 }
  267.                 *cp= '\0';
  268.                 if(  NULL == argv  )
  269.                         die( "Extra lines added to file.  Abort." );
  270.                 if(  0 == strncmp( new, "D ", 2 )  ) {
  271.                         if(  0 != strcmp( new+2, *argv )  ) {
  272.                           char msg[512];
  273.                                 Sprintf( msg, "`%s' became `%s'.  Abort.",
  274.                                   *argv, new );
  275.                                 die( msg );
  276.                         }
  277.                         errno= 0;
  278.                         if(  0 != unlink( *argv )  ) {
  279.                           char msg[255];
  280.                                 Fprintf( stderr, "Error deleting `%s':\n",
  281.                                   *argv );
  282.                                 perror( Self );
  283.                         } else {
  284.                                 dcnt++;
  285.                                 if(  Verbose  )
  286.                                     Fprintf( stdout, "rm %s\n", *argv );
  287.                         }
  288.                 } else if(  0 == strncmp( new, "L ", 2 )  ) {
  289.                         if(  0 == strcmp( new+2, *argv )  ) {
  290.                                 Fprintf( stderr,
  291.                                   "%s: Won't link `%s' to itself\n",
  292.                                   Self, *argv );
  293.                         } else {
  294.                                 errno= 0;
  295.                                 if(  0 <= link( *argv, new+2 )  ) {
  296.                                         lcnt++;
  297.                                         if(  Verbose  )
  298.                                             Fprintf( stdout, "ln %s %s\n",
  299.                                               *argv, new+2 );
  300.                                 } else {
  301.                                         Fprintf( stderr,
  302.                                           "%s: Couldn't link `%s' to `%s'\n",
  303.                                           Self, *argv, new+2 );
  304.                                         perror( Self );
  305.                                 }
  306.                         }
  307.                 } else if(  0 != strcmp( *argv, new )  ) {
  308.                         errno= 0;
  309.                         if(  0 <= link( *argv, new )  ) {
  310.                                 cnt++;
  311.                                 if(  Verbose  )
  312.                                         Fprintf( stdout, "mv %s %s\n",
  313.                                           *argv, new );
  314.                                 Unlink( *argv );
  315.                         } else {
  316.                                 Fprintf( stderr,
  317.                                   "%s: Couldn't rename `%s' to `%s'\n",
  318.                                   Self, *argv, new );
  319.                                 perror( Self );
  320.                         }
  321.                 }
  322.         }
  323.         if(  NULL != *argv  )
  324.                 Fprintf( stderr, "%s: Warning, line(s) were deleted.\n", Self );
  325.         Fclose( fp );
  326. }
  327.  
  328. static void
  329. summarize()
  330. {
  331.         Fprintf( stderr, "%s: %d file%s renamed, %d deleted, %d linked.\n",
  332.           Self, cnt, 1==cnt ? "" : "s", dcnt, lcnt );
  333. }
  334.  
  335. void
  336. main( argc, argv )
  337.   int argc;
  338.   char **argv;
  339. {
  340.   char tmp[40];
  341.   static char head[]=
  342. "Edit file name to rename, \"D file\" to delete, \"L link\" to link.\n";
  343.         argv= flags( &argc, argv );
  344.         if(  argc <= 0  )
  345.                 usage();
  346.         Sprintf( tmp, "/tmp/mvi%d", getpid() );
  347.         if(  0 != setjmp( death )  ) {
  348.                 (void) unlink( tmp );
  349.                 summarize();
  350.                 exit( 1 );
  351.         }
  352.         writemp( tmp, head, argv );
  353.         editemp( tmp );
  354.         chktemp( tmp, head, argv );
  355.         domv( tmp, head, argv );
  356.         Unlink( tmp );
  357.         summarize();
  358. }
  359.  
  360. /*
  361.  
  362. -- 
  363.  Tye McQueen, E.     [if uucp]             [if internet]
  364.                    [...uunet!]spillman!tye[@uunet.uu.net]
  365. ----------------------------------------------------------
  366.  Nothing is obvious unless you are overlooking something. 
  367. ----------------------------------------------------------
  368.  
  369. */
  370.