acquire-method.cc 9.0 KB

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