[ SEA-GHOST MINI SHELL]
#!/usr/bin/python -t
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Library General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
# Copyright 2005 Duke University
"""
Progress display callback classes for the yum command line.
"""
import rpm
import os
import sys
import logging
from yum import _
from yum.constants import *
class RPMInstallCallback:
"""Yum command line callback class for callbacks from the RPM library."""
def __init__(self, output=1):
self.output = output
self.callbackfilehandles = {}
self.total_actions = 0
self.total_installed = 0
self.installed_pkg_names = []
self.total_removed = 0
self.mark = "#"
self.marks = 27
self.lastmsg = None
self.logger = logging.getLogger('yum.filelogging.RPMInstallCallback')
self.filelog = False
self.myprocess = { TS_UPDATE : _('Updating'),
TS_ERASE: _('Erasing'),
TS_INSTALL: _('Installing'),
TS_TRUEINSTALL : _('Installing'),
TS_OBSOLETED: _('Obsoleted'),
TS_OBSOLETING: _('Installing')}
self.mypostprocess = { TS_UPDATE: _('Updated'),
TS_ERASE: _('Erased'),
TS_INSTALL: _('Installed'),
TS_TRUEINSTALL: _('Installed'),
TS_OBSOLETED: _('Obsoleted'),
TS_OBSOLETING: _('Installed')}
self.tsInfo = None # this needs to be set for anything else to work
def _dopkgtup(self, hdr):
tmpepoch = hdr['epoch']
if tmpepoch is None: epoch = '0'
else: epoch = str(tmpepoch)
return (hdr['name'], hdr['arch'], epoch, hdr['version'], hdr['release'])
def _makeHandle(self, hdr):
handle = '%s:%s.%s-%s-%s' % (hdr['epoch'], hdr['name'], hdr['version'],
hdr['release'], hdr['arch'])
return handle
def _localprint(self, msg):
if self.output:
print msg
def _makefmt(self, percent, progress = True):
l = len(str(self.total_actions))
size = "%s.%s" % (l, l)
fmt_done = "[%" + size + "s/%" + size + "s]"
done = fmt_done % (self.total_installed + self.total_removed,
self.total_actions)
marks = self.marks - (2 * l)
width = "%s.%s" % (marks, marks)
fmt_bar = "%-" + width + "s"
if progress:
bar = fmt_bar % (self.mark * int(marks * (percent / 100.0)), )
fmt = "\r %-10.10s: %-28.28s " + bar + " " + done
else:
bar = fmt_bar % (self.mark * marks, )
fmt = " %-10.10s: %-28.28s " + bar + " " + done
return fmt
def _logPkgString(self, hdr):
"""return nice representation of the package for the log"""
(n,a,e,v,r) = self._dopkgtup(hdr)
if e == '0':
pkg = '%s.%s %s-%s' % (n, a, v, r)
else:
pkg = '%s.%s %s:%s-%s' % (n, a, e, v, r)
return pkg
def callback(self, what, bytes, total, h, user):
"""Handle callbacks from the RPM library.
:param what: number identifying the type of callback
:param bytes: the number of bytes associated with the
callback; the exact meaning depends on the type of
the callback. For example, for a RPMCALLBACK_INST_PROGRESS
callback, bytes will represent the current amount of work done
:param total: the total amount of work associated with the
callback; the exact meaning depends on the type of the
callback. For example, *total* may represent the total
number of transactions in a transaction set
:param h: a package object or string identifying the package
involved in the callback
:param user: unused
"""
if what == rpm.RPMCALLBACK_TRANS_START:
if bytes == 6:
self.total_actions = total
elif what == rpm.RPMCALLBACK_TRANS_PROGRESS:
pass
elif what == rpm.RPMCALLBACK_TRANS_STOP:
pass
elif what == rpm.RPMCALLBACK_INST_OPEN_FILE:
self.lastmsg = None
hdr = None
if h is not None:
hdr, rpmloc = h
handle = self._makeHandle(hdr)
fd = os.open(rpmloc, os.O_RDONLY)
self.callbackfilehandles[handle]=fd
self.total_installed += 1
self.installed_pkg_names.append(hdr['name'])
return fd
else:
self._localprint(_("No header - huh?"))
elif what == rpm.RPMCALLBACK_INST_CLOSE_FILE:
hdr = None
if h is not None:
hdr, rpmloc = h
handle = self._makeHandle(hdr)
os.close(self.callbackfilehandles[handle])
fd = 0
# log stuff
pkgtup = self._dopkgtup(hdr)
txmbrs = self.tsInfo.getMembers(pkgtup=pkgtup)
for txmbr in txmbrs:
try:
process = self.myprocess[txmbr.output_state]
processed = self.mypostprocess[txmbr.output_state]
except KeyError:
pass
if self.filelog:
pkgrep = self._logPkgString(hdr)
msg = '%s: %s' % (processed, pkgrep)
self.logger.info(msg)
elif what == rpm.RPMCALLBACK_INST_PROGRESS:
if h is not None:
# If h is a string, we're repackaging.
# Why the RPMCALLBACK_REPACKAGE_PROGRESS flag isn't set, I have no idea
if type(h) == type(""):
if total == 0:
percent = 0
else:
percent = (bytes*100L)/total
if self.output and sys.stdout.isatty():
fmt = self._makefmt(percent)
msg = fmt % (_('Repackage'), h)
if bytes == total:
msg = msg + "\n"
if msg != self.lastmsg:
sys.stdout.write(msg)
sys.stdout.flush()
self.lastmsg = msg
else:
hdr, rpmloc = h
if total == 0:
percent = 0
else:
percent = (bytes*100L)/total
pkgtup = self._dopkgtup(hdr)
txmbrs = self.tsInfo.getMembers(pkgtup=pkgtup)
for txmbr in txmbrs:
try:
process = self.myprocess[txmbr.output_state]
except KeyError, e:
print _("Error: invalid output state: %s for %s") % \
(txmbr.output_state, hdr['name'])
else:
if self.output and (sys.stdout.isatty() or bytes == total):
fmt = self._makefmt(percent)
msg = fmt % (process, hdr['name'])
if msg != self.lastmsg:
sys.stdout.write(msg)
sys.stdout.flush()
self.lastmsg = msg
if bytes == total:
print " "
elif what == rpm.RPMCALLBACK_UNINST_START:
pass
elif what == rpm.RPMCALLBACK_UNINST_PROGRESS:
pass
elif what == rpm.RPMCALLBACK_UNINST_STOP:
self.total_removed += 1
if self.filelog and h not in self.installed_pkg_names:
logmsg = _('Erased: %s' % (h))
self.logger.info(logmsg)
if self.output and sys.stdout.isatty():
if h not in self.installed_pkg_names:
process = _("Removing")
else:
process = _("Cleanup")
percent = 100
fmt = self._makefmt(percent, False)
msg = fmt % (process, h)
sys.stdout.write(msg + "\n")
sys.stdout.flush()
elif what == rpm.RPMCALLBACK_REPACKAGE_START:
pass
elif what == rpm.RPMCALLBACK_REPACKAGE_STOP:
pass
elif what == rpm.RPMCALLBACK_REPACKAGE_PROGRESS:
pass
SEA-GHOST - SHELL CODING BY SEA-GHOST