/* DATAEDIT - provide a lock-knowledgable wrapper for data table file manual editing 
   or external program update (use -c commandstring, where commandstring has a %s into
   which will be substituted the tmp filename)
 */

#include "tdhkit.h"
#include "shsql.h"

extern int GL_make_unique_string();
extern int unlink();

int
main( argc, argv )
int argc;
char **argv;
{
int i, stat;
char uin[80], buf[MAXRECORDLEN], tok[ DATAMAXLEN+1 ];
char altname[80], altfile[256], uniq[80]; /* the temporary working file */
char command[256];
char *editor, *getenv();
FILE *fp;
int skipmaint;
int n_expected, linenum, problemfound, ix, nt;


TDH_errprog( "dataedit" );
if( argc < 2 ) { fprintf( stderr, "usage: dataedit tablename [-c command]\n" ); exit( 1 ); }

/* process config file.. */
stat = SHSQL_allconfig();
if( stat != 0 ) exit( 1 );


if( GL_member( argv[1][0], "./$" )) { SHSQL_err( 302, "dataedit error: use with database table files only", argv[1] ); exit( 1 ); }

/* make a temp file name.. */
GL_make_unique_string( uniq, 0 );
sprintf( altname, "__edit_%s", uniq );
sprintf( altfile, "%s/data/%s", SHSQL_projdir, altname );

strcpy( command, "" );
skipmaint = 0;
for( i = 2; i < argc; i++ ) {
	if( strcmp( argv[i], "-c" )==0 ) {
		if( i+1 < argc ) {
			i++;
			sprintf( command, argv[i], altfile );
			fprintf( stderr, "this command will be invoked: %s\n", command );
			}
		}
	else if( strcmp( argv[i], "-s" )==0 ) skipmaint = 1;
	}

/* get a write-lock on the data file.. */
stat = SHSQL_lock( argv[1] );
if( stat != 0 ) { SHSQL_err( 303, "table is currently write-locked by someone else.. cannot proceed", argv[1] ); exit( 1 ); }

SHSQL_err( 402, "Note: dataedit starting", argv[1] );

/* make a temporary copy of data file.. */
sprintf( buf, "(cd %s/data; cp -p %s %s)", SHSQL_projdir, argv[1], altname );
system( buf );

TRY_AGAIN:

/* invoke editor or external program */
if( command[0] == '\0' ) {
	editor = getenv( "EDITOR" );
	if( editor == NULL ) editor = "vi";
	sprintf( buf, "%s %s", editor, altfile );
	system( buf );
	printf( "\n\nfinished editing..  save the result back into the database (y/n)? " );
	scanf( "%s", uin );
	if( uin[0] != 'y' ) {
		SHSQL_err( 403, "Note: dataedit finished, database not changed.", argv[1] );
		unlink( altfile );
		exit( 0 );
		}
	}
else system( command );

if( skipmaint ) goto NOMAINT;

/* perform field count check.. added scg 2/24/04 */
printf( "checking record field counts.." ); fflush( stdout );
sprintf( buf, "%s/data/%s", SHSQL_projdir, altname );
fp = fopen( buf, "r" );
n_expected = 0;
linenum = 0;
problemfound = 0;
while( fgets( buf, MAXRECORDLEN, fp ) != NULL ) {
	linenum++;
	nt = sscanf( buf, "%s", tok );
	if( nt < 1 || strncmp( tok, "//", 2 )==0 ) continue;
	ix = 0;
	for( i = 0; ; i++ ) {
		if( strcmp( GL_getok( buf, &ix ), "" )==0 ) break;
		}
	if( n_expected == 0 ) n_expected = i;
	else if( i != n_expected ) { printf( "\nfield count problem: line %d   %-30s\n", linenum, buf ); problemfound = 1; }
	}
fclose( fp );
if( problemfound ) {
	ASK_AGAIN:
	printf( "\nwhat now?   f = fix problems    q = quit and discard  : " );
	fgets( buf, 200, stdin );
	fgets( buf, 200, stdin );
	if( buf[0] == 'f' ) goto TRY_AGAIN;
	else if( buf[0] == 'q' ) {
		SHSQL_err( 403, "Note: dataedit finished, database not changed.", argv[1] );
		unlink( altfile );
		exit( 0 );
		}
	else goto ASK_AGAIN;
	}

else printf( " ..ok\n" );


/* if indexes exist, rebuild them and done.. */
sprintf( buf, "%s/indexes/%s.0", SHSQL_projdir, argv[1] );
fp = fopen( buf, "r" );
if( fp != NULL ) {
	printf( "Rebuilding indexes..\n" );
	if( SHSQL_bin[0] != '\0' ) sprintf( buf, "%s/tabmaint %s -n %s", SHSQL_bin, argv[1], altname );
	else sprintf( buf, "tabmaint %s -n %s", argv[1], altname );
	system( buf );
	stat = SHSQL_unlock( );
	SHSQL_err( 403, "Note: dataedit finished", argv[1] );
	exit( 0 );
	}


NOMAINT:
/* move temp file -> real file */
stat = SHSQL_readlock( argv[1], 1 ); /* attempt to set read lock.. */
if( stat != 0 ) { SHSQL_unlock(); exit( 1 ); }

sprintf( buf, "(cd %s/data; mv %s %s)", SHSQL_projdir, altname, argv[1] );
system( buf );
			
stat = SHSQL_readlock( argv[1], 0 ); 
stat = SHSQL_unlock( );
SHSQL_err( 403, "Note: dataedit finished", argv[1] );

exit( 0 );
}
