]> git.saurik.com Git - apt.git/blob - cmdline/apt-get.cc
Convert most callers of isspace() to isspace_ascii()
[apt.git] / cmdline / apt-get.cc
1 // -*- mode: cpp; mode: fold -*-
2 // Description /*{{{*/
3 // $Id: apt-get.cc,v 1.156 2004/08/28 01:05:16 mdz Exp $
4 /* ######################################################################
5
6 apt-get - Cover for dpkg
7
8 This is an allout cover for dpkg implementing a safer front end. It is
9 based largely on libapt-pkg.
10
11 The syntax is different,
12 apt-get [opt] command [things]
13 Where command is:
14 update - Resyncronize the package files from their sources
15 upgrade - Smart-Download the newest versions of all packages
16 dselect-upgrade - Follows dselect's changes to the Status: field
17 and installes new and removes old packages
18 dist-upgrade - Powerful upgrader designed to handle the issues with
19 a new distribution.
20 install - Download and install a given package (by name, not by .deb)
21 check - Update the package cache and check for broken packages
22 clean - Erase the .debs downloaded to /var/cache/apt/archives and
23 the partial dir too
24
25 ##################################################################### */
26 /*}}}*/
27 // Include Files /*{{{*/
28 #include <config.h>
29
30 #include <apt-pkg/acquire-item.h>
31 #include <apt-pkg/algorithms.h>
32 #include <apt-pkg/aptconfiguration.h>
33 #include <apt-pkg/cachefile.h>
34 #include <apt-pkg/cacheset.h>
35 #include <apt-pkg/clean.h>
36 #include <apt-pkg/cmndline.h>
37 #include <apt-pkg/debmetaindex.h>
38 #include <apt-pkg/depcache.h>
39 #include <apt-pkg/error.h>
40 #include <apt-pkg/fileutl.h>
41 #include <apt-pkg/indexfile.h>
42 #include <apt-pkg/init.h>
43 #include <apt-pkg/md5.h>
44 #include <apt-pkg/metaindex.h>
45 #include <apt-pkg/pkgrecords.h>
46 #include <apt-pkg/pkgsystem.h>
47 #include <apt-pkg/progress.h>
48 #include <apt-pkg/sourcelist.h>
49 #include <apt-pkg/srcrecords.h>
50 #include <apt-pkg/strutl.h>
51 #include <apt-pkg/version.h>
52 #include <apt-pkg/acquire.h>
53 #include <apt-pkg/configuration.h>
54 #include <apt-pkg/macros.h>
55 #include <apt-pkg/pkgcache.h>
56 #include <apt-pkg/cacheiterators.h>
57 #include <apt-pkg/upgrade.h>
58 #include <apt-pkg/sptr.h>
59
60 #include <apt-private/acqprogress.h>
61 #include <apt-private/private-cacheset.h>
62 #include <apt-private/private-cachefile.h>
63 #include <apt-private/private-cmndline.h>
64 #include <apt-private/private-download.h>
65 #include <apt-private/private-install.h>
66 #include <apt-private/private-main.h>
67 #include <apt-private/private-moo.h>
68 #include <apt-private/private-output.h>
69 #include <apt-private/private-update.h>
70 #include <apt-private/private-upgrade.h>
71 #include <apt-private/private-utils.h>
72 #include <apt-private/private-source.h>
73
74 #include <errno.h>
75 #include <signal.h>
76 #include <stddef.h>
77 #include <stdio.h>
78 #include <stdlib.h>
79 #include <string.h>
80 #include <sys/ioctl.h>
81 #include <sys/stat.h>
82 #include <unistd.h>
83 #include <pwd.h>
84 #include <grp.h>
85
86 #include <algorithm>
87 #include <fstream>
88 #include <iostream>
89 #include <sstream>
90 #include <set>
91 #include <string>
92 #include <vector>
93
94 #include <apti18n.h>
95 /*}}}*/
96
97 using namespace std;
98
99 /* mark packages as automatically/manually installed. {{{*/
100 static bool DoMarkAuto(CommandLine &CmdL)
101 {
102 bool Action = true;
103 int AutoMarkChanged = 0;
104 OpTextProgress progress;
105 CacheFile Cache;
106 if (Cache.Open() == false)
107 return false;
108
109 if (strcasecmp(CmdL.FileList[0],"markauto") == 0)
110 Action = true;
111 else if (strcasecmp(CmdL.FileList[0],"unmarkauto") == 0)
112 Action = false;
113
114 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
115 {
116 const char *S = *I;
117 // Locate the package
118 pkgCache::PkgIterator Pkg = Cache->FindPkg(S);
119 if (Pkg.end() == true) {
120 return _error->Error(_("Couldn't find package %s"),S);
121 }
122 else
123 {
124 if (!Action)
125 ioprintf(c1out,_("%s set to manually installed.\n"), Pkg.Name());
126 else
127 ioprintf(c1out,_("%s set to automatically installed.\n"),
128 Pkg.Name());
129
130 Cache->MarkAuto(Pkg,Action);
131 AutoMarkChanged++;
132 }
133 }
134
135 _error->Notice(_("This command is deprecated. Please use 'apt-mark auto' and 'apt-mark manual' instead."));
136
137 if (AutoMarkChanged && ! _config->FindB("APT::Get::Simulate",false))
138 return Cache->writeStateFile(NULL);
139 return false;
140 }
141 /*}}}*/
142 // DoDSelectUpgrade - Do an upgrade by following dselects selections /*{{{*/
143 // ---------------------------------------------------------------------
144 /* Follows dselect's selections */
145 static bool DoDSelectUpgrade(CommandLine &)
146 {
147 CacheFile Cache;
148 if (Cache.OpenForInstall() == false || Cache.CheckDeps() == false)
149 return false;
150
151 pkgDepCache::ActionGroup group(Cache);
152
153 // Install everything with the install flag set
154 pkgCache::PkgIterator I = Cache->PkgBegin();
155 for (;I.end() != true; ++I)
156 {
157 /* Install the package only if it is a new install, the autoupgrader
158 will deal with the rest */
159 if (I->SelectedState == pkgCache::State::Install)
160 Cache->MarkInstall(I,false);
161 }
162
163 /* Now install their deps too, if we do this above then order of
164 the status file is significant for | groups */
165 for (I = Cache->PkgBegin();I.end() != true; ++I)
166 {
167 /* Install the package only if it is a new install, the autoupgrader
168 will deal with the rest */
169 if (I->SelectedState == pkgCache::State::Install)
170 Cache->MarkInstall(I,true);
171 }
172
173 // Apply erasures now, they override everything else.
174 for (I = Cache->PkgBegin();I.end() != true; ++I)
175 {
176 // Remove packages
177 if (I->SelectedState == pkgCache::State::DeInstall ||
178 I->SelectedState == pkgCache::State::Purge)
179 Cache->MarkDelete(I,I->SelectedState == pkgCache::State::Purge);
180 }
181
182 /* Resolve any problems that dselect created, allupgrade cannot handle
183 such things. We do so quite aggressively too.. */
184 if (Cache->BrokenCount() != 0)
185 {
186 pkgProblemResolver Fix(Cache);
187
188 // Hold back held packages.
189 if (_config->FindB("APT::Ignore-Hold",false) == false)
190 {
191 for (pkgCache::PkgIterator I = Cache->PkgBegin(); I.end() == false; ++I)
192 {
193 if (I->SelectedState == pkgCache::State::Hold)
194 {
195 Fix.Protect(I);
196 Cache->MarkKeep(I);
197 }
198 }
199 }
200
201 if (Fix.Resolve() == false)
202 {
203 ShowBroken(c1out,Cache,false);
204 return _error->Error(_("Internal error, problem resolver broke stuff"));
205 }
206 }
207
208 // Now upgrade everything
209 if (APT::Upgrade::Upgrade(Cache, APT::Upgrade::FORBID_REMOVE_PACKAGES | APT::Upgrade::FORBID_INSTALL_NEW_PACKAGES) == false)
210 {
211 ShowBroken(c1out,Cache,false);
212 return _error->Error(_("Internal error, problem resolver broke stuff"));
213 }
214
215 return InstallPackages(Cache,false);
216 }
217 /*}}}*/
218 // DoCheck - Perform the check operation /*{{{*/
219 // ---------------------------------------------------------------------
220 /* Opening automatically checks the system, this command is mostly used
221 for debugging */
222 static bool DoCheck(CommandLine &)
223 {
224 CacheFile Cache;
225 Cache.Open();
226 Cache.CheckDeps();
227
228 return true;
229 }
230 /*}}}*/
231 // DoIndexTargets - Lists all IndexTargets /*{{{*/
232 static std::string format_key(std::string key)
233 {
234 // deb822 is case-insensitive, but the human eye prefers candy
235 std::transform(key.begin(), key.end(), key.begin(), ::tolower);
236 key[0] = ::toupper(key[0]);
237 size_t found = key.find("_uri");
238 if (found != std::string::npos)
239 key.replace(found, 4, "-URI");
240 while ((found = key.find('_')) != std::string::npos)
241 {
242 key[found] = '-';
243 key[found + 1] = ::toupper(key[found + 1]);
244 }
245 return key;
246 }
247 static bool DoIndexTargets(CommandLine &CmdL)
248 {
249 pkgCacheFile CacheFile;
250 pkgSourceList *SrcList = CacheFile.GetSourceList();
251
252 if (SrcList == NULL)
253 return false;
254
255 std::string const Format = _config->Find("APT::Get::IndexTargets::Format");
256 bool const ReleaseInfo = _config->FindB("APT::Get::IndexTargets::ReleaseInfo", true);
257 bool Filtered = CmdL.FileSize() > 1;
258 for (pkgSourceList::const_iterator S = SrcList->begin(); S != SrcList->end(); ++S)
259 {
260 std::vector<IndexTarget> const targets = (*S)->GetIndexTargets();
261 std::map<std::string, string> AddOptions;
262 if (ReleaseInfo)
263 {
264 AddOptions.insert(std::make_pair("TRUSTED", ((*S)->IsTrusted() ? "yes" : "no")));
265 pkgCache &Cache = *CacheFile.GetPkgCache();
266 pkgCache::RlsFileIterator const RlsFile = (*S)->FindInCache(Cache, false);
267 if (RlsFile.end())
268 continue;
269 #define APT_RELEASE(X,Y) if (RlsFile.Y() != NULL) AddOptions.insert(std::make_pair(X, RlsFile.Y()))
270 APT_RELEASE("CODENAME", Codename);
271 APT_RELEASE("SUITE", Archive);
272 APT_RELEASE("VERSION", Version);
273 APT_RELEASE("ORIGIN", Origin);
274 APT_RELEASE("LABEL", Label);
275 #undef APT_RELEASE
276 }
277
278 for (std::vector<IndexTarget>::const_iterator T = targets.begin(); T != targets.end(); ++T)
279 {
280 std::string filename = T->Option(ReleaseInfo ? IndexTarget::EXISTING_FILENAME : IndexTarget::FILENAME);
281 if (filename.empty())
282 continue;
283
284 std::ostringstream stanza;
285 if (Filtered || Format.empty())
286 {
287 stanza << "MetaKey: " << T->MetaKey << "\n"
288 << "ShortDesc: " << T->ShortDesc << "\n"
289 << "Description: " << T->Description << "\n"
290 << "URI: " << T->URI << "\n"
291 << "Filename: " << filename << "\n"
292 << "Optional: " << (T->IsOptional ? "yes" : "no") << "\n"
293 << "KeepCompressed: " << (T->KeepCompressed ? "yes" : "no") << "\n";
294 for (std::map<std::string,std::string>::const_iterator O = AddOptions.begin(); O != AddOptions.end(); ++O)
295 stanza << format_key(O->first) << ": " << O->second << "\n";
296 for (std::map<std::string,std::string>::const_iterator O = T->Options.begin(); O != T->Options.end(); ++O)
297 {
298 if (O->first == "PDIFFS")
299 stanza << "PDiffs: " << O->second << "\n";
300 else if (O->first == "COMPRESSIONTYPES")
301 stanza << "CompressionTypes: " << O->second << "\n";
302 else if (O->first == "DEFAULTENABLED")
303 stanza << "DefaultEnabled: " << O->second << "\n";
304 else
305 stanza << format_key(O->first) << ": " << O->second << "\n";
306 }
307 stanza << "\n";
308
309 if (Filtered)
310 {
311 // that is a bit crude, but good enough for now
312 bool found = true;
313 std::string haystack = std::string("\n") + stanza.str() + "\n";
314 std::transform(haystack.begin(), haystack.end(), haystack.begin(), ::tolower);
315 size_t const filesize = CmdL.FileSize() - 1;
316 for (size_t i = 0; i != filesize; ++i)
317 {
318 std::string needle = std::string("\n") + CmdL.FileList[i + 1] + "\n";
319 std::transform(needle.begin(), needle.end(), needle.begin(), ::tolower);
320 if (haystack.find(needle) != std::string::npos)
321 continue;
322 found = false;
323 break;
324 }
325 if (found == false)
326 continue;
327 }
328 }
329
330 if (Format.empty())
331 cout << stanza.str();
332 else
333 {
334 std::string out = SubstVar(Format, "$(FILENAME)", filename);
335 out = T->Format(out);
336 for (std::map<std::string,std::string>::const_iterator O = AddOptions.begin(); O != AddOptions.end(); ++O)
337 out = SubstVar(out, std::string("$(") + O->first + ")", O->second);
338 cout << out << std::endl;
339 }
340 }
341 }
342
343 return true;
344 }
345 /*}}}*/
346 static bool ShowHelp(CommandLine &) /*{{{*/
347 {
348 if (_config->FindB("version") == true)
349 {
350 cout << _("Supported modules:") << endl;
351
352 for (unsigned I = 0; I != pkgVersioningSystem::GlobalListLen; I++)
353 {
354 pkgVersioningSystem *VS = pkgVersioningSystem::GlobalList[I];
355 if (_system != 0 && _system->VS == VS)
356 cout << '*';
357 else
358 cout << ' ';
359 cout << "Ver: " << VS->Label << endl;
360
361 /* Print out all the packaging systems that will work with
362 this VS */
363 for (unsigned J = 0; J != pkgSystem::GlobalListLen; J++)
364 {
365 pkgSystem *Sys = pkgSystem::GlobalList[J];
366 if (_system == Sys)
367 cout << '*';
368 else
369 cout << ' ';
370 if (Sys->VS->TestCompatibility(*VS) == true)
371 cout << "Pkg: " << Sys->Label << " (Priority " << Sys->Score(*_config) << ")" << endl;
372 }
373 }
374
375 for (unsigned I = 0; I != pkgSourceList::Type::GlobalListLen; I++)
376 {
377 pkgSourceList::Type *Type = pkgSourceList::Type::GlobalList[I];
378 cout << " S.L: '" << Type->Name << "' " << Type->Label << endl;
379 }
380
381 for (unsigned I = 0; I != pkgIndexFile::Type::GlobalListLen; I++)
382 {
383 pkgIndexFile::Type *Type = pkgIndexFile::Type::GlobalList[I];
384 cout << " Idx: " << Type->Label << endl;
385 }
386
387 return true;
388 }
389
390 std::cout <<
391 _("Usage: apt-get [options] command\n"
392 " apt-get [options] install|remove pkg1 [pkg2 ...]\n"
393 " apt-get [options] source pkg1 [pkg2 ...]\n"
394 "\n"
395 "apt-get is a command line interface for retrieval of packages\n"
396 "and information about them from authenticated sources and\n"
397 "for installation, upgrade and removal of packages together\n"
398 "with their dependencies.\n");
399 return true;
400 }
401 /*}}}*/
402 static std::vector<aptDispatchWithHelp> GetCommands() /*{{{*/
403 {
404 return {
405 {"update", &DoUpdate, _("Retrieve new lists of packages")},
406 {"upgrade", &DoUpgrade, _("Perform an upgrade")},
407 {"install", &DoInstall, _("Install new packages (pkg is libc6 not libc6.deb)")},
408 {"remove", &DoInstall, _("Remove packages")},
409 {"purge", &DoInstall, _("Remove packages and config files")},
410 {"autoremove", &DoInstall, _("Remove automatically all unused packages")},
411 {"auto-remove", &DoInstall, nullptr},
412 {"markauto", &DoMarkAuto, nullptr},
413 {"unmarkauto", &DoMarkAuto, nullptr},
414 {"dist-upgrade", &DoDistUpgrade, _("Distribution upgrade, see apt-get(8)")},
415 {"full-upgrade", &DoDistUpgrade, nullptr},
416 {"dselect-upgrade", &DoDSelectUpgrade, _("Follow dselect selections")},
417 {"build-dep", &DoBuildDep, _("Configure build-dependencies for source packages")},
418 {"clean", &DoClean, _("Erase downloaded archive files")},
419 {"autoclean", &DoAutoClean, _("Erase old downloaded archive files")},
420 {"auto-clean", &DoAutoClean, nullptr},
421 {"check", &DoCheck, _("Verify that there are no broken dependencies")},
422 {"source", &DoSource, _("Download source archives")},
423 {"download", &DoDownload, _("Download the binary package into the current directory")},
424 {"changelog", &DoChangelog, _("Download and display the changelog for the given package")},
425 {"indextargets", &DoIndexTargets, nullptr},
426 {"moo", &DoMoo, nullptr},
427 {nullptr, nullptr, nullptr}
428 };
429 }
430 /*}}}*/
431 int main(int argc,const char *argv[]) /*{{{*/
432 {
433 InitLocale();
434
435 // Parse the command line and initialize the package library
436 CommandLine CmdL;
437 auto const Cmds = ParseCommandLine(CmdL, APT_CMD::APT_GET, &_config, &_system, argc, argv, &ShowHelp, &GetCommands);
438
439 InitSignals();
440 InitOutput();
441
442 CheckIfSimulateMode(CmdL);
443
444 return DispatchCommandLine(CmdL, Cmds);
445 }
446 /*}}}*/