ctm.c revision 2971
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$ 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 38extern int Proc(char *); 39 40int 41main(int argc, char **argv) 42{ 43 int stat=0; 44 int c; 45 extern int optopt,optind; 46 extern char * optarg; 47 48 Verbose = 1; 49 Paranoid = 1; 50 setbuf(stderr,0); 51 setbuf(stdout,0); 52 53 while((c=getopt(argc,argv,"ab:B:cd:Fm:pPqr:R:T:Vv")) != -1) { 54 switch (c) { 55 case 'c': CheckIt++; break; /* Only check it */ 56 case 'p': Paranoid--; break; /* Less Paranoid */ 57 case 'P': Paranoid++; break; /* More Paranoid */ 58 case 'q': Verbose--; break; /* Quiet */ 59 case 'v': Verbose++; break; /* Verbose */ 60 case 'T': TmpDir = optarg; break; 61 case 'F': Force = 1; break; 62 case ':': 63 fprintf(stderr,"Option '%c' requires an argument.\n",optopt); 64 stat++; 65 break; 66 case '?': 67 fprintf(stderr,"Option '%c' not supported.\n",optopt); 68 stat++; 69 break; 70 default: 71 fprintf(stderr,"Option '%c' not yet implemented.\n",optopt); 72 break; 73 } 74 } 75 76 if(stat) { 77 fprintf(stderr,"%d errors during option processing\n",stat); 78 return Exit_Pilot; 79 } 80 stat = 0; 81 argc -= optind; 82 argv += optind; 83 84 if(!argc) 85 stat |= Proc("-"); 86 87 while(argc-- && !stat) { 88 stat |= Proc(*argv++); 89 } 90 91 if(stat == Exit_Done) 92 stat = Exit_OK; 93 94 if(Verbose) 95 fprintf(stderr,"Exit(%d)\n",stat); 96 return stat; 97} 98 99int 100Proc(char *filename) 101{ 102 FILE *f; 103 int i; 104 char *p = strrchr(filename,'.'); 105 106 if(!strcmp(filename,"-")) { 107 p = 0; 108 f = stdin; 109 } else if(!strcmp(p,".gz") || !strcmp(p,".Z")) { 110 p = Malloc(100); 111 strcpy(p,"gunzip < "); 112 strcat(p,filename); 113 f = popen(p,"r"); 114 if(!f) { perror(p); return Exit_Garbage; } 115 } else { 116 p = 0; 117 f = fopen(filename,"r"); 118 } 119 if(!f) { 120 perror(filename); 121 return Exit_Garbage; 122 } 123 124 if(Verbose > 1) 125 fprintf(stderr,"Working on <%s>\n",filename); 126 127 if(FileName) Free(FileName); 128 FileName = String(filename); 129 130 /* If we cannot seek, we're doomed, so copy to a tmp-file in that case */ 131 if(!p && -1 == fseek(f,0,SEEK_END)) { 132 char *fn = tempnam(TmpDir,"CMTclient"); 133 FILE *f2 = fopen(fn,"w+"); 134 int i; 135 136 if(!f2) { 137 perror(fn); 138 fclose(f); 139 return Exit_Broke; 140 } 141 unlink(fn); 142 fprintf(stderr,"Writing tmp-file \"%s\"\n",fn); 143 while(EOF != (i=getc(f))) 144 if(EOF == putc(i,f2)) { 145 fclose(f2); 146 return Exit_Broke; 147 } 148 fclose(f); 149 f = f2; 150 } 151 152 if(!p) 153 rewind(f); 154 155 if((i=Pass1(f))) 156 return i; 157 158 if(!p) { 159 rewind(f); 160 } else { 161 pclose(f); 162 f = popen(p,"r"); 163 if(!f) { perror(p); return Exit_Broke; } 164 } 165 166 i=Pass2(f); 167 168 if(!p) { 169 rewind(f); 170 } else { 171 pclose(f); 172 f = popen(p,"r"); 173 if(!f) { perror(p); return Exit_Broke; } 174 } 175 176 if(i) { 177 if((!Force) || (i & ~Exit_Forcible)) 178 return i; 179 } 180 181 if(CheckIt) { 182 fprintf(stderr,"All checks out ok.\n"); 183 return Exit_Done; 184 } 185 186 i=Pass3(f); 187 188 if(!p) { 189 fclose(f); 190 } else { 191 pclose(f); 192 Free(p); 193 } 194 if(i) 195 return i; 196 197 fprintf(stderr,"All done ok\n"); 198 return Exit_Done; 199} 200