/* COPYRIGHT (c) 1990 Kapteyn Astronomical Institute University of Groningen, The Netherlands All Rights Reserved. #> delete.dc1 Program: DELETE Purpose: Delete sets Category: UTILITY File: delete.c Author: M. Vogelaar Keywords: ** LIST= List with GIPSY set names? Y/[N] Can be either Y or N. If user specifies LIST=Y, a list with set names in the current directory is displayed. The default is LIST=N INSET= Give name of set to delete: [stop] Enter: 1) One set name, e.g.: INSET=AURORA 2) Set names separated by a semicolon (;) e.g.: INSET=AURORA;ngc3079a;ngc3079b 3) A path followed by a set name (no wildcard expansion): INSET=./WORK/ngc400 4) Set name(s) containing the wildcard character '*'. Wildcards can appear everywhere in a name. The wildcard expansion works only in the current directory! INSET=ngc* (Delete all GIPSY sets that start with 'ngc') INSET=* (Delete all GIPSY sets in current dir.) The names of sets which the user wants to delete are asked in a loop. Press carriage return to abort this loop and to stop the program. OK= Ok to delete ? Y/[N] Confirm the choice for EACH file that you entered with INSET= Long file names are cut off. A number of dots indicate if this has happened. Description: DELETE deletes GIPSY sets (image part and descriptor part). After the introduction of the GDS server, it became more important to be able to delete sets within the environment where the server is running. If f.i. you delete sets with the unix 'rm' command, the program DISK will still list those sets if the server is still running. Program DELETE doe the job properly. It checks whether a file is a valid GIPSY set and will warn you if it is not (program will display the corresponding GDS error like: GDS -- bad descriptor header). However, you still can delete these invalid sets. The program stores the names of all files that end on '.descr'. This list is necessary if you want to use a wildcard expansion using the asterisk character '*'. This explains why wildcard expansion can only be used in the current directory. If a set (entered with INSET=) does not exist, then a warning is displayed in your log area. If a set exists, but does not conform to the rules for a valid GIPSY set, then a warning is displayed in the log area together with the corresponding GDS error, and a warning will be inserted in the OK= prompt. Notice that it is still possible to delete such files. So program DELETE can delete your very important backupless text file 'important.descr' if that is what you want. Updates: Jun 15, 1995: VOG, Completely rewritten. #< */ #include "stdio.h" #include "stdlib.h" #include "string.h" #include "ctype.h" #include "time.h" #include "math.h" #include "cmain.h" #include "gipsyc.h" #include "init.h" #include "finis.h" #include "flist.h" #include "nelc.h" #include "myname.h" #include "anyout.h" #include "gds_exist.h" #include "gds_delete.h" #include "gds_errstr.h" #include "userfio.h" #include "userint.h" #include "userlog.h" #include "userchar.h" #include "cancel.h" #include "status.h" #include "nelc.h" #include "error.h" #include "wmatch.h" /* Matches a test string with the mask string ...*/ #define VERSION "2.0" #define MAX_FILNAM_LEN 512 /* Max. length of directory entries */ #define BIGSTORE 80 #define NONE 0 /* Default values for userxxx functions */ #define REQUEST 1 #define HIDDEN 2 #define EXACT 4 #define YES 1 #define NO 0 #define PROCESS_AREA_LEN 54 #define MYMIN(a,b) ((a) > (b) ? (b) : (a)) #define MYMAX(a,b) ((a) > (b) ? (a) : (b)) #define KEY_INSET tofchar("INSET=") #define KEY_OK tofchar("OK=") /* Macro to create static storage for Fortran type string */ #define fmake(fchr,size) { \ static char buff[size+1]; \ int i; \ for (i = 0; i < size; buff[i++] = ' '); \ buff[i] = 0; \ fchr.a = buff; \ fchr.l = size; \ } static int compare( char **ps1, char **ps2 ) /*------------------------------------------------------------*/ /* PURPOSE: Compare function for use in 'qsort'. */ /* This function is used by 'qsort' to sort an array with */ /* pointers to pointers to characters. The numbers in the */ /* strings are treated differently so that a10 is positioned */ /* after a2. */ /*------------------------------------------------------------*/ { char *s1, *s2; int i, j; /* Local counters */ int diff; /* Difference between two chars */ s1 = *ps1; /* copy pointers to char. arrays */ s2 = *ps2; i = j = 0; for (;;) { if (isdigit( s1[i] ) && isdigit( s2[j]) ) { char number1[20]; /* strings containing digits */ char number2[20]; int n1 = 0, n2 = 0; while (isdigit(s1[i])) number1[n1++] = s1[i++]; while (isdigit(s2[j])) number2[n2++] = s2[j++]; number1[n1] = '\0'; /* Terminate string */ number2[n2] = '\0'; diff = atoi(number1) - atoi(number2); /* Convert to integers */ if (diff != 0) return(diff); } else /* Is end of a string reached? */ { if (s1[i] == '\0' && s2[j] != '\0') return(-1); if (s1[i] != '\0' && s2[j] == '\0') return(1); if (s1[i] == '\0' && s2[j] == '\0') return(0); diff = s1[i++] - s2[j++]; if (diff != 0) return( diff ); } } } static void delete_set( fchar Setin ) /*------------------------------------------------------------*/ /* PURPOSE: Delete set, but ask for confirmation first. */ /*------------------------------------------------------------*/ { bool ok; /* Confirm the deleting */ char messbuf[BIGSTORE]; fint nitems; fint dfault; fint r; int slen = nelc_c(Setin); r = 0; if ( !(tobool(gds_exist_c(Setin, &r))) ) { fchar Errstr; fmake( Errstr, BIGSTORE ); if (r < 0) { gds_errstr_c( Errstr, &r ); anyoutf( 1, "Set [%.*s] is not a valid GIPSY set! (%.*s)", slen, Setin.a, nelc_c(Errstr), Errstr.a ); sprintf( messbuf, "Invalid GIPSY set, delete anyway? Y/[N]" ); } else { anyoutf( 1, "Set [%.*s] does not exist!", slen, Setin.a ); return; } } else /*--------------------------------------------------*/ /* How many characters are left to display the file */ /* name in the process area? */ /*--------------------------------------------------*/ { int messlen; /* Length of message without set name */ messlen = strlen("Ok to delete ? Y/[N]"); if (slen+messlen+1 < PROCESS_AREA_LEN) sprintf( messbuf, "Ok to delete %.*s ? Y/[N]", slen, Setin.a ); else sprintf( messbuf, "Ok to delete %.*s...? Y/[N]", PROCESS_AREA_LEN-messlen-5, Setin.a ); } /* Ask confirmation */ ok = toflog( NO ); dfault = REQUEST; nitems = 1; r = userlog_c( &ok, &nitems, &dfault, KEY_OK, tofchar(messbuf) ); ok = tobool( ok ); r = 0; if (ok) { gds_delete_c( Setin, &r ); if (r < 0) { fchar Errstr; fmake( Errstr, BIGSTORE ); gds_errstr_c( Errstr, &r ); anyoutf( 1, "Set [%.*s] could not be deleted! (%.*s)", slen, Setin.a, nelc_c(Errstr), Errstr.a ); } } cancel_c( KEY_OK ); } static int isvalidname( char *name, int len ) /*------------------------------------------------------------*/ /* PURPOSE: A name can represent a GIPSY set if it ends on */ /* .descr */ /* The length is also an input variable because we need it */ /* here, but it is already calculated in the calling */ /* environment. Return a string without the .descr part. */ /*------------------------------------------------------------*/ { if (len < 7) /* String too short to contain .descr */ return( 0 ); return( !(strcmp(".descr", &name[len-6])) ); } MAIN_PROGRAM_ENTRY /*-------------------------------------------------------------------------*/ /* The macro MAIN_PROGRAM_ENTRY replaces the C-call main() to start the */ /* main body of your GIPSY application. Variables defined as 'fchar' start */ /* with a capital. */ /*-------------------------------------------------------------------------*/ { fint nitems; fint dfault; fint r; int entries = 0; bool next; bool cont; bool list; char **files = NULL; /* Array of pointers to char. arrays */ init_c(); /* contact Hermes */ /* Task identification */ { fchar Ftask; /* Name of current task */ fmake( Ftask, 20 ); /* Macro 'fmake' must be available */ myname_c( Ftask ); /* Get task name */ Ftask.a[nelc_c(Ftask)] = '\0'; /* Terminate task name with null char. */ IDENTIFICATION( Ftask.a, VERSION ); /* Show task and version */ } /* Does user want a list with GIPSY sets? */ nitems = 1; list = toflog( NO ); dfault = HIDDEN; r = userlog_c( &list, &nitems, &dfault, tofchar("LIST="), tofchar("List with GIPSY set names? Y/[N]") ); list = tobool( list ); /*--------------------------------------------------*/ /* In order to do a wildcard match, we need a list */ /* of file names first. Read files from current */ /* directory and store the GIPSY sets. */ /*--------------------------------------------------*/ { fchar Filename; fchar Dirname; fmake( Filename, MAX_FILNAM_LEN ); fmake( Dirname, MAX_FILNAM_LEN ); /* Select a directory; a space selects the current directory */ Dirname = tofchar( " " ); entries = 0; /* Total number of entries in dir. */ next = YES; status_c( tofchar("Reading files in directory") ); while ( next ) { r = flist_c(Dirname, Filename); next = (r == 0); if (r == -1) anyoutf( 1, "Entry trunctated because buffer is not large enough" ); if (r == -3) anyoutf( 1, "Error reading directory" ); if (r == -4) anyoutf( 1, "Cannot obtain current directory" ); if (next) { int len = nelc_c(Filename); Filename.a[len] = '\0'; if ( isvalidname(Filename.a, len) ) { files = realloc( files, (entries+1) * sizeof(char *) ); /* new pointer */ files[entries] = malloc( len + 1 ); /* Store without .descr */ sprintf( files[entries], "%.*s", len - 6, Filename.a ); entries++; } } } } if (list) /*--------------------------------------------------*/ /* Do a quicksort, first parameter is name of array.*/ /* Second is number of elements in that array, third*/ /* is the size of one element and the last parameter*/ /* is a function for comparison. */ /*--------------------------------------------------*/ { int i; qsort( files, entries, sizeof(char *), (int(*)())compare ); for (i = 0; i < entries; i++) anyoutf( 1, "%4d: %s", i+1, files[i] ); } /*--------------------------------------------------*/ /* Loop over sets to delete. End loop after default */ /*--------------------------------------------------*/ cont = YES; while( cont ) { fchar Delset; int i; fmake( Delset, MAX_FILNAM_LEN ); dfault = REQUEST; nitems = 1; r = userchar_c( Delset, &nitems, &dfault, KEY_INSET, tofchar("Give name of set to delete: [stop]" ) ); cancel_c( KEY_INSET ); cont = (r > 0); if (cont) { Delset.a[nelc_c(Delset)] = '\0'; if ( strchr(Delset.a, '*') != NULL ) /*--------------------------------------------------*/ /* The wildcard character is part of the INSET= */ /* string. Check against all stored file names. De- */ /* lete if name is matched. The wildcard character */ /* is *. */ /*--------------------------------------------------*/ { int matched = 0; for (i = 0; i < entries; i++) { fint casesensitive = YES; if ( tobool(wmatch_c( tofchar(files[i]), tofchar(Delset.a), tofchar("*"), &casesensitive )) ) { matched++; /* Check file and ask confirmation before deleting */ delete_set( tofchar(files[i]) ); } } if (!matched) anyoutf( 1, "No files found to delete!" ); } else { /* Check file and ask confirmation before deleting */ delete_set( Delset ); } } } /*----------------------------------------*/ /* Free the allocated character arrays. */ /*----------------------------------------*/ { int i; for (i = 0; i < entries; i++) free( files[i] ); free( files ); } finis_c(); return(EXIT_SUCCESS); }