- initial import of revision 374 from cnc
[apt.git] / apt-pkg / luaiface.cc
1 // CNC:2003-03-15
2 // -*- mode: cpp; mode: fold -*-
3 // Description                                                          /*{{{*/
4 // $Id: repository.cc,v 1.4 2002/07/29 18:13:52 niemeyer Exp $
5 /* ######################################################################
6
7    Lua interface system.
8    
9    ##################################################################### */
10                                                                         /*}}}*/
11 #ifdef __GNUG__
12 #pragma implementation "apt-pkg/luaiface.h"
13 #endif       
14
15 #include <config.h>
16
17 #ifdef WITH_LUA
18
19 extern "C" {
20 #include "lua.h"
21 #include "lualib.h"
22 #include "lauxlib.h"
23 #include "lposix.h"
24 #include "lrexlib.h"
25 #include "linit.h"
26 }
27
28 #include <apt-pkg/depcache.h>
29 #include <apt-pkg/configuration.h>
30 #include <apt-pkg/algorithms.h>
31 #include <apt-pkg/error.h>
32 #include <apt-pkg/pkgrecords.h>
33 #include <apt-pkg/sptr.h>
34 #include <apt-pkg/version.h>
35 #include <apt-pkg/pkgsystem.h>
36
37 #include <apt-pkg/luaiface.h>
38
39 #include <apti18n.h>
40
41 #include <limits.h>
42 #include <unistd.h>
43 #include <sys/types.h>
44 #include <assert.h>
45
46 #define pushudata(ctype, value) \
47    do { \
48       ctype *_tmp = (ctype *) lua_newuserdata(L, sizeof(ctype)); \
49       *_tmp = (ctype) value; \
50       luaL_getmetatable(L, #ctype); \
51       lua_setmetatable(L, -2); \
52    } while (0)
53
54 #define checkudata(ctype, target, n) \
55    do { \
56       ctype *_tmp = (ctype *) luaL_checkudata(L, n, #ctype); \
57       if (_tmp != NULL) \
58          target = *_tmp; \
59       else \
60          target = NULL; \
61    } while (0)
62
63 Lua *_GetLuaObj()
64 {
65    static Lua *Obj = new Lua;
66    return Obj;
67 }
68
69 static int luaopen_apt(lua_State *L);
70
71 static int AptLua_vercomp(lua_State *L);
72 static int AptLua_pkgcomp(lua_State *L);
73
74 #define CACHE_KEY "ChunkCache"
75
76 Lua::Lua()
77       : DepCache(0), Cache(0), CacheControl(0), Fix(0), DontFix(0)
78 {
79    _config->CndSet("Dir::Bin::scripts", "/usr/lib/apt/scripts");
80
81    const luaL_reg lualibs[] = {
82       {"base", luaopen_base},
83       {"table", luaopen_table},
84       {"io", luaopen_io},
85       {"string", luaopen_string},
86       {"math", luaopen_math},
87       {"debug", luaopen_debug},
88       {"loadlib", luaopen_loadlib},
89       {"posix", luaopen_posix},
90       {"rex", luaopen_rex},
91       {"init", luaopen_init},
92       {"apt", luaopen_apt},
93       {NULL, NULL}
94    };
95    L = lua_open();
96    const luaL_reg *lib = lualibs;
97    for (; lib->name; lib++) {
98       lib->func(L);  /* open library */
99       lua_settop(L, 0);  /* discard any results */
100    }
101    luaL_newmetatable(L, "pkgCache::Package*");
102    lua_pushstring(L, "__eq");
103    lua_pushcfunction(L, AptLua_pkgcomp);
104    lua_settable(L, -3);
105    luaL_newmetatable(L, "pkgCache::Version*");
106    lua_pushstring(L, "__eq");
107    lua_pushcfunction(L, AptLua_vercomp);
108    lua_settable(L, -3);
109    lua_pop(L, 2);
110    lua_pushstring(L, CACHE_KEY);
111    lua_newtable(L);
112    lua_rawset(L, LUA_REGISTRYINDEX);
113 }
114
115 Lua::~Lua()
116 {
117    if (CacheControl)
118       CacheControl->Close();
119    lua_close(L);
120 }
121
122 bool Lua::HasScripts(const char *ConfListKey)
123 {
124    const Configuration::Item *Top = _config->Tree(ConfListKey);
125    if (Top != 0 && Top->Child != 0)
126       return true;
127    return false;
128 }
129
130 bool Lua::RunScripts(const char *ConfListKey, bool CacheChunks)
131 {
132    lua_pushstring(L, CACHE_KEY);
133    lua_rawget(L, LUA_REGISTRYINDEX);
134    assert(lua_istable(L, -1));
135
136    int CacheIndex = lua_gettop(L);
137
138    lua_pushstring(L, ConfListKey);
139    lua_rawget(L, CacheIndex);
140
141    if (lua_isnil(L, -1)) {
142       string File, Dir = _config->FindDir("Dir::Bin::scripts", "");
143       lua_pop(L, 1);
144       lua_newtable(L);
145       int Count = 0;
146       const Configuration::Item *Top = _config->Tree(ConfListKey);
147       for (Top = (Top == 0?0:Top->Child); Top != 0; Top = Top->Next) {
148          const string &Value = Top->Value;
149          if (Value.empty() == true)
150             continue;
151          if (Value == "interactive") {
152             lua_pushstring(L, "script_slot");
153             lua_pushstring(L, ConfListKey);
154             lua_rawset(L, LUA_GLOBALSINDEX);
155
156             RunInteractive(ConfListKey);
157
158             lua_pushstring(L, "script_slot");
159             lua_pushnil(L);
160             lua_rawset(L, LUA_GLOBALSINDEX);
161             continue;
162          }
163          if (Value[0] == '.' || Value[0] == '/') {
164             if (FileExists(Value) == true)
165                File = Value;
166             else
167                continue;
168          } else {
169             File = Dir+Value;
170             if (FileExists(File) == false)
171                continue;
172          }
173          if (luaL_loadfile(L, File.c_str()) != 0) {
174             _error->Warning(_("Error loading script: %s"),
175                             lua_tostring(L, -1));
176             lua_pop(L, 1);
177          }
178          lua_rawseti(L, -2, ++Count);
179       }
180       if (Count == 0) {
181          lua_pop(L, 2); // Script table and cache table.
182          return false;
183       }
184       if (CacheChunks == true) {
185          lua_pushstring(L, ConfListKey);
186          lua_pushvalue(L, -2);
187          lua_rawset(L, CacheIndex);
188       }
189    }
190
191    lua_pushstring(L, "script_slot");
192    lua_pushstring(L, ConfListKey);
193    lua_rawset(L, LUA_GLOBALSINDEX);
194
195    InternalRunScript();
196
197    lua_pushstring(L, "script_slot");
198    lua_pushnil(L);
199    lua_rawset(L, LUA_GLOBALSINDEX);
200
201    lua_pop(L, 1);
202
203    return true;
204 }
205
206 bool Lua::RunScript(const char *Script, const char *ChunkCacheKey)
207 {
208    lua_pushstring(L, CACHE_KEY);
209    lua_rawget(L, LUA_REGISTRYINDEX);
210    assert(lua_istable(L, -1));
211
212    int CacheIndex = lua_gettop(L);
213
214    if (Script == NULL || *Script == '\0')
215       return false;
216    
217    bool Cached = false;
218    if (ChunkCacheKey) {
219       lua_pushstring(L, ChunkCacheKey);
220       lua_rawget(L, 1);
221       if (!lua_isnil(L, -1))
222          Cached = true;
223       else
224          lua_pop(L, 1);
225    }
226
227    if (Cached == false) {
228       if (luaL_loadbuffer(L, Script, strlen(Script), "<lua>") != 0) {
229          _error->Warning(_("Error loading script: %s"),
230                          lua_tostring(L, -1));
231          lua_pop(L, 2); // Error and cache table
232          assert(lua_gettop(L) == 0);
233          return false;
234       }
235
236       if (ChunkCacheKey) {
237          lua_pushstring(L, ChunkCacheKey);
238          lua_pushvalue(L, -2);
239          lua_rawset(L, CacheIndex);
240       }
241    }
242
243    InternalRunScript();
244
245    lua_pop(L, 1);
246
247    return true;
248 }
249
250 void Lua::InternalRunScript()
251 {
252    // Script or script list must be at the top, and will be poped.
253    if (lua_istable(L, -1)) {
254       int t = lua_gettop(L);
255       lua_pushnil(L);
256       while (lua_next(L, t)) {
257          if (lua_pcall(L, 0, 0, 0) != 0) {
258             _error->Warning(_("Error running script: %s"),
259                             lua_tostring(L, -1));
260             lua_remove(L, -1);
261          }
262       }
263       lua_pop(L, 1);
264    } else {
265       if (lua_pcall(L, 0, 0, 0) != 0) {
266          _error->Warning(_("Error running script: %s"),
267                          lua_tostring(L, -1));
268          lua_remove(L, -1);
269       }
270    }
271 }
272
273 /* From lua.c */
274 static int AptAux_readline(lua_State *l, const char *prompt) {
275    static char buffer[1024];
276    if (prompt) {
277       fputs(prompt, stdout);
278       fflush(stdout);
279    }
280    if (fgets(buffer, sizeof(buffer), stdin) == NULL) {
281       return 0;  /* read fails */
282    } else {
283       lua_pushstring(l, buffer);
284       return 1;
285    }
286 }
287
288 /* Based on lua.c */
289 void Lua::RunInteractive(const char *PlaceHint)
290 {
291    cout << endl
292         << "APT Interactive " << LUA_VERSION << " Interpreter" << endl;
293    if (PlaceHint)
294         cout << "[" << PlaceHint << "]" << endl;
295    for (;;) {
296       if (AptAux_readline(L, "> ") == 0)
297          break;
298       if (lua_tostring(L, -1)[0] == '=') {
299          lua_pushfstring(L, "print(%s)", lua_tostring(L, -1)+1);
300          lua_remove(L, -2);
301       }
302       int rc = 0;
303       for (;;) {
304          rc = luaL_loadbuffer(L, lua_tostring(L, -1),
305                               lua_strlen(L, -1), "<lua>");
306          if (rc == LUA_ERRSYNTAX &&
307              strstr(lua_tostring(L, -1), "near `<eof>'") != NULL) {
308             if (AptAux_readline(L, ">> ") == 0)
309                break;
310             lua_remove(L, -2); // Remove error
311             lua_concat(L, 2);
312             continue;
313          }
314          break;
315       }
316       if (rc == 0)
317          rc = lua_pcall(L, 0, 0, 0);
318       if (rc != 0) {
319          fprintf(stderr, "%s\n", lua_tostring(L, -1));
320          lua_pop(L, 1);
321       }
322       lua_pop(L, 1); // Remove line
323    }
324    fputs("\n", stdout);
325 }
326
327 void Lua::ResetScript(const char *ChunkCacheKey)
328 {
329    lua_pushstring(L, ChunkCacheKey);
330    lua_pushnil(L);
331    lua_rawset(L, 1);
332 }
333
334 void Lua::SetGlobal(const char *Name)
335 {
336    lua_pushstring(L, Name);
337    lua_pushnil(L);
338    lua_rawset(L, LUA_GLOBALSINDEX);
339    Globals.push_back(Name);
340 }
341
342 void Lua::SetGlobal(const char *Name, const char *Value)
343 {
344    if (Value != NULL) {
345       lua_pushstring(L, Name);
346       lua_pushstring(L, Value);
347       lua_rawset(L, LUA_GLOBALSINDEX);
348    }
349    Globals.push_back(Name);
350 }
351
352 void Lua::SetGlobal(const char *Name, pkgCache::Package *Value)
353 {
354    if (Value != NULL) {
355       lua_pushstring(L, Name);
356       pushudata(pkgCache::Package*, Value);
357       lua_rawset(L, LUA_GLOBALSINDEX);
358    }
359    Globals.push_back(Name);
360 }
361
362 void Lua::SetGlobal(const char *Name, const char **Value, int Total)
363 {
364    lua_pushstring(L, Name);
365    lua_newtable(L);
366    if (Total == -1)
367       Total = INT_MAX;
368    for (int i=0; i != Total && Value[i] != NULL; i++) {
369       lua_pushstring(L, Value[i]);
370       lua_rawseti(L, -2, i+1);
371    }
372    lua_rawset(L, LUA_GLOBALSINDEX);
373    Globals.push_back(Name);
374 }
375
376 void Lua::SetGlobal(const char *Name, vector<const char *> &Value,
377                     int Total)
378 {
379    lua_pushstring(L, Name);
380    lua_newtable(L);
381    if (Total == -1 || Total > Value.size())
382       Total = Value.size();
383    for (int i=0; i != Total && Value[i] != NULL; i++) {
384       lua_pushstring(L, Value[i]);
385       lua_rawseti(L, -2, i+1);
386    }
387    lua_rawset(L, LUA_GLOBALSINDEX);
388    Globals.push_back(Name);
389 }
390
391 void Lua::SetGlobal(const char *Name, vector<string> &Value,
392                     int Total)
393 {
394    lua_pushstring(L, Name);
395    lua_newtable(L);
396    if (Total == -1 || Total > Value.size())
397       Total = Value.size();
398    for (int i=0; i != Total; i++) {
399       lua_pushstring(L, Value[i].c_str());
400       lua_rawseti(L, -2, i+1);
401    }
402    lua_rawset(L, LUA_GLOBALSINDEX);
403    Globals.push_back(Name);
404 }
405
406 void Lua::SetGlobal(const char *Name, vector<pkgCache::Package*> &Value,
407                     int Total)
408 {
409    lua_pushstring(L, Name);
410    lua_newtable(L);
411    if (Total == -1 || Total > Value.size())
412       Total = Value.size();
413    for (int i=0; i != Total && Value[i] != NULL; i++) {
414       pushudata(pkgCache::Package*, Value[i]);
415       lua_rawseti(L, -2, i+1);
416    }
417    lua_rawset(L, LUA_GLOBALSINDEX);
418    Globals.push_back(Name);
419 }
420
421 void Lua::SetGlobal(const char *Name, bool Value)
422 {
423    lua_pushstring(L, Name);
424    lua_pushboolean(L, Value);
425    lua_rawset(L, LUA_GLOBALSINDEX);
426    Globals.push_back(Name);
427 }
428
429 void Lua::SetGlobal(const char *Name, double Value)
430 {
431    lua_pushstring(L, Name);
432    lua_pushnumber(L, Value);
433    lua_rawset(L, LUA_GLOBALSINDEX);
434    Globals.push_back(Name);
435 }
436
437 void Lua::SetGlobal(const char *Name, void *Value)
438 {
439    if (Value != NULL) {
440       lua_pushstring(L, Name);
441       lua_pushlightuserdata(L, Value);
442       lua_rawset(L, LUA_GLOBALSINDEX);
443    }
444    Globals.push_back(Name);
445 }
446
447 void Lua::SetGlobal(const char *Name, lua_CFunction Value)
448 {
449    lua_pushstring(L, Name);
450    lua_pushcfunction(L, Value);
451    lua_rawset(L, LUA_GLOBALSINDEX);
452    Globals.push_back(Name);
453 }
454
455 void Lua::ResetGlobals()
456 {
457    if (Globals.empty() == false) {
458       for (vector<string>::const_iterator I = Globals.begin();
459            I != Globals.end(); I++) {
460          lua_pushstring(L, I->c_str());
461          lua_pushnil(L);
462          lua_rawset(L, LUA_GLOBALSINDEX);
463       }
464       Globals.clear();
465    }
466 }
467
468 const char *Lua::GetGlobalStr(const char *Name)
469 {
470    lua_pushstring(L, Name);
471    lua_rawget(L, LUA_GLOBALSINDEX);
472    const char *Ret = NULL;
473    if (lua_isstring(L, -1))
474       Ret = lua_tostring(L, -1);
475    lua_remove(L, -1);
476    return Ret;
477 }
478
479 vector<string> Lua::GetGlobalStrList(const char *Name)
480 {
481    vector<string> Ret;
482    lua_pushstring(L, Name);
483    lua_rawget(L, LUA_GLOBALSINDEX);
484    int t = lua_gettop(L);
485    if (lua_istable(L, t)) {
486       lua_pushnil(L);
487       while (lua_next(L, t) != 0) {
488          if (lua_isstring(L, -1))
489             Ret.push_back(lua_tostring(L, -1));
490          lua_pop(L, 1);
491       }
492    }
493    lua_remove(L, -1);
494    return Ret;
495 }
496
497 double Lua::GetGlobalNum(const char *Name)
498 {
499    lua_pushstring(L, Name);
500    lua_rawget(L, LUA_GLOBALSINDEX);
501    double Ret = 0;
502    if (lua_isnumber(L, -1))
503       Ret = lua_tonumber(L, -1);
504    lua_remove(L, -1);
505    return Ret;
506 }
507
508 bool Lua::GetGlobalBool(const char *Name)
509 {
510    lua_pushstring(L, Name);
511    lua_rawget(L, LUA_GLOBALSINDEX);
512    bool Ret = lua_toboolean(L, -1);
513    lua_remove(L, -1);
514    return Ret;
515 }
516
517 void *Lua::GetGlobalPtr(const char *Name)
518 {
519    lua_pushstring(L, Name);
520    lua_rawget(L, LUA_GLOBALSINDEX);
521    void *Ret = NULL;
522    if (lua_isuserdata(L, -1))
523       Ret = lua_touserdata(L, -1);
524    lua_remove(L, -1);
525    return Ret;
526 }
527
528 pkgCache::Package *Lua::GetGlobalPkg(const char *Name)
529 {
530    lua_pushstring(L, Name);
531    lua_rawget(L, LUA_GLOBALSINDEX);
532    pkgCache::Package *Ret;
533    checkudata(pkgCache::Package*, Ret, -1);
534    lua_remove(L, -1);
535    return Ret;
536 }
537
538 vector<pkgCache::Package*> Lua::GetGlobalPkgList(const char *Name)
539 {
540    vector<pkgCache::Package*> Ret;
541    lua_pushstring(L, Name);
542    lua_rawget(L, LUA_GLOBALSINDEX);
543    int t = lua_gettop(L);
544    if (lua_istable(L, t)) {
545       lua_pushnil(L);
546       while (lua_next(L, t) != 0) {
547          pkgCache::Package *Pkg;
548          checkudata(pkgCache::Package*, Pkg, -1);
549          if (Pkg)
550             Ret.push_back(Pkg);
551          lua_pop(L, 1);
552       }
553    }
554    lua_remove(L, -1);
555    return Ret;
556 }
557
558 void Lua::SetDepCache(pkgDepCache *DepCache_)
559 {
560    DepCache = DepCache_;
561    if (DepCache != NULL)
562       Cache = &DepCache->GetCache();
563    else
564       Cache = NULL;
565 }
566
567 void Lua::SetCacheControl(LuaCacheControl *CacheControl_)
568 {
569    CacheControl = CacheControl_;
570 }
571
572 pkgDepCache *Lua::GetDepCache(lua_State *L)
573 {
574    if (DepCache == NULL && CacheControl)
575       SetDepCache(CacheControl->Open());
576    if (DepCache == NULL && L != NULL) {
577       lua_pushstring(L, "no depcache available at that point");
578       lua_error(L);
579    }
580    return DepCache;
581 }
582
583 pkgCache *Lua::GetCache(lua_State *L)
584 {
585    if (Cache == NULL && CacheControl)
586       SetDepCache(CacheControl->Open());
587    if (Cache == NULL && L != NULL) {
588       lua_pushstring(L, "no cache available at that point");
589       lua_error(L);
590    }
591    return Cache;
592 }
593
594 inline pkgCache::Package *AptAux_ToPackage(lua_State *L, int n)
595 {
596    if (lua_isstring(L, n)) {
597       pkgCache *Cache = _lua->GetCache(L);
598       if (Cache == NULL)
599          return NULL;
600       const char *Name = lua_tostring(L, n);
601       return (pkgCache::Package*)Cache->FindPackage(Name);
602    } else {
603       pkgCache::Package *Pkg;
604       checkudata(pkgCache::Package*, Pkg, n);
605       if (Pkg == NULL)
606          luaL_argerror(L, n, "invalid package");
607       return Pkg;
608    }
609 }
610
611 static pkgCache::PkgIterator *AptAux_ToPkgIterator(lua_State *L, int n)
612 {
613    pkgCache::Package *Pkg = AptAux_ToPackage(L, n);
614    if (Pkg == NULL)
615       return NULL;
616    pkgCache *Cache = _lua->GetCache(L);
617    if (Cache == NULL)
618       return NULL;
619    return new pkgCache::PkgIterator(*Cache, Pkg);
620 }
621
622 inline pkgCache::Version *AptAux_ToVersion(lua_State *L, int n)
623 {
624    pkgCache::Version *Ver;
625    checkudata(pkgCache::Version*, Ver, n);
626    if (Ver == NULL)
627       luaL_argerror(L, n, "invalid version");
628    return Ver;
629 }
630
631 static pkgCache::VerIterator *AptAux_ToVerIterator(lua_State *L, int n)
632 {
633    pkgCache::Version *Ver = AptAux_ToVersion(L, n);
634    if (Ver == NULL)
635       return NULL;
636    pkgCache *Cache = _lua->GetCache(L);
637    if (Cache == NULL)
638       return NULL;
639    return new pkgCache::VerIterator(*Cache, Ver);
640 }
641
642 inline int AptAux_PushPackage(lua_State *L, pkgCache::Package *Pkg)
643 {
644    if (Pkg != 0) {
645       pushudata(pkgCache::Package*, Pkg);
646       return 1;
647    }
648    return 0;
649 }
650
651 inline int AptAux_PushVersion(lua_State *L, pkgCache::Version *Ver)
652 {
653    if (Ver != 0) {
654       pushudata(pkgCache::Version*, Ver);
655       return 1;
656    }
657    return 0;
658 }
659
660 static int AptAux_PushVersion(lua_State *L, map_ptrloc Loc)
661 {
662    pkgCache *Cache = _lua->GetCache(L);
663    if (Cache == NULL)
664       return 0;
665    if (Loc != 0) {
666       pkgCache::Version *Ver = Cache->VerP+Loc;
667       if (Ver != 0) {
668          pushudata(pkgCache::Version*, Ver);
669          return 1;
670       }
671    }
672    return 0;
673 }
674
675 static int AptAux_PushCacheString(lua_State *L, map_ptrloc Pos)
676 {
677    if (Pos == 0)
678       return 0;
679    pkgCache *Cache = _lua->GetCache(L);
680    if (Cache == NULL)
681       return 0;
682    const char *Str = Cache->StrP+Pos;
683    lua_pushstring(L, Str);
684    return 1;
685 }
686
687 inline int AptAux_PushBool(lua_State *L, bool Value)
688 {
689    if (Value == true) {
690       lua_pushnumber(L, 1);
691       return 1;
692    }
693    return 0;
694 }
695
696 #define MARK_KEEP      0
697 #define MARK_INSTALL   1
698 #define MARK_REINSTALL 2
699 #define MARK_REMOVE    3
700
701 static int AptAux_mark(lua_State *L, int Kind)
702 {
703    pkgCache::Package *Pkg = AptAux_ToPackage(L, 1);
704    if (Pkg != NULL) {
705       pkgDepCache *DepCache = _lua->GetDepCache(L);
706       if (DepCache == NULL)
707          return 0;
708       pkgProblemResolver *MyFix = NULL;
709       pkgProblemResolver *Fix = _lua->GetProblemResolver();
710       if (Fix == NULL)
711          Fix = MyFix = new pkgProblemResolver(DepCache);
712       pkgCache::PkgIterator PkgI(DepCache->GetCache(), Pkg);
713       Fix->Clear(PkgI);
714       Fix->Protect(PkgI);
715       switch (Kind) {
716          case MARK_KEEP:
717             DepCache->MarkKeep(PkgI);
718             break;
719          case MARK_INSTALL:
720             DepCache->MarkInstall(PkgI);
721             break;
722          case MARK_REINSTALL:
723             DepCache->SetReInstall(PkgI, true);
724             break;
725          case MARK_REMOVE:
726             Fix->Remove(PkgI);
727             DepCache->MarkDelete(PkgI);
728             break;
729       }
730       if (_lua->GetDontFix() == false && DepCache->BrokenCount() > 0) {
731          if (Kind != MARK_KEEP) {
732             Fix->Resolve(false);
733          } else {
734             Fix->InstallProtect();
735             Fix->Resolve(true);
736          }
737       }
738       delete MyFix;
739    }
740    return 0;
741 }
742
743 static int AptAux_marksimple(lua_State *L, int Kind)
744 {
745    pkgCache::Package *Pkg = AptAux_ToPackage(L, 1);
746    if (Pkg != NULL) {
747       pkgDepCache *DepCache = _lua->GetDepCache(L);
748       if (DepCache == NULL)
749          return 0;
750       pkgCache::PkgIterator PkgI(DepCache->GetCache(), Pkg);
751       pkgDepCache::State state(DepCache);
752       switch (Kind) {
753          case MARK_KEEP:
754             DepCache->MarkKeep(PkgI);
755             break;
756          case MARK_INSTALL:
757             DepCache->MarkInstall(PkgI, false);
758             break;
759          case MARK_REMOVE:
760             DepCache->MarkDelete(PkgI);
761             break;
762       }
763       if (DepCache->BrokenCount() > 0)
764          state.Restore();
765    }
766    return 0;
767 }
768
769 static int AptLua_confget(lua_State *L)
770 {
771    const char *key = luaL_checkstring(L, 1);
772    const char *def = luaL_optstring(L, 2, "");
773    string Value;
774    if (key != NULL)
775       Value = _config->FindAny(key, def);
776    lua_pushstring(L, Value.c_str());
777    return 1;
778 }
779
780 static int AptLua_confgetlist(lua_State *L)
781 {
782    const char *key = luaL_checkstring(L, 1);
783    if (key == NULL)
784       return 0;
785    const Configuration::Item *Top = _config->Tree(key);
786    lua_newtable(L);
787    int i = 1;
788    for (Top = (Top == 0?0:Top->Child); Top != 0; Top = Top->Next) {
789        if (Top->Value.empty() == true)
790           continue;
791        lua_pushstring(L, Top->Value.c_str());
792        lua_rawseti(L, -2, i++);
793    }
794    return 1;
795 }
796
797 static int AptLua_confset(lua_State *L)
798 {
799    const char *key = luaL_checkstring(L, 1);
800    const char *val = luaL_checkstring(L, 2);
801    int cnd = 0;
802    if (lua_gettop(L) >= 3 && lua_isboolean(L, 3))
803       cnd = lua_toboolean(L, 3);
804    else
805       cnd = luaL_optint(L, 3, 0);
806    if (key != NULL && val != NULL) {
807       if (cnd != 0)
808          _config->CndSet(key, val);
809       else
810          _config->Set(key, val);
811    }
812    return 0;
813 }
814
815 static int AptLua_confexists(lua_State *L)
816 {
817    const char *key = luaL_checkstring(L, 1);
818    if (key == NULL)
819       return 0;
820    if (_config->Exists(key) == true)
821       lua_pushnumber(L, 1);
822    else
823       lua_pushnil(L);
824    return 1;
825 }
826
827 static int AptLua_confclear(lua_State *L)
828 {
829    const char *key = luaL_checkstring(L, 1);
830    if (key != NULL)
831       _config->Clear(key);
832    return 0;
833 }
834
835
836 static int AptLua_pkgfind(lua_State *L)
837 {
838    const char *name = luaL_checkstring(L, 1);
839    if (name == NULL)
840       return 0;
841    pkgCache *Cache = _lua->GetCache(L);
842    if (Cache == NULL)
843       return 0;
844    return AptAux_PushPackage(L, Cache->FindPackage(name));
845 }
846
847 static int AptLua_pkglist(lua_State *L)
848 {
849    pkgCache *Cache = _lua->GetCache(L);
850    if (Cache == NULL)
851       return 0;
852    lua_newtable(L);
853    int i = 1;
854    for (pkgCache::PkgIterator PkgI = Cache->PkgBegin();
855         PkgI.end() == false; PkgI++) {
856       pushudata(pkgCache::Package*, PkgI);
857       lua_rawseti(L, -2, i++);
858    }
859    return 1;
860 }
861
862 static int AptLua_pkgname(lua_State *L)
863 {
864    pkgCache::Package *Pkg = AptAux_ToPackage(L, 1);
865    if (Pkg == NULL)
866       return 0;
867    return AptAux_PushCacheString(L, Pkg->Name);
868 }
869
870 static int AptLua_pkgid(lua_State *L)
871 {
872    pkgCache::Package *Pkg = AptAux_ToPackage(L, 1);
873    if (Pkg == NULL)
874       return 0;
875    lua_pushnumber(L, Pkg->ID);
876    return 1;
877 }
878
879 static int AptLua_pkgsummary(lua_State *L)
880 {
881    SPtr<pkgCache::PkgIterator> PkgI = AptAux_ToPkgIterator(L, 1);
882    if (PkgI == NULL)
883       return 0;
884    if ((*PkgI)->VersionList == 0) {
885       lua_pushstring(L, "");
886    } else {
887       pkgCache *Cache = _lua->GetCache(L);
888       if (Cache == NULL)
889          return 0;
890       pkgRecords Recs(*Cache);
891       pkgRecords::Parser &Parse = 
892                               Recs.Lookup(PkgI->VersionList().FileList());
893       lua_pushstring(L, Parse.ShortDesc().c_str());
894    }
895    return 1;
896 }
897
898 static int AptLua_pkgdescr(lua_State *L)
899 {
900    SPtr<pkgCache::PkgIterator> PkgI = AptAux_ToPkgIterator(L, 1);
901    if (PkgI == NULL)
902       return 0;
903    if ((*PkgI)->VersionList == 0) {
904       lua_pushstring(L, "");
905    } else {
906       pkgCache *Cache = _lua->GetCache(L);
907       if (Cache == NULL)
908          return 0;
909       pkgRecords Recs(*Cache);
910       pkgRecords::Parser &Parse = Recs.Lookup(PkgI->VersionList().FileList());
911       lua_pushstring(L, Parse.LongDesc().c_str());
912    }
913    return 1;
914 }
915
916 static int AptLua_pkgisvirtual(lua_State *L)
917 {
918    pkgCache::Package *Pkg = AptAux_ToPackage(L, 1);
919    if (Pkg == NULL)
920       return 0;
921    if (Pkg->VersionList == 0)
922       lua_pushnumber(L, 1);
923    else
924       lua_pushnil(L);
925    return 1;
926 }
927
928 static int AptLua_pkgvercur(lua_State *L)
929 {
930    SPtr<pkgCache::PkgIterator> PkgI = AptAux_ToPkgIterator(L, 1);
931    if (PkgI == NULL)
932       return 0;
933    int Ret = AptAux_PushVersion(L, (*PkgI)->CurrentVer);
934    return Ret;
935 }
936
937 static int AptLua_pkgverinst(lua_State *L)
938 {
939    pkgDepCache *DepCache = _lua->GetDepCache(L);
940    if (DepCache == NULL)
941       return 0;
942    SPtr<pkgCache::PkgIterator> PkgI = AptAux_ToPkgIterator(L, 1);
943    if (PkgI == NULL)
944       return 0;
945    pkgCache::Version *InstVer = (*DepCache)[(*PkgI)].InstallVer;
946    pkgCache::Version *CurVer = (*PkgI).CurrentVer();
947    if (InstVer == CurVer)
948       InstVer = NULL;
949    return AptAux_PushVersion(L, InstVer);
950 }
951
952 static int AptLua_pkgvercand(lua_State *L)
953 {
954    pkgDepCache *DepCache = _lua->GetDepCache(L);
955    if (DepCache == NULL)
956       return 0;
957    SPtr<pkgCache::PkgIterator> PkgI = AptAux_ToPkgIterator(L, 1);
958    if (PkgI == NULL)
959       return 0;
960    pkgCache::Version *CandVer = (*DepCache)[(*PkgI)].CandidateVer;
961    pkgCache::Version *CurVer = (*PkgI).CurrentVer();
962    if (CandVer == CurVer)
963       CandVer = NULL;
964    return AptAux_PushVersion(L, CandVer);
965 }
966
967 static int AptLua_pkgverlist(lua_State *L)
968 {
969    SPtr<pkgCache::PkgIterator> PkgI = AptAux_ToPkgIterator(L, 1);
970    if (PkgI == NULL)
971       return 0;
972    lua_newtable(L);
973    int i = 1;
974    for (pkgCache::VerIterator Ver = (*PkgI).VersionList();
975         Ver.end() == false; Ver++) {
976       pushudata(pkgCache::Version*, Ver);
977       lua_rawseti(L, -2, i++);
978    }
979    return 1;
980 }
981
982 static int AptLua_verpkg(lua_State *L)
983 {
984    pkgCache::VerIterator *VerI = AptAux_ToVerIterator(L, 1);
985    if (VerI == NULL)
986       return 0;
987    pushudata(pkgCache::Package*, VerI->ParentPkg());
988    return 1;
989 }
990
991 static int AptLua_verstr(lua_State *L)
992 {
993    pkgCache::Version *Ver = AptAux_ToVersion(L, 1);
994    if (Ver == NULL)
995       return 0;
996    return AptAux_PushCacheString(L, Ver->VerStr);
997 }
998
999 static int AptLua_verarch(lua_State *L)
1000 {
1001    pkgCache::Version *Ver = AptAux_ToVersion(L, 1);
1002    if (Ver == NULL)
1003       return 0;
1004    return AptAux_PushCacheString(L, Ver->Arch);
1005    
1006 }
1007
1008 static int AptLua_verid(lua_State *L)
1009 {
1010    pkgCache::Version *Ver = AptAux_ToVersion(L, 1);
1011    if (Ver == NULL)
1012       return 0;
1013    lua_pushnumber(L, Ver->ID);
1014    return 1;
1015    
1016 }
1017
1018 static int AptLua_verisonline(lua_State *L)
1019 {
1020    pkgCache::VerIterator *VerI = AptAux_ToVerIterator(L, 1);
1021    if (VerI == NULL)
1022       return 0;
1023    return AptAux_PushBool(L, VerI->Downloadable());
1024 }
1025
1026 static int AptLua_verprovlist(lua_State *L)
1027 {
1028    pkgCache::VerIterator *VerI = AptAux_ToVerIterator(L, 1);
1029    if (VerI == NULL)
1030       return 0;
1031    pkgCache::PrvIterator PrvI = VerI->ProvidesList();
1032    lua_newtable(L);
1033    int i = 1;
1034    for (; PrvI.end() == false; PrvI++) {
1035       lua_newtable(L);
1036       lua_pushstring(L, "pkg");
1037       pushudata(pkgCache::Package*, PrvI.ParentPkg());
1038       lua_settable(L, -3);
1039       lua_pushstring(L, "name");
1040       lua_pushstring(L, PrvI.Name());
1041       lua_settable(L, -3);
1042 #ifndef DEAD
1043       lua_pushstring(L, "version");
1044       if (PrvI.ProvideVersion())
1045          lua_pushstring(L, PrvI.ProvideVersion());
1046       else
1047          lua_pushstring(L, "");
1048       lua_settable(L, -3);
1049 #endif
1050       lua_pushstring(L, "verstr");
1051       if (PrvI.ProvideVersion())
1052          lua_pushstring(L, PrvI.ProvideVersion());
1053       else
1054          lua_pushstring(L, "");
1055       lua_settable(L, -3);
1056       lua_rawseti(L, -2, i++);
1057    }
1058    return 1;
1059 }
1060
1061 static int AptLua_verdeplist(lua_State *L)
1062 {
1063    const char *TypeStr[] = {
1064       "", "depends", "predepends", "suggests", "recommends",
1065       "conflicts", "replaces", "obsoletes"
1066    };
1067    pkgCache::VerIterator *VerI = AptAux_ToVerIterator(L, 1);
1068    if (VerI == NULL)
1069       return 0;
1070    pkgCache::DepIterator DepI = VerI->DependsList();
1071    lua_newtable(L);
1072    int i = 1;
1073    for (; DepI.end() == false; DepI++) {
1074       lua_newtable(L);
1075       lua_pushstring(L, "pkg");
1076       pushudata(pkgCache::Package*, DepI.TargetPkg());
1077       lua_settable(L, -3);
1078       lua_pushstring(L, "name");
1079       lua_pushstring(L, DepI.TargetPkg().Name());
1080       lua_settable(L, -3);
1081       lua_pushstring(L, "verstr");
1082       if (DepI.TargetVer())
1083          lua_pushstring(L, DepI.TargetVer());
1084       else
1085          lua_pushstring(L, "");
1086       lua_settable(L, -3);
1087       lua_pushstring(L, "operator");
1088       lua_pushstring(L, DepI.CompType());
1089       lua_settable(L, -3);
1090       lua_pushstring(L, "type");
1091       lua_pushstring(L, TypeStr[DepI->Type]);
1092       lua_settable(L, -3);
1093       lua_pushstring(L, "verlist");
1094       lua_newtable(L);
1095       pkgCache::Version **VerList = DepI.AllTargets();
1096       for (int j = 0; VerList[j]; j++) {
1097          pushudata(pkgCache::Version*, VerList[j]);
1098          lua_rawseti(L, -2, j+1);
1099       }
1100       delete[] VerList;
1101       lua_settable(L, -3);
1102       lua_rawseti(L, -2, i++);
1103    }
1104    return 1;
1105 }
1106
1107 static int AptLua_verstrcmp(lua_State *L)
1108 {
1109    const char *Ver1, *Ver2;
1110    const char *Arch1, *Arch2;
1111    int Top = lua_gettop(L);
1112    int Ret = -9999;
1113    bool Error = false;
1114    if (Top == 2) {
1115       Ver1 = luaL_checkstring(L, 1);
1116       Ver2 = luaL_checkstring(L, 2);
1117       if (Ver1 == NULL || Ver2 == NULL)
1118          Error = true;
1119       else
1120          Ret = _system->VS->CmpVersion(Ver1, Ver2);
1121    } else if (Top == 4) {
1122       Ver1 = luaL_checkstring(L, 1);
1123       Arch1 = luaL_checkstring(L, 2);
1124       Ver2 = luaL_checkstring(L, 3);
1125       Arch2 = luaL_checkstring(L, 4);
1126       if (Ver1 == NULL || Arch1 == NULL || Ver2 == NULL || Arch2 == NULL)
1127          Error = true;
1128       else
1129          Ret = _system->VS->CmpVersionArch(Ver1, Arch1, Ver2, Arch2);
1130    } else {
1131       Error = true;
1132    }
1133    if (Error == true) {
1134       lua_pushstring(L, "verstrcmp requires 2 or 4 string arguments");
1135       lua_error(L);
1136       return 0;
1137    } else {
1138       lua_pushnumber(L, Ret);
1139       return 1;
1140    }
1141 }
1142
1143 static int AptLua_markkeep(lua_State *L)
1144 {
1145    return AptAux_mark(L, MARK_KEEP);
1146 }
1147
1148 static int AptLua_markinstall(lua_State *L)
1149 {
1150    return AptAux_mark(L, MARK_INSTALL);
1151 }
1152
1153 static int AptLua_markreinstall(lua_State *L)
1154 {
1155    _config->Set("Apt::Get::ReInstall", true);
1156    return AptAux_mark(L, MARK_REINSTALL);
1157 }
1158
1159 static int AptLua_markremove(lua_State *L)
1160 {
1161    return AptAux_mark(L, MARK_REMOVE);
1162 }
1163
1164 static int AptLua_marksimplekeep(lua_State *L)
1165 {
1166    return AptAux_marksimple(L, MARK_KEEP);
1167 }
1168
1169 static int AptLua_marksimpleinstall(lua_State *L)
1170 {
1171    return AptAux_marksimple(L, MARK_INSTALL);
1172 }
1173
1174 static int AptLua_marksimpleremove(lua_State *L)
1175 {
1176    return AptAux_marksimple(L, MARK_REMOVE);
1177 }
1178
1179 static int AptLua_markdistupgrade(lua_State *L)
1180 {
1181    if (lua_gettop(L) != 0) {
1182       lua_pushstring(L, "markdistupgrade has no arguments");
1183       lua_error(L);
1184       return 0;
1185    }
1186    pkgDepCache *DepCache = _lua->GetDepCache(L);
1187    if (DepCache != NULL)
1188       pkgDistUpgrade(*DepCache);
1189    return 0;
1190 }
1191
1192 static int AptLua_markupgrade(lua_State *L)
1193 {
1194    if (lua_gettop(L) != 0) {
1195       lua_pushstring(L, "markdistupgrade has no arguments");
1196       lua_error(L);
1197       return 0;
1198    }
1199    pkgDepCache *DepCache = _lua->GetDepCache(L);
1200    if (DepCache != NULL)
1201       pkgAllUpgrade(*DepCache);
1202    return 0;
1203 }
1204
1205 static int AptLua_statkeep(lua_State *L)
1206 {
1207    pkgDepCache *DepCache = _lua->GetDepCache(L);
1208    if (DepCache == NULL)
1209       return 0;
1210    SPtr<pkgCache::PkgIterator> PkgI = AptAux_ToPkgIterator(L, 1);
1211    if (PkgI == NULL)
1212       return 0;
1213    return AptAux_PushBool(L,
1214                 (*DepCache)[*PkgI].Keep() &&
1215                 !((*DepCache)[*PkgI].iFlags & pkgDepCache::ReInstall));
1216 }
1217
1218 static int AptLua_statinstall(lua_State *L)
1219 {
1220    pkgDepCache *DepCache = _lua->GetDepCache(L);
1221    if (DepCache == NULL)
1222       return 0;
1223    SPtr<pkgCache::PkgIterator> PkgI = AptAux_ToPkgIterator(L, 1);
1224    if (PkgI == NULL)
1225       return 0;
1226    return AptAux_PushBool(L, (*DepCache)[*PkgI].Install());
1227 }
1228
1229 static int AptLua_statremove(lua_State *L)
1230 {
1231    pkgDepCache *DepCache = _lua->GetDepCache(L);
1232    if (DepCache == NULL)
1233       return 0;
1234    SPtr<pkgCache::PkgIterator> PkgI = AptAux_ToPkgIterator(L, 1);
1235    if (PkgI == NULL)
1236       return 0;
1237    return AptAux_PushBool(L, (*DepCache)[*PkgI].Delete());
1238 }
1239
1240 static int AptLua_statnewinstall(lua_State *L)
1241 {
1242    pkgDepCache *DepCache = _lua->GetDepCache(L);
1243    if (DepCache == NULL)
1244       return 0;
1245    SPtr<pkgCache::PkgIterator> PkgI = AptAux_ToPkgIterator(L, 1);
1246    if (PkgI == NULL)
1247       return 0;
1248    return AptAux_PushBool(L, (*DepCache)[*PkgI].NewInstall());
1249 }
1250
1251 static int AptLua_statreinstall(lua_State *L)
1252 {
1253    pkgDepCache *DepCache = _lua->GetDepCache(L);
1254    if (DepCache == NULL)
1255       return 0;
1256    SPtr<pkgCache::PkgIterator> PkgI = AptAux_ToPkgIterator(L, 1);
1257    if (PkgI == NULL)
1258       return 0;
1259    return AptAux_PushBool(L,
1260                 (*DepCache)[*PkgI].Keep() &&
1261                 ((*DepCache)[*PkgI].iFlags & pkgDepCache::ReInstall));
1262 }
1263
1264 static int AptLua_statupgrade(lua_State *L)
1265 {
1266    pkgDepCache *DepCache = _lua->GetDepCache(L);
1267    if (DepCache == NULL)
1268       return 0;
1269    SPtr<pkgCache::PkgIterator> PkgI = AptAux_ToPkgIterator(L, 1);
1270    if (PkgI == NULL)
1271       return 0;
1272    return AptAux_PushBool(L, (*DepCache)[*PkgI].Upgrade());
1273 }
1274
1275 static int AptLua_statupgradable(lua_State *L)
1276 {
1277    pkgDepCache *DepCache = _lua->GetDepCache(L);
1278    if (DepCache == NULL)
1279       return 0;
1280    SPtr<pkgCache::PkgIterator> PkgI = AptAux_ToPkgIterator(L, 1);
1281    if (PkgI == NULL)
1282       return 0;
1283    return AptAux_PushBool(L, (*DepCache)[*PkgI].Upgradable());
1284 }
1285
1286 static int AptLua_statdowngrade(lua_State *L)
1287 {
1288    pkgDepCache *DepCache = _lua->GetDepCache(L);
1289    if (DepCache == NULL)
1290       return 0;
1291    SPtr<pkgCache::PkgIterator> PkgI = AptAux_ToPkgIterator(L, 1);
1292    if (PkgI == NULL)
1293       return 0;
1294    return AptAux_PushBool(L, (*DepCache)[*PkgI].Downgrade());
1295 }
1296
1297 static int AptLua_statnowbroken(lua_State *L)
1298 {
1299    pkgDepCache *DepCache = _lua->GetDepCache(L);
1300    if (DepCache == NULL)
1301       return 0;
1302    SPtr<pkgCache::PkgIterator> PkgI = AptAux_ToPkgIterator(L, 1);
1303    if (PkgI == NULL)
1304       return 0;
1305    return AptAux_PushBool(L, (*DepCache)[*PkgI].NowBroken());
1306 }
1307
1308 static int AptLua_statinstbroken(lua_State *L)
1309 {
1310    pkgDepCache *DepCache = _lua->GetDepCache(L);
1311    if (DepCache == NULL)
1312       return 0;
1313    SPtr<pkgCache::PkgIterator> PkgI = AptAux_ToPkgIterator(L, 1);
1314    if (PkgI == NULL)
1315       return 0;
1316    return AptAux_PushBool(L, (*DepCache)[*PkgI].InstBroken());
1317 }
1318
1319 static int AptLua_statstr(lua_State *L)
1320 {
1321    pkgDepCache *DepCache = _lua->GetDepCache(L);
1322    if (DepCache == NULL)
1323       return 0;
1324    SPtr<pkgCache::PkgIterator> PkgI = AptAux_ToPkgIterator(L, 1);
1325    if (PkgI == NULL)
1326       return 0;
1327    pkgDepCache::StateCache &S = (*DepCache)[*PkgI];
1328    if (S.NewInstall()) {
1329       if (S.InstBroken()) {
1330          lua_pushstring(L, "newinstall(broken)");
1331       } else {
1332          lua_pushstring(L, "newinstall");
1333       }
1334    } else if (S.Upgrade()) {
1335       if (S.InstBroken()) {
1336          lua_pushstring(L, "upgrade(broken)");
1337       } else {
1338          lua_pushstring(L, "upgrade");
1339       }
1340    } else if (S.Downgrade()) {
1341       if (S.InstBroken()) {
1342          lua_pushstring(L, "downgrade(broken)");
1343       } else {
1344          lua_pushstring(L, "downgrade");
1345       }
1346    } else if (S.Keep() && (S.iFlags & pkgDepCache::ReInstall)) {
1347       if (S.NowBroken()) {
1348          lua_pushstring(L, "reinstall(broken)");
1349       } else {
1350          lua_pushstring(L, "reinstall");
1351       }
1352    } else if (S.Keep()) {
1353       if (S.NowBroken()) {
1354          lua_pushstring(L, "keep(broken)");
1355       } else {
1356          lua_pushstring(L, "keep");
1357       }
1358    } else if (S.Delete()) {
1359       lua_pushstring(L, "remove");
1360    } else {
1361       lua_pushstring(L, "unknown state in statstr(), "
1362                         "report to the maintainer");
1363       lua_error(L);
1364       return 0;
1365    }
1366    return 1;
1367 }
1368
1369 static int AptLua_apterror(lua_State *L)
1370 {
1371    const char *str = luaL_checkstring(L, 1);
1372    if (str != NULL)
1373       _error->Error("%s", str);
1374    return 0;
1375 }
1376
1377 static int AptLua_aptwarning(lua_State *L)
1378 {
1379    const char *str = luaL_checkstring(L, 1);
1380    if (str != NULL)
1381       _error->Warning("%s", str);
1382    return 0;
1383 }
1384
1385 static int AptLua_gettext(lua_State *L)
1386 {
1387    const char *str = luaL_checkstring(L, 1);
1388    if (str != NULL) {
1389       lua_pushliteral(L, "TEXTDOMAIN");
1390       lua_rawget(L, LUA_GLOBALSINDEX);
1391       if (lua_isstring(L, -1))
1392          lua_pushstring(L, dgettext(lua_tostring(L, -1), str));
1393       else
1394          lua_pushstring(L, gettext(str));
1395       lua_remove(L, -2);
1396       return 1;
1397    }
1398    return 0;
1399 }
1400
1401 static const luaL_reg aptlib[] = {
1402    {"confget",          AptLua_confget},
1403    {"confgetlist",      AptLua_confgetlist},
1404    {"confset",          AptLua_confset},
1405    {"confexists",       AptLua_confexists},
1406    {"confclear",        AptLua_confclear},
1407    {"pkgfind",          AptLua_pkgfind},
1408    {"pkglist",          AptLua_pkglist},
1409    {"pkgname",          AptLua_pkgname},
1410    {"pkgid",            AptLua_pkgid},
1411    {"pkgsummary",       AptLua_pkgsummary},
1412    {"pkgdescr",         AptLua_pkgdescr},
1413    {"pkgisvirtual",     AptLua_pkgisvirtual},
1414    {"pkgvercur",        AptLua_pkgvercur},
1415    {"pkgverinst",       AptLua_pkgverinst},
1416    {"pkgvercand",       AptLua_pkgvercand},
1417    {"pkgverlist",       AptLua_pkgverlist},
1418    {"verpkg",           AptLua_verpkg},
1419    {"verstr",           AptLua_verstr},
1420    {"verarch",          AptLua_verarch},
1421    {"verid",            AptLua_verid},
1422    {"verisonline",      AptLua_verisonline},
1423    {"verprovlist",      AptLua_verprovlist},
1424    {"verdeplist",       AptLua_verdeplist},
1425    {"verstrcmp",        AptLua_verstrcmp},
1426    {"markkeep",         AptLua_markkeep},
1427    {"markinstall",      AptLua_markinstall},
1428    {"markreinstall",    AptLua_markreinstall},
1429    {"markremove",       AptLua_markremove},
1430    {"marksimplekeep",   AptLua_marksimpleinstall},
1431    {"marksimpleinstall",AptLua_marksimpleinstall},
1432    {"marksimpleremove", AptLua_marksimpleinstall},
1433    {"markdistupgrade",  AptLua_markdistupgrade},
1434    {"markupgrade",      AptLua_markupgrade},
1435    {"statkeep",         AptLua_statkeep},
1436    {"statinstall",      AptLua_statinstall},
1437    {"statremove",       AptLua_statremove},
1438    {"statnewinstall",   AptLua_statnewinstall},
1439    {"statreinstall",    AptLua_statreinstall},
1440    {"statupgrade",      AptLua_statupgrade},
1441    {"statupgradable",   AptLua_statupgradable},
1442    {"statdowngrade",    AptLua_statdowngrade},
1443    {"statnowbroken",    AptLua_statnowbroken},
1444    {"statinstbroken",   AptLua_statinstbroken},
1445    {"statstr",          AptLua_statstr},
1446    {"apterror",         AptLua_apterror},
1447    {"aptwarning",       AptLua_aptwarning},
1448    {"_",                AptLua_gettext},
1449    {NULL, NULL}
1450 };
1451
1452 static int AptLua_vercomp(lua_State *L)
1453 {
1454    pkgCache::Version *v1, *v2;
1455    checkudata(pkgCache::Version*, v1, 1);
1456    checkudata(pkgCache::Version*, v2, 2);
1457    lua_pushboolean(L, (!v1 || v1 != v2) ? 0 : 1);
1458    return 1;
1459 }
1460
1461 static int AptLua_pkgcomp(lua_State *L)
1462 {
1463    pkgCache::Package *p1, *p2;
1464    checkudata(pkgCache::Package*, p1, 1);
1465    checkudata(pkgCache::Package*, p2, 2);
1466    lua_pushboolean(L, (!p1 || p1 != p2) ? 0 : 1);
1467    return 1;
1468 }
1469
1470
1471 static int luaopen_apt(lua_State *L)
1472 {
1473    lua_pushvalue(L, LUA_GLOBALSINDEX);
1474    luaL_openlib(L, NULL, aptlib, 0);
1475    return 0;
1476 }
1477
1478 pkgDepCache *LuaCacheControl::Open()
1479 {
1480    if (geteuid() == 0)
1481       return Open(true);
1482    else
1483       return Open(false);
1484 }
1485
1486 #endif // WITH_LUA
1487
1488 // vim:sts=3:sw=3