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