ctm.c revision 7168
1/* 2 * ---------------------------------------------------------------------------- 3 * "THE BEER-WARE LICENSE" (Revision 42): 4 * <phk@login.dknet.dk> wrote this file. As long as you retain this notice you 5 * can do whatever you want with this stuff. If we meet some day, and you think 6 * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp 7 * ---------------------------------------------------------------------------- 8 * 9 * $Id: ctm.c,v 1.8 1995/03/04 20:36:45 phk Exp $ 10 * 11 * This is the client program of 'CTM'. It will apply a CTM-patch to a 12 * collection of files. 13 * 14 * Options we'd like to see: 15 * 16 * -a Attempt best effort. 17 * -b <dir> Base-dir 18 * -B <file> Backup to tar-file. 19 * -d <int> Debug TBD. 20 * -m <mail-addr> Email me instead. 21 * -r <name> Reconstruct file. 22 * -R <file> Read list of files to reconstruct. 23 * 24 * Options we have: 25 * -c Check it out, don't do anything. 26 * -F Force 27 * -p Less paranoid. 28 * -P Paranoid. 29 * -q Tell us less. 30 * -T <tmpdir>. Temporary files. 31 * -v Tell us more. 32 * 33 */ 34 35#define EXTERN /* */ 36#include "ctm.h" 37 38#define CTM_STATUS ".ctm_status" 39 40extern int Proc(char *, unsigned applied); 41 42int 43main(int argc, char **argv) 44{ 45 int stat=0; 46 int c; 47 extern int optopt,optind; 48 extern char * optarg; 49 FILE *statfile; 50 unsigned applied = 0; 51 52 Verbose = 1; 53 Paranoid = 1; 54 setbuf(stderr,0); 55 setbuf(stdout,0); 56 57 while((c=getopt(argc,argv,"ab:B:cd:Fm:pPqr:R:T:Vv")) != -1) { 58 switch (c) { 59 case 'c': CheckIt++; break; /* Only check it */ 60 case 'p': Paranoid--; break; /* Less Paranoid */ 61 case 'P': Paranoid++; break; /* More Paranoid */ 62 case 'q': Verbose--; break; /* Quiet */ 63 case 'v': Verbose++; break; /* Verbose */ 64 case 'T': TmpDir = optarg; break; 65 case 'F': Force = 1; break; 66 case ':': 67 fprintf(stderr,"Option '%c' requires an argument.\n",optopt); 68 stat++; 69 break; 70 case '?': 71 fprintf(stderr,"Option '%c' not supported.\n",optopt); 72 stat++; 73 break; 74 default: 75 fprintf(stderr,"Option '%c' not yet implemented.\n",optopt); 76 break; 77 } 78 } 79 80 if(stat) { 81 fprintf(stderr,"%d errors during option processing\n",stat); 82 return Exit_Pilot; 83 } 84 stat = Exit_Done; 85 argc -= optind; 86 argv += optind; 87 88 if((statfile = fopen(CTM_STATUS, "r")) == NULL) 89 fprintf(stderr, "Warning: " CTM_STATUS " not found.\n"); 90 else { 91 fscanf(statfile, "%*s %u", &applied); 92 fclose(statfile); 93 } 94 95 if(!argc) 96 stat |= Proc("-", applied); 97 98 while(argc-- && stat == Exit_Done) { 99 stat |= Proc(*argv++, applied); 100 stat &= ~Exit_Version; 101 } 102 103 if(stat == Exit_Done) 104 stat = Exit_OK; 105 106 if(Verbose) 107 fprintf(stderr,"Exit(%d)\n",stat); 108 return stat; 109} 110 111int 112Proc(char *filename, unsigned applied) 113{ 114 FILE *f; 115 int i; 116 char *p = strrchr(filename,'.'); 117 118 if(!strcmp(filename,"-")) { 119 p = 0; 120 f = stdin; 121 } else if(p && (!strcmp(p,".gz") || !strcmp(p,".Z"))) { 122 p = Malloc(100); 123 strcpy(p,"gunzip < "); 124 strcat(p,filename); 125 f = popen(p,"r"); 126 if(!f) { perror(p); return Exit_Garbage; } 127 } else { 128 p = 0; 129 f = fopen(filename,"r"); 130 } 131 if(!f) { 132 perror(filename); 133 return Exit_Garbage; 134 } 135 136 if(Verbose > 1) 137 fprintf(stderr,"Working on <%s>\n",filename); 138 139 if(FileName) Free(FileName); 140 FileName = String(filename); 141 142 /* If we cannot seek, we're doomed, so copy to a tmp-file in that case */ 143 if(!p && -1 == fseek(f,0,SEEK_END)) { 144 char *fn = tempnam(TmpDir,"CMTclient"); 145 FILE *f2 = fopen(fn,"w+"); 146 int i; 147 148 if(!f2) { 149 perror(fn); 150 fclose(f); 151 return Exit_Broke; 152 } 153 unlink(fn); 154 fprintf(stderr,"Writing tmp-file \"%s\"\n",fn); 155 while(EOF != (i=getc(f))) 156 if(EOF == putc(i,f2)) { 157 fclose(f2); 158 return Exit_Broke; 159 } 160 fclose(f); 161 f = f2; 162 } 163 164 if(!p) 165 rewind(f); 166 167 if((i=Pass1(f, applied))) 168 goto exit_and_close; 169 170 if(!p) { 171 rewind(f); 172 } else { 173 pclose(f); 174 f = popen(p,"r"); 175 if(!f) { perror(p); return Exit_Broke; } 176 } 177 178 i=Pass2(f); 179 180 if(!p) { 181 rewind(f); 182 } else { 183 pclose(f); 184 f = popen(p,"r"); 185 if(!f) { perror(p); return Exit_Broke; } 186 } 187 188 if(i) { 189 if((!Force) || (i & ~Exit_Forcible)) 190 goto exit_and_close; 191 } 192 193 if(CheckIt) { 194 fprintf(stderr,"All checks out ok.\n"); 195 i = Exit_Done; 196 goto exit_and_close; 197 } 198 199 i=Pass3(f); 200 201exit_and_close: 202 if(!p) { 203 fclose(f); 204 } else { 205 pclose(f); 206 Free(p); 207 } 208 if(i) 209 return i; 210 211 fprintf(stderr,"All done ok\n"); 212 return Exit_Done; 213} 214