Fixed config handling bug again
[ntk/apt.git] / apt-pkg / acquire-method.cc
CommitLineData
93bf083d
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
bfd22fc0 3// $Id: acquire-method.cc,v 1.4 1998/11/05 07:21:38 jgg Exp $
93bf083d
AL
4/* ######################################################################
5
6 Acquire Method
7
8 ##################################################################### */
9 /*}}}*/
10// Include Files /*{{{*/
11#ifdef __GNUG__
12#pragma implementation "apt-pkg/acquire-method.h"
13#endif
14#include <apt-pkg/acquire-method.h>
15#include <apt-pkg/error.h>
16#include <apt-pkg/configuration.h>
17#include <strutl.h>
18#include <apt-pkg/fileutl.h>
19
20#include <stdio.h>
21 /*}}}*/
22
23// AcqMethod::pkgAcqMethod - Constructor /*{{{*/
24// ---------------------------------------------------------------------
25/* This constructs the initialization text */
26pkgAcqMethod::pkgAcqMethod(const char *Ver,unsigned long Flags)
27{
28 char S[300] = "";
29 char *End = S;
30 strcat(End,"100 Capabilities\n");
31 sprintf(End+strlen(End),"Version: %s\n",Ver);
32
33 if ((Flags & SingleInstance) == SingleInstance)
34 strcat(End,"Single-Instance: true\n");
35
36 if ((Flags & PreScan) == PreScan)
37 strcat(End,"Pre-Scan: true\n");
38
39 if ((Flags & Pipeline) == Pipeline)
40 strcat(End,"Pipeline: true\n");
41
42 if ((Flags & SendConfig) == SendConfig)
43 strcat(End,"Send-Config: true\n");
44 strcat(End,"\n");
45
46 if (write(STDOUT_FILENO,S,strlen(S)) != (signed)strlen(S))
47 exit(100);
be4401bf
AL
48
49 SetNonBlock(STDIN_FILENO,true);
92e889c8
AL
50
51 Queue = 0;
93bf083d
AL
52}
53 /*}}}*/
54// AcqMethod::Fail - A fetch has failed /*{{{*/
55// ---------------------------------------------------------------------
56/* */
57void pkgAcqMethod::Fail()
58{
59 string Err = "Undetermined Error";
60 if (_error->empty() == false)
61 _error->PopMessage(Err);
62 _error->Discard();
63 Fail(Err);
64}
65 /*}}}*/
66// AcqMethod::Fail - A fetch has failed /*{{{*/
67// ---------------------------------------------------------------------
68/* */
69void pkgAcqMethod::Fail(string Err)
70{
71 char S[1024];
be4401bf
AL
72 if (Queue != 0)
73 {
74 snprintf(S,sizeof(S),"400 URI Failure\nURI: %s\n"
75 "Message: %s\n\n",Queue->Uri.c_str(),Err.c_str());
76
77 // Dequeue
78 FetchItem *Tmp = Queue;
79 Queue = Queue->Next;
80 delete Tmp;
81 }
82 else
83 snprintf(S,sizeof(S),"400 URI Failure\nURI: <UNKNOWN>\n"
84 "Message: %s\n\n",Err.c_str());
85
93bf083d
AL
86 if (write(STDOUT_FILENO,S,strlen(S)) != (signed)strlen(S))
87 exit(100);
88}
89 /*}}}*/
90// AcqMethod::URIStart - Indicate a download is starting /*{{{*/
91// ---------------------------------------------------------------------
92/* */
be4401bf 93void pkgAcqMethod::URIStart(FetchResult &Res)
93bf083d 94{
be4401bf
AL
95 if (Queue == 0)
96 abort();
97
93bf083d
AL
98 char S[1024] = "";
99 char *End = S;
100
be4401bf 101 End += snprintf(S,sizeof(S),"200 URI Start\nURI: %s\n",Queue->Uri.c_str());
93bf083d
AL
102 if (Res.Size != 0)
103 End += snprintf(End,sizeof(S) - (End - S),"Size: %u\n",Res.Size);
104
105 if (Res.LastModified != 0)
106 End += snprintf(End,sizeof(S) - (End - S),"Last-Modified: %s\n",
107 TimeRFC1123(Res.LastModified).c_str());
108
be4401bf 109 if (Res.ResumePoint != 0)
93bf083d 110 End += snprintf(End,sizeof(S) - (End - S),"Resume-Point: %u\n",
be4401bf 111 Res.ResumePoint);
93bf083d
AL
112
113 strcat(End,"\n");
114 if (write(STDOUT_FILENO,S,strlen(S)) != (signed)strlen(S))
115 exit(100);
116}
117 /*}}}*/
118// AcqMethod::URIDone - A URI is finished /*{{{*/
119// ---------------------------------------------------------------------
120/* */
121void pkgAcqMethod::URIDone(FetchResult &Res, FetchResult *Alt)
122{
be4401bf
AL
123 if (Queue == 0)
124 abort();
125
93bf083d
AL
126 char S[1024] = "";
127 char *End = S;
128
be4401bf 129 End += snprintf(S,sizeof(S),"201 URI Done\nURI: %s\n",Queue->Uri.c_str());
93bf083d
AL
130
131 if (Res.Filename.empty() == false)
132 End += snprintf(End,sizeof(S) - (End - S),"Filename: %s\n",Res.Filename.c_str());
133
134 if (Res.Size != 0)
135 End += snprintf(End,sizeof(S) - (End - S),"Size: %u\n",Res.Size);
136
137 if (Res.LastModified != 0)
138 End += snprintf(End,sizeof(S) - (End - S),"Last-Modified: %s\n",
139 TimeRFC1123(Res.LastModified).c_str());
140
141 if (Res.MD5Sum.empty() == false)
142 End += snprintf(End,sizeof(S) - (End - S),"MD5Sum: %s\n",Res.MD5Sum.c_str());
143
144 if (Res.IMSHit == true)
145 strcat(End,"IMS-Hit: true\n");
146 End = S + strlen(S);
147
148 if (Alt != 0)
149 {
150 if (Alt->Filename.empty() == false)
151 End += snprintf(End,sizeof(S) - (End - S),"Alt-Filename: %s\n",Alt->Filename.c_str());
152
153 if (Alt->Size != 0)
154 End += snprintf(End,sizeof(S) - (End - S),"Alt-Size: %u\n",Alt->Size);
155
156 if (Alt->LastModified != 0)
157 End += snprintf(End,sizeof(S) - (End - S),"Alt-Last-Modified: %s\n",
158 TimeRFC1123(Alt->LastModified).c_str());
159
160 if (Alt->MD5Sum.empty() == false)
161 End += snprintf(End,sizeof(S) - (End - S),"Alt-MD5Sum: %s\n",
162 Alt->MD5Sum.c_str());
163
164 if (Alt->IMSHit == true)
165 strcat(End,"Alt-IMS-Hit: true\n");
166 }
167
168 strcat(End,"\n");
169 if (write(STDOUT_FILENO,S,strlen(S)) != (signed)strlen(S))
170 exit(100);
be4401bf
AL
171
172 // Dequeue
173 FetchItem *Tmp = Queue;
174 Queue = Queue->Next;
175 delete Tmp;
93bf083d
AL
176}
177 /*}}}*/
178// AcqMethod::Configuration - Handle the configuration message /*{{{*/
179// ---------------------------------------------------------------------
180/* This parses each configuration entry and puts it into the _config
181 Configuration class. */
182bool pkgAcqMethod::Configuration(string Message)
183{
184 ::Configuration &Cnf = *_config;
185
186 const char *I = Message.begin();
187
188 unsigned int Length = strlen("Config-Item");
189 for (; I + Length < Message.end(); I++)
190 {
191 // Not a config item
192 if (I[Length] != ':' || stringcasecmp(I,I+Length,"Config-Item") != 0)
193 continue;
194
195 I += Length + 1;
196
197 for (; I < Message.end() && *I == ' '; I++);
198 const char *Equals = I;
199 for (; Equals < Message.end() && *Equals != '='; Equals++);
200 const char *End = Equals;
201 for (; End < Message.end() && *End != '\n'; End++);
202 if (End == Equals)
203 return false;
204
205 Cnf.Set(string(I,Equals-I),string(Equals+1,End-Equals-1));
206 I = End;
207 }
208
209 return true;
210}
211 /*}}}*/
212// AcqMethod::Run - Run the message engine /*{{{*/
213// ---------------------------------------------------------------------
214/* */
be4401bf 215int pkgAcqMethod::Run(bool Single)
93bf083d 216{
93bf083d
AL
217 while (1)
218 {
be4401bf 219 // Block if the message queue is empty
93bf083d 220 if (Messages.empty() == true)
be4401bf
AL
221 {
222 if (Single == false)
223 if (WaitFd(STDIN_FILENO) == false)
224 return 0;
be4401bf 225
92e889c8
AL
226 if (ReadMessages(STDIN_FILENO,Messages) == false)
227 return 0;
228 }
229
be4401bf
AL
230 // Single mode exits if the message queue is empty
231 if (Single == true && Messages.empty() == true)
232 return 0;
233
93bf083d
AL
234 string Message = Messages.front();
235 Messages.erase(Messages.begin());
236
237 // Fetch the message number
238 char *End;
239 int Number = strtol(Message.c_str(),&End,10);
240 if (End == Message.c_str())
241 {
242 cerr << "Malformed message!" << endl;
243 return 100;
244 }
245
246 switch (Number)
247 {
248 case 601:
249 if (Configuration(Message) == false)
250 return 100;
251 break;
252
253 case 600:
be4401bf
AL
254 {
255 FetchItem *Tmp = new FetchItem;
256
257 Tmp->Uri = LookupTag(Message,"URI");
258 Tmp->DestFile = LookupTag(Message,"FileName");
259 StrToTime(LookupTag(Message,"Last-Modified"),Tmp->LastModified);
260 Tmp->Next = 0;
261
262 // Append it to the list
263 FetchItem **I = &Queue;
92e889c8 264 for (; *I != 0; I = &(*I)->Next);
be4401bf 265 *I = Tmp;
bfd22fc0
AL
266
267 // Notify that this item is to be fetched.
be4401bf 268 if (Fetch(Tmp) == false)
93bf083d 269 Fail();
bfd22fc0 270
93bf083d
AL
271 break;
272 }
273 }
274 }
275
276 return 0;
277}
278 /*}}}*/
be4401bf
AL
279// AcqMethod::Log - Send a log message /*{{{*/
280// ---------------------------------------------------------------------
281/* */
282void pkgAcqMethod::Log(const char *Format,...)
283{
284 string CurrentURI = "<UNKNOWN>";
285 if (Queue != 0)
286 CurrentURI = Queue->Uri;
287
288 va_list args;
289 va_start(args,Format);
290
291 // sprintf the description
292 char S[1024];
293 unsigned int Len = snprintf(S,sizeof(S),"101 Log\nURI: %s\n"
294 "Message: ",CurrentURI.c_str());
295
296 vsnprintf(S+Len,sizeof(S)-Len,Format,args);
297 strcat(S,"\n\n");
298
299 if (write(STDOUT_FILENO,S,strlen(S)) != (signed)strlen(S))
300 exit(100);
301}
302 /*}}}*/
303// AcqMethod::Status - Send a status message /*{{{*/
304// ---------------------------------------------------------------------
305/* */
306void pkgAcqMethod::Status(const char *Format,...)
307{
308 string CurrentURI = "<UNKNOWN>";
309 if (Queue != 0)
310 CurrentURI = Queue->Uri;
311
312 va_list args;
313 va_start(args,Format);
314
315 // sprintf the description
316 char S[1024];
92e889c8 317 unsigned int Len = snprintf(S,sizeof(S),"101 Status\nURI: %s\n"
be4401bf
AL
318 "Message: ",CurrentURI.c_str());
319
320 vsnprintf(S+Len,sizeof(S)-Len,Format,args);
321 strcat(S,"\n\n");
322
323 if (write(STDOUT_FILENO,S,strlen(S)) != (signed)strlen(S))
324 exit(100);
325}
326 /*}}}*/
327
93bf083d
AL
328// AcqMethod::FetchResult::FetchResult - Constructor /*{{{*/
329// ---------------------------------------------------------------------
330/* */
331pkgAcqMethod::FetchResult::FetchResult() : LastModified(0),
332 IMSHit(false), Size(0)
333{
334}
335 /*}}}*/
336