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