ctm.c revision 2926
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 * -c Check it out, "ma non troppo" 20 * -d <int> Debug TBD. 21 * -F Force 22 * -m <mail-addr> Email me instead. 23 * -p Less paranoid. 24 * -P Paranoid. 25 * -q Be quiet. 26 * -r <name> Reconstruct file. 27 * -R <file> Read list of files to reconstruct. 28 * -T <tmpdir>. Temporary files. 29 * -v Tell about each file. 30 * 31 */ 32 33#define EXTERN /* */ 34#include "ctm.h" 35 36extern int Proc(char *); 37 38int 39main(int argc, char **argv) 40{ 41 int stat=0; 42 int c; 43 extern int optopt,optind; 44 extern char * optarg; 45 46 Verbose = 1; 47 Paranoid = 1; 48 setbuf(stderr,0); 49 setbuf(stdout,0); 50 51 while((c=getopt(argc,argv,"ab:B:cd:Fm:pPqr:R:T:Vv")) != -1) { 52 switch (c) { 53 case 'p': Paranoid--; break; /* Less Paranoid */ 54 case 'P': Paranoid++; break; /* More Paranoid */ 55 case 'q': Verbose--; break; /* Quiet */ 56 case 'v': Verbose++; break; /* Verbose */ 57 case 'T': TmpDir = optarg; break; 58 case 'F': Force = 1; break; 59 case ':': 60 fprintf(stderr,"Option '%c' requires an argument.\n",optopt); 61 stat++; 62 break; 63 case '?': 64 fprintf(stderr,"Option '%c' not supported.\n",optopt); 65 stat++; 66 break; 67 default: 68 fprintf(stderr,"Option '%c' not yet implemented.\n",optopt); 69 break; 70 } 71 } 72 73 if(stat) { 74 fprintf(stderr,"%d errors during option processing\n",stat); 75 exit(2); 76 } 77 stat = 0; 78 argc -= optind; 79 argv += optind; 80 81 if(!argc) 82 stat |= Proc("-"); 83 84 while(argc-- && !stat) 85 stat |= Proc(*argv++); 86 87 return stat; 88} 89 90int 91Proc(char *filename) 92{ 93 FILE *f; 94 int i; 95 char *p = strrchr(filename,'.'); 96 97 if(!strcmp(filename,"-")) { 98 p = 0; 99 f = stdin; 100 } else if(!strcmp(p,".gz") || !strcmp(p,".Z")) { 101 p = Malloc(100); 102 strcpy(p,"gunzip < "); 103 strcat(p,filename); 104 f = popen(p,"r"); 105 } else { 106 p = 0; 107 f = fopen(filename,"r"); 108 } 109 if(!f) { 110 perror(filename); 111 return 1; 112 } 113 114 if(Verbose > 1) 115 fprintf(stderr,"Working on <%s>\n",filename); 116 117 if(FileName) Free(FileName); 118 FileName = String(filename); 119 120 /* If we cannot seek, we're doomed, so copy to a tmp-file in that case */ 121 if(!p && -1 == fseek(f,0,SEEK_END)) { 122 char *fn = tempnam(TmpDir,"CMTclient"); 123 FILE *f2 = fopen(fn,"w+"); 124 int i; 125 126 if(!f2) { 127 perror(fn); 128 fclose(f); 129 return 4; 130 } 131 unlink(fn); 132 fprintf(stderr,"Writing tmp-file \"%s\"\n",fn); 133 while(EOF != (i=getc(f))) 134 putc(i,f2); 135 fclose(f); 136 f = f2; 137 } 138 139 if(!p) 140 rewind(f); 141 142 if((i=Pass1(f))) 143 return i; 144 145 if(!p) { 146 rewind(f); 147 } else { 148 pclose(f); 149 f = popen(p,"r"); 150 } 151 152 if((i=Pass2(f))) 153 return i; 154 155 if(!p) { 156 rewind(f); 157 } else { 158 pclose(f); 159 f = popen(p,"r"); 160 } 161 162 if((i=Pass3(f))) 163 return i; 164 165 if(!p) { 166 fclose(f); 167 } else { 168 pclose(f); 169 Free(p); 170 } 171 172 return 0; 173} 174