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
Wrap
C/C++ Source or Header
|
1996-06-18
|
13KB
|
370 lines
/*
From: tye@spillman.uucp (E. Tye McQueen)
Subject: Re: Using 'rename'
Date: Fri, 05 Jun 1992 19:11:16 GMT
Distribution: comp.lang.perl
Organization: Spillman Data Systems
Followup-To: alt.sources.d
Lines: 357
tchrist@convex.COM (Tom Christiansen) writes:
)From the keyboard of glenn@clsi.COM (Glenn Boysko):
): % ls -1 | perl -ne 'print "Failed: $_" unless rename($_, s/foo/bar/);'
)
)Substitute returns not the new string, but the count of successful
)substitutions.
No, it's not Perl (it was written long before I'd heard of Perl),
but it is very handy for this. [Cross-post to alt.sources with
follow-up directed to alt.sources.d] It hasn't needed other than
minor changes for years so the design and coding style are old and
not defended by the author (me).
*/
/* mvi.c -- mv (rename) files using vi (visual editor).
* by Tye McQueen
*/
#include <ctype.h> /* ispunct() */
#include <errno.h> /* errno */
#include <setjmp.h> /* jmp_buf setjmp() longjmp() */
#include <signal.h> /* signal() SIG_DFL SIG_IGN */
#include <stdio.h> /* FILE f*() */
extern char *getenv();
static int rmtmp= 0; /* If tmp needs to be deleted */
static jmp_buf death; /* Place to jump to to have tmp deleted */
static char *Self; /* Program name (argument zero) */
static int Verbose= 0; /* If we echo each renaming to stderr */
static char *Editor= NULL; /* Editor to use to edit file names... */
static char **Eargs= NULL; /* ...and arguments to pass to it */
#define Fprintf (void) fprintf
#define Sprintf (void) sprintf
#define Signal (void) signal
#define Wait (void) wait
static void
die( text )
char *text;
{
if( ispunct( text[strlen(text)-1] ) ) {
Fprintf( stderr, "%s: %s\n", Self, text );
} else {
Fprintf( stderr, "%s: %s%c\n", Self, text, errno ? ':' : '.' );
if( 0 != errno )
perror( Self );
}
if( rmtmp )
longjmp( death, 1 );
exit( 1 );
}
static void
Unlink( name )
char *name;
{
errno= 0;
if( 0 != unlink(name) ) {
char msg[255];
Sprintf( msg, "Error deleting `%s'", name );
die( msg );
}
}
static FILE *
Fopen( name, acc )
char *name;
char *acc;
{
FILE *fp;
errno= 0;
if( NULL == ( fp= fopen(name,acc) ) ) {
char msg[255];
Sprintf( msg, "Error opening `%s' for `%s' access", name, acc );
die( msg );
}
return( fp );
}
static void
Fclose( fp )
FILE *fp;
{
errno= 0;
if( 0 != fclose(fp) )
die( "Error closing file" );
}
static void
usage()
{
Fprintf( stderr,
"usage: %s [-v] [-e editor [options -e]] wildcard(s)\n", Self );
Fprintf( stderr, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
" -v Verbose- echo each name change as it is done.",
" -e Editor - specifies an alternate editor to use (instead of that",
" specified by environment variable VISUAL or EDITOR or just",
" vi) and optionally specifies command line arguments for it.",
" -- Quotes a `-' at the front of an argument. After the first",
" argument that cannot be an option, this quoting is ignored.",
" Note that using `-e editor' witout a closing `-e' means",
" all arguments must be checked.",
" Examples:" );
Fprintf( stderr, " %s -e myed --e -e *\n", Self );
Fprintf( stderr, "%s\n%s\n",
" uses `myed -e /tmp/mvi????' to edit the names of all files in",
" the current working directory." );
Fprintf( stderr, " %s -e ex --file1- --file2-\n", Self );
Fprintf( stderr, " %s -e ex -e --file1- -file2-\n", Self );
Fprintf( stderr,
" both use `ex' to edit the names of `-file1-' and `-file2-'\n" );
exit( 1 );
}
static char **
flags( argc, argv )
int *argc;
char **argv;
{
Self= *argv;
while( --*argc && '-' == **++argv ) {
switch( *++*argv ) {
case 'e': case 'E':
--*argc;
if( NULL == *( Eargs= ++argv ) )
die( "Name of editor must follow -e." );
Editor= *Eargs;
while( --*argc, *++argv ) {
if( '-' == **argv )
switch( argv[0][1] ) {
case '-':
if( '\0' == *++*argv ) die(
"Invalid argument: -" );
break;
case 'e': case 'E':
*argv= NULL;
break;
}
if( NULL == *argv )
break;
}
break;
case 'v': case 'V':
Verbose= !Verbose;
break;
case '-':
++*argv;
return( argv );
default:
{ char msg[255];
Sprintf( msg, "Unknown switch `-%s'.", *argv );
die( msg );
}
}
}
if( NULL == Editor ) {
Editor= getenv("VISUAL");
if( NULL == Editor )
Editor= getenv("EDITOR");
if( NULL == Editor )
Editor= "vi";
}
return( argv );
}
static void
writemp( tmp, head, argv )
char *tmp;
char *head;
char **argv;
{
FILE *fp= Fopen( tmp, "w" );
rmtmp= 1;
Fprintf( fp, head );
while( *argv )
Fprintf( fp, "%s\n", *(argv++) );
Fclose( fp );
}
static void
editemp( tmp )
char *tmp;
{
char **larg;
switch( fork() ) {
case 0: /* Subprocess */
if( NULL != Eargs ) {
larg= Eargs;
while( *larg )
++larg;
*larg= tmp;
*++larg= NULL;
execvp( Editor, Eargs );
} else
execlp( Editor, Editor, tmp, (char *)0 );
/* Fall through if error */
case -1: /* Error */
Fprintf( stderr, "%s: can't exec %s\n", Self, Editor );
Unlink( tmp );
exit( 1 );
}
Signal( SIGINT, SIG_IGN );
Signal( SIGQUIT, SIG_IGN );
Wait( (int *)0 );
Signal( SIGINT, SIG_DFL );
Signal( SIGQUIT, SIG_DFL );
}
static void
chktemp( tmp, head, argv )
char *tmp;
char *head;
char **argv;
{
char new[255], *cp;
FILE *fp= Fopen( tmp, "r" );
for( cp= head; *cp; cp++ )
if( fgetc(fp) != *cp )
die( "First line modified. Abort." );
for( ; fgets(new,sizeof(new),fp); argv++ ) {
cp= new + strlen(new) - 1;
if( '\n' != *cp ) {
char msg[128];
Sprintf( msg, "New name is longer than %u characters.",
sizeof(new) );
die( msg );
}
*cp= '\0';
if( NULL == argv )
die( "Extra line(s) added to file. Abort." );
}
if( NULL != *argv )
die( "Line(s) deleted from file. Abort." );
Fclose( fp );
}
static int cnt= 0, dcnt= 0, lcnt= 0;
static void
domv( tmp, head, argv )
char *tmp;
char *head;
char **argv;
{
char new[255], *cp;
FILE *fp= Fopen( tmp, "r" );
for( cp= head; *cp; cp++ )
if( fgetc(fp) != *cp )
die( "First line modified. Abort." );
for( ; fgets(new,sizeof(new),fp); argv++ ) {
cp= new + strlen(new) - 1;
if( '\n' != *cp ) {
char msg[128];
Sprintf( msg, "New name is longer than %u characters.",
sizeof(new) );
die( msg );
}
*cp= '\0';
if( NULL == argv )
die( "Extra lines added to file. Abort." );
if( 0 == strncmp( new, "D ", 2 ) ) {
if( 0 != strcmp( new+2, *argv ) ) {
char msg[512];
Sprintf( msg, "`%s' became `%s'. Abort.",
*argv, new );
die( msg );
}
errno= 0;
if( 0 != unlink( *argv ) ) {
char msg[255];
Fprintf( stderr, "Error deleting `%s':\n",
*argv );
perror( Self );
} else {
dcnt++;
if( Verbose )
Fprintf( stdout, "rm %s\n", *argv );
}
} else if( 0 == strncmp( new, "L ", 2 ) ) {
if( 0 == strcmp( new+2, *argv ) ) {
Fprintf( stderr,
"%s: Won't link `%s' to itself\n",
Self, *argv );
} else {
errno= 0;
if( 0 <= link( *argv, new+2 ) ) {
lcnt++;
if( Verbose )
Fprintf( stdout, "ln %s %s\n",
*argv, new+2 );
} else {
Fprintf( stderr,
"%s: Couldn't link `%s' to `%s'\n",
Self, *argv, new+2 );
perror( Self );
}
}
} else if( 0 != strcmp( *argv, new ) ) {
errno= 0;
if( 0 <= link( *argv, new ) ) {
cnt++;
if( Verbose )
Fprintf( stdout, "mv %s %s\n",
*argv, new );
Unlink( *argv );
} else {
Fprintf( stderr,
"%s: Couldn't rename `%s' to `%s'\n",
Self, *argv, new );
perror( Self );
}
}
}
if( NULL != *argv )
Fprintf( stderr, "%s: Warning, line(s) were deleted.\n", Self );
Fclose( fp );
}
static void
summarize()
{
Fprintf( stderr, "%s: %d file%s renamed, %d deleted, %d linked.\n",
Self, cnt, 1==cnt ? "" : "s", dcnt, lcnt );
}
void
main( argc, argv )
int argc;
char **argv;
{
char tmp[40];
static char head[]=
"Edit file name to rename, \"D file\" to delete, \"L link\" to link.\n";
argv= flags( &argc, argv );
if( argc <= 0 )
usage();
Sprintf( tmp, "/tmp/mvi%d", getpid() );
if( 0 != setjmp( death ) ) {
(void) unlink( tmp );
summarize();
exit( 1 );
}
writemp( tmp, head, argv );
editemp( tmp );
chktemp( tmp, head, argv );
domv( tmp, head, argv );
Unlink( tmp );
summarize();
}
/*
--
Tye McQueen, E. [if uucp] [if internet]
[...uunet!]spillman!tye[@uunet.uu.net]
----------------------------------------------------------
Nothing is obvious unless you are overlooking something.
----------------------------------------------------------
*/