lsb: Willingness to help for the Ubuntu merge

"Didier 'OdyX' Raboud" <[email protected]>
Newsgroups gmane.linux.debian.devel.lsb
Organization Debian, the Universal OS
Message-ID <[email protected]>
Hi Colin, hi Matthias,

now that the Ubuntu Pangolin was released (congrats!), from what I
understand from the Ubuntu release process, it will very soon be the
"big merge" time. And the src:lsb package has diverged quite a lot
between the Debian and Ubuntu counterparts.

Now, while I tried my best to merge the past and actual changes from
Ubuntu, there is certainly a diff that needs manual merging (hence
discussion). Furthermore, I don't think Ubuntu and Debian really need
different src:lsb packages (especially when we can play with dpkg-vendor
snippets where needed).

So I am willing to put work where needed towards the goal of sharing a
single Debian source package. Where do you want to start from?

(By the way, one major hurdle is probably the default python version for
lsb-release. The attached patch is an attempt at making the python
scripts work with both python2.6 and python3 without further change.
Comments welcome.)

Cheers,

OdyX
lsb_4.1+Debian2_py2to3.patch (text/x-diff, 22.8 KB)
diff --git a/initdutils.py b/initdutils.py
index 3b5bb10..e911dfa 100644
--- a/initdutils.py
+++ b/initdutils.py
@@ -1,13 +1,10 @@
 # Support for scanning init scripts for LSB info
 
-import re, sys, os, cStringIO
-import cPickle
+# Python3-compatible print() function
+from __future__ import print_function
 
-try:
-    assert True
-except:
-    True = 1
-    False = 0
+import re, sys, os, io
+import pickle
 
 class RFC822Parser(dict):
     "A dictionary-like object."
@@ -15,14 +12,14 @@ class RFC822Parser(dict):
     
     def __init__(self, fileob=None, strob=None, startcol=0, basedict=None):
         if not fileob and not strob:
-            raise ValueError, 'need a file or string'
+            raise ValueError('need a file or string')
         if not basedict:
             basedict = {}
         
         super(RFC822Parser, self).__init__(basedict)
 
         if not fileob:
-            fileob = cStringIO.StringIO(strob)
+            fileob = io.StringIO(strob)
 
         key = None
         for line in fileob:
@@ -79,13 +76,13 @@ def scan_initfile(initfile):
 
     inheaders = RFC822Parser(strob=headerlines)
     headers = {}
-    for header, body in inheaders.iteritems():
+    for header, body in list(inheaders.items()):
         # Ignore empty headers
         if not body.strip():
             continue
         
         if header in ('Default-Start', 'Default-Stop'):
-            headers[header] = map(int, body.split())
+            headers[header] = list(map(int, body.split()))
         elif header in ('Required-Start', 'Required-Stop', 'Provides',
                         'Should-Start', 'Should-Stop'):
             headers[header] = body.split()
@@ -103,24 +100,24 @@ def save_facilities(facilities):
         return
     
     fh = file(FACILITIES, 'w')
-    for facility, entries in facilities.items():
+    for facility, entries in list(facilities.items()):
         # Ignore system facilities
         if facility.startswith('$'): continue
-        for (scriptname, pri) in entries.items():
+        for (scriptname, pri) in list(entries.items()):
             start, stop = pri
-            print >> fh, "%(scriptname)s %(facility)s %(start)d %(stop)d" % locals()
+            print("%(scriptname)s %(facility)s %(start)d %(stop)d" % locals(), file=fh)
     fh.close()
 
 def load_facilities():
     facilities = {}
     if os.path.exists(FACILITIES):
-        for line in open(FACILITIES).xreadlines():
+        for line in open(FACILITIES):
             try:
                 scriptname, name, start, stop = line.strip().split()
                 facilities.setdefault(name, {})[scriptname] = (int(start),
                                                                int(stop))
-            except ValueError, x:
-                print >> sys.stderr, 'Invalid facility line', line
+            except ValueError as x:
+                print('Invalid facility line', line, file=sys.stderr)
 
     return facilities
 
@@ -129,7 +126,7 @@ def load_depends():
 
     if os.path.exists(DEPENDS):
         independs = RFC822Parser(fileob=file(DEPENDS))
-        for initfile, facilities in independs.iteritems():
+        for initfile, facilities in list(independs.items()):
             depends[initfile] = facilities.split()
     return depends
 
@@ -142,8 +139,8 @@ def save_depends(depends):
         return
     
     fh = file(DEPENDS, 'w')
-    for initfile, facilities in depends.iteritems():
-        print >> fh, '%s: %s' % (initfile, ' '.join(facilities))
+    for initfile, facilities in list(depends.items()):
+        print('%s: %s' % (initfile, ' '.join(facilities)), file=fh)
     fh.close()
 
 # filemap entries are mappings, { (package, filename) : instloc }
@@ -152,7 +149,7 @@ def load_lsbinstall_info():
         return {}
     
     fh = open(LSBINSTALL, 'rb')
-    filemap = cPickle.load(fh)
+    filemap = pickle.load(fh)
     fh.close()
 
     # Just in case it's corrupted somehow
@@ -170,8 +167,8 @@ def save_lsbinstall_info(filemap):
         return
     
     fh = open(LSBINSTALL, 'wb')
-    cPickle.dump(fh, filemap)
+    pickle.dump(fh, filemap)
     fh.close()
 
 if __name__ == '__main__':
-    print scan_initfile('init-fragment')
+    print(scan_initfile('init-fragment'))
diff --git a/install_initd b/install_initd
index 4ec8452..3f3e86e 100755
--- a/install_initd
+++ b/install_initd
@@ -1,5 +1,8 @@
 #!/usr/bin/python
 
+# Python3-compatible print() function
+from __future__ import print_function
+
 import sys, re, os, initdutils
 
 if len(sys.argv) > 1:
@@ -12,7 +15,7 @@ if len(sys.argv) > 1:
     else:
         initfile = os.path.join('/etc/init.d', initfile)
 else:
-    print >> sys.stderr, 'Usage: %s /etc/init.d/<init-script>' % sys.argv[0]
+    print('Usage: %s /etc/init.d/<init-script>' % sys.argv[0], file=sys.stderr)
     sys.exit(1)
 
 # Default priorities
@@ -22,19 +25,19 @@ defstop = [0, 1, 6]
 
 # Estimated priorities of these facilities in Debian
 os_facilities = {
-    "$local_fs" : {'lsb' : (0, 100)},
-    "$network" : {'lsb' : (10, 50)},
-    "$remote_fs" : {'lsb': (19, 20)},
-    "$named" : {'lsb': (19, 19)},
-    "$syslog" : {'lsb' : (10, 89)},
+    "$local_fs": {'lsb' : (0, 100)},
+    "$network": {'lsb' : (10, 50)},
+    "$remote_fs": {'lsb': (19, 20)},
+    "$named": {'lsb': (19, 19)},
+    "$syslog": {'lsb' : (10, 89)},
     # No longer present in gLSB 1.2; however, required for gLSB 1.1
     # compat.  Note that these are looser than $portmap and $time;
     # anything specifying $netdaemons will be run later, which may not
     # be what you want...
-    "$netdaemons" : {'lsb': (80, 19)},
+    "$netdaemons": {'lsb': (80, 19)},
     # gLSB 1.2
-    "$portmap" : {'lsb' : (19, 34)},
-    "$time" : {'lsb' : (24, 21)},
+    "$portmap": {'lsb' : (19, 34)},
+    "$time": {'lsb' : (24, 21)},
     }
 
 facilities = initdutils.load_facilities()
@@ -51,10 +54,10 @@ if reqstart or shouldstart:
     startpri = 5
     for facility in reqstart:
         if facility not in facilities:
-            print >> sys.stderr, 'Missing required start facility', facility
+            print('Missing required start facility', facility, file=sys.stderr)
             sys.exit(1)
         else:
-            for script, pri in facilities[facility].iteritems():
+            for script, pri in list(facilities[facility].items()):
                 if script != initfile:
                     start, stop = pri
                     startpri = max(startpri, start+1)
@@ -63,9 +66,9 @@ if reqstart or shouldstart:
     
     for facility in shouldstart:
         if facility not in facilities:
-            print >> sys.stderr, 'Missing should-start facility', facility, '(ignored)'
+            print('Missing should-start facility', facility, '(ignored)', file=sys.stderr)
         else:
-            for script, pri in facilities[facility].iteritems():
+            for script, pri in list(facilities[facility].items()):
                 if script != initfile:
                     start, stop = pri
                     startpri = max(startpri, start+1)
@@ -77,10 +80,10 @@ if reqstop or shouldstop:
     stoppri = 95
     for facility in reqstop:
         if facility not in facilities:
-            print >> sys.stderr, 'Missing required stop facility', facility
+            print('Missing required stop facility', facility, file=sys.stderr)
             sys.exit(1)
         else:
-            for script, pri in facilities[facility].iteritems():
+            for script, pri in list(facilities[facility].items()):
                 if script != initfile:
                     start, stop = pri
                     stoppri = min(stoppri, stop-1)
@@ -89,9 +92,9 @@ if reqstop or shouldstop:
 
     for facility in shouldstop:
         if facility not in facilities:
-            print >> sys.stderr, 'Missing should-stop facility', facility, '(ignored)'
+            print('Missing should-stop facility', facility, '(ignored)', file=sys.stderr)
         else:
-            for script, pri in facilities[facility].iteritems():
+            for script, pri in list(facilities[facility].items()):
                 if script != initfile:
                     start, stop = pri
                     stoppri = min(stoppri, stop-1)
@@ -105,9 +108,9 @@ provides = headers.get('Provides', [])
 if provides:
     for facility in provides:
         if facility[0] == '$':
-            print >> sys.stderr, 'Ignoring system-provided facility', facility
+            print('Ignoring system-provided facility', facility, file=sys.stderr)
             continue
-        if not facilities.has_key(facility):
+        if facility not in facilities:
             facilities[facility] = {}
 
         facilities[facility][initfile] = (startpri, stoppri)
@@ -117,13 +120,13 @@ defstart = headers.get('Default-Start', defstart)
 defstop = headers.get('Default-Stop', defstop)
 
 # A set type would be nice... [range(2,6) = 2..5]
-for level in range(2,6):
+for level in range(2, 6):
     if level in defstart:
-        for i in range(2,6):
+        for i in range(2, 6):
             if i not in defstart:
                 defstart.append(i)
     if level in defstop:
-        for i in range(2,6):
+        for i in range(2, 6):
             if i not in defstop:
                 defstop.append(i)
 
diff --git a/lsb_release b/lsb_release
index f8e8a53..abb201f 100755
--- a/lsb_release
+++ b/lsb_release
@@ -17,9 +17,11 @@
 #    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 #    02110-1301 USA
 
+# Python3-compatible print() function
+from __future__ import print_function
+
 from optparse import OptionParser
 import sys
-import commands
 import os
 import re
 
@@ -62,35 +64,35 @@ def main():
     if none or options.all or options.version:
         verinfo = lsb_release.check_modules_installed()
         if not verinfo:
-            print >> sys.stderr, "No LSB modules are available."
+            print("No LSB modules are available.", file=sys.stderr)
         elif short:
-            print ':'.join(verinfo)
+            print(':'.join(verinfo))
         else:
-            print 'LSB Version:\t' + ':'.join(verinfo)
+            print('LSB Version:\t' + ':'.join(verinfo))
 
     if options.id or options.all:
         if short:
-            print distinfo.get('ID', 'n/a')
+            print(distinfo.get('ID', 'n/a'))
         else:
-            print 'Distributor ID:\t%s' % distinfo.get('ID', 'n/a')
+            print('Distributor ID:\t%s' % distinfo.get('ID', 'n/a'))
 
     if options.description or options.all:
         if short:
-            print distinfo.get('DESCRIPTION', 'n/a')
+            print(distinfo.get('DESCRIPTION', 'n/a'))
         else:
-            print 'Description:\t%s' % distinfo.get('DESCRIPTION', 'n/a')
+            print('Description:\t%s' % distinfo.get('DESCRIPTION', 'n/a'))
 
     if options.release or options.all:
         if short:
-            print distinfo.get('RELEASE', 'n/a')
+            print(distinfo.get('RELEASE', 'n/a'))
         else:
-            print 'Release:\t%s' % distinfo.get('RELEASE', 'n/a')
+            print('Release:\t%s' % distinfo.get('RELEASE', 'n/a'))
 
     if options.codename or options.all:
         if short:
-            print distinfo.get('CODENAME', 'n/a')
+            print(distinfo.get('CODENAME', 'n/a'))
         else:
-            print 'Codename:\t%s' % distinfo.get('CODENAME', 'n/a')
+            print('Codename:\t%s' % distinfo.get('CODENAME', 'n/a'))
 
 if __name__ == '__main__':
     main()
diff --git a/lsb_release.py b/lsb_release.py
index 2727d13..33c189c 100644
--- a/lsb_release.py
+++ b/lsb_release.py
@@ -17,8 +17,11 @@
 #    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 #    02110-1301 USA
 
+# Python3-compatible print() function
+from __future__ import print_function
+
 import sys
-import commands
+import subprocess
 import os
 import re
 
@@ -42,9 +45,9 @@ RELEASE_CODENAME_LOOKUP = {
 
 TESTING_CODENAME = 'unknown.new.testing'
 
-RELEASES_ORDER = RELEASE_CODENAME_LOOKUP.items()
+RELEASES_ORDER = list(RELEASE_CODENAME_LOOKUP.items())
 RELEASES_ORDER.sort()
-RELEASES_ORDER = list(zip(*RELEASES_ORDER)[1])
+RELEASES_ORDER = list(list(zip(*RELEASES_ORDER))[1])
 RELEASES_ORDER.extend(['stable', 'testing', 'unstable', 'sid'])
 
 def lookup_codename(release, unknown=None):
@@ -120,7 +123,11 @@ except NameError:
 # This is Debian-specific at present
 def check_modules_installed():
     # Find which LSB modules are installed on this system
-    output = commands.getoutput("dpkg-query -f '${Version} ${Provides}\n' -W %s 2>/dev/null" % PACKAGES)
+    output = subprocess.Popen(['dpkg-query','-f',"'${Version} ${Provides}\n'",'-W',PACKAGES],
+                              env={'LANG': 'C'},
+                              stdout=subprocess.PIPE,
+                              stderr=subprocess.PIPE,
+                              close_fds=True).communicate()[0].decode('ascii')
     if not output:
         return []
 
@@ -164,22 +171,21 @@ def parse_policy_line(data):
                 retval[longnames[k]] = v
     return retval
 
-def compare_release(x, y):
+def release_index(x):
     suite_x = x[1].get('suite')
-    suite_y = y[1].get('suite')
 
-    if suite_x and suite_y:
-        if suite_x in RELEASES_ORDER and suite_y in RELEASES_ORDER:
-            return RELEASES_ORDER.index(suite_y)-RELEASES_ORDER.index(suite_x)
-        else:
-            return cmp(suite_x, suite_y)
+    if suite_x in RELEASES_ORDER:
+        return RELEASES_ORDER.index(suite_x)
 
     return 0
 
 def parse_apt_policy():
     data = []
     
-    policy = commands.getoutput('LANG=C apt-cache policy 2>/dev/null')
+    policy = subprocess.Popen(['apt-cache','policy'],
+                              env={'LANG': 'C'},
+                              stdout=subprocess.PIPE,
+                              close_fds=True).communicate()[0].decode('ascii')
     for line in policy.split('\n'):
         line = line.strip()
         m = re.match(r'(-?\d+)', line)
@@ -213,15 +219,14 @@ def guess_release_from_apt(origin='Debian', component='main',
     if not releases:
         return None
     
-    releases.sort()
-    releases.reverse()
+    releases.sort(key=lambda tuple: tuple[0],reverse=True)
 
     # We've sorted the list by descending priority, so the first entry should
     # be the "main" release in use on the system
 
     max_priority = releases[0][0]
     releases = [x for x in releases if x[0] == max_priority]
-    releases.sort(compare_release)
+    releases.sort(key=release_index)
 
     return releases[0][1]
 
@@ -244,8 +249,8 @@ def guess_debian_release():
         try:
             with open('/etc/debian_version') as debian_version:
                 release = debian_version.read().strip()
-        except IOError, msg:
-            print >> sys.stderr, 'Unable to open /etc/debian_version:', str(msg)
+        except IOError as msg:
+            print('Unable to open /etc/debian_version:', str(msg), file=sys.stderr)
             release = 'unknown'
             
         if not release[0:1].isalpha():
@@ -315,8 +320,8 @@ def get_lsb_information():
                             arg = arg[1:-1]
                         if arg: # Ignore empty arguments
                             distinfo[var] = arg.strip()
-        except IOError, msg:
-            print >> sys.stderr, 'Unable to open /etc/lsb-release:', str(msg)
+        except IOError as msg:
+            print('Unable to open /etc/lsb-release:', str(msg), file=sys.stderr)
             
     return distinfo
 
@@ -332,8 +337,8 @@ def get_distro_information():
         return lsbinfo
 
 def test():
-    print get_distro_information()
-    print check_modules_installed()
+    print(get_distro_information())
+    print(check_modules_installed())
 
 if __name__ == '__main__':
     test()
diff --git a/lsbinstall b/lsbinstall
index f007517..30ad303 100755
--- a/lsbinstall
+++ b/lsbinstall
@@ -1,10 +1,13 @@
 #!/usr/bin/python
 
+# Python3-compatible print() function
+from __future__ import print_function
+
 import sys
 import os
 import shutil
 import socket
-import commands
+import subprocess
 from tempfile import NamedTemporaryFile
 from initdutils import load_lsbinstall_info, save_lsbinstall_info
 
@@ -19,7 +22,7 @@ objecttypes = (
     )
 
 def installed_message(objectname):
-    print objectname, 'is installed'
+    print(objectname, 'is installed')
 
 def handle_generic_install(options, args, location, showinstloc=False):
     filename = args[0]
@@ -40,9 +43,9 @@ def handle_generic_install(options, args, location, showinstloc=False):
         if os.path.exists(fileinfo):
             try:
                 os.unlink(fileinfo)
-            except (IOError, OSError, os.error), why:
-                print >> sys.stderr, 'Removal of %s failed: %s' % (
-                    instloc, str(why))
+            except (IOError, OSError, os.error) as why:
+                print('Removal of %s failed: %s' % (
+                    instloc, str(why)), file=sys.stderr)
                 sys.exit(1)
 
         # Remove it from the database, even if it was previously removed
@@ -54,27 +57,27 @@ def handle_generic_install(options, args, location, showinstloc=False):
         instloc = os.path.join(location, '%s.%s' % (options.package, basename))
 
     if os.path.exists(instloc):
-        print >> sys.stderr, 'Unable to install %s: %s exists' % (
-            filename, instloc)
+        print('Unable to install %s: %s exists' % (
+            filename, instloc), file=sys.stderr)
         sys.exit(1)
 
     if not os.path.exists(location):
         try:
             os.makedirs(location)
-        except (IOError, OSError, os.error), why:
-            print >> sys.stderr, 'Unable to create %s to install %s: %s' % (
-                location, filename, str(why))
+        except (IOError, OSError, os.error) as why:
+            print('Unable to create %s to install %s: %s' % (
+                location, filename, str(why)), file=sys.stderr)
             sys.exit(1)
         
     try:
         shutil.copy2(filename, instloc)
-    except (IOError, os.error), why:
-        print >> sys.stderr, 'Installation of %s as %s failed: %s' % (
-            filename, instloc, str(why))
+    except (IOError, os.error) as why:
+        print('Installation of %s as %s failed: %s' % (
+            filename, instloc, str(why)), file=sys.stderr)
         sys.exit(1)
         
     if showinstloc:
-        print instloc
+        print(instloc)
 
     filemap[(package, filename)] = instloc
     save_lsbinstall_info(filemap)
@@ -91,7 +94,7 @@ def handle_service(options, args):
         port, proto = pproto.split('/', 1)
         port = int(port)
     except:
-        print >> sys.stderr, 'You must specify a port/protocol pair as the first argument.'
+        print('You must specify a port/protocol pair as the first argument.', file=sys.stderr)
         sys.exit(2)
 
     if options.check:
@@ -100,7 +103,7 @@ def handle_service(options, args):
         except socket.error:
             sys.exit(1)
 
-        print '%d/%s corresponds to service %s' % (port, proto, serv)
+        print('%d/%s corresponds to service %s' % (port, proto, serv))
         return
 
     sname = args[1]
@@ -143,7 +146,7 @@ def handle_service(options, args):
                             laliases += [a]
                 elif name == lname or name in laliases:
                     # name shows up, but in wrong protocol/port
-                    print >> sys.stderr, 'Conflict between specified addition and /etc/services; aborting.'
+                    print('Conflict between specified addition and /etc/services; aborting.', file=sys.stderr)
                     fpout.close()
                     os.unlink(newfname)
                     sys.exit(1)
@@ -157,7 +160,7 @@ def handle_service(options, args):
                 line = '%15s %15s %s' % lname, lpproto, endbits
                 line = line.rstrip()
 
-            print >> fpout, line
+            print(line, file=fpout)
         
         fpin.close()
         fpout.close()
@@ -167,12 +170,12 @@ def handle_service(options, args):
         return
 
     fp = open('/etc/services', 'a')
-    print >> fp, '%15s %15s %s # Added by lsbinstall for %s' % (
-        sname, pproto, ' '.join(saliases), pkg)
+    print('%15s %15s %s # Added by lsbinstall for %s' % (
+        sname, pproto, ' '.join(saliases), pkg), file=fp)
     fp.close()
 
 def handle_inet(options, args, parser):
-    cmd = 'update-inetd --group LSB '
+    cmd = ['update-inetd','--group','LSB']
 
     alist = list(args[0].split(':'))
     if len(alist) < 2:
@@ -184,7 +187,7 @@ def handle_inet(options, args, parser):
     
     if options.remove:
         parts = r'%s\s+.*\s+%s\s+.*' % (re.escape(alist[0], alist[1]))
-        cmd += '--remove '+commands.mkarg(parts)
+        cmd.extend(['--remove',parts])
     elif options.check:
         return
     else:
@@ -192,9 +195,9 @@ def handle_inet(options, args, parser):
             parser.error('The operand must have six colon-separated arguments.')
             return
         newalist = [alist[0], alist[2], alist[1]] + alist[3:]
-        cmd += '--add '+commands.mkarg('\t'.join(newalist))
+        cmd.extend(['--add','\t'.join(newalist)])
 
-    os.system(cmd)
+    subprocess.call(cmd)
     pass
 
 def handle_man(options, args):
@@ -264,7 +267,7 @@ def main():
             parser.error('Only one argument supported for %s' % options.type)
         handle_man(options, args)
     else:
-        print >> sys.stderr, 'Unsupported type %s' % options.type
+        print('Unsupported type %s' % options.type, file=sys.stderr)
         sys.exit(1)
 
 if __name__ == '__main__':
diff --git a/remove_initd b/remove_initd
index 0322c7f..29e3dce 100755
--- a/remove_initd
+++ b/remove_initd
@@ -1,5 +1,8 @@
 #!/usr/bin/python
 
+# Python3-compatible print() function
+from __future__ import print_function
+
 import sys, re, os, initdutils
 
 if len(sys.argv) > 1:
@@ -12,7 +15,7 @@ if len(sys.argv) > 1:
     else:
         initfile = os.path.join('/etc/init.d', initfile)
 else:
-    print >> sys.stderr, 'Usage: %s /etc/init.d/<init-script>' % sys.argv[0]
+    print('Usage: %s /etc/init.d/<init-script>' % sys.argv[0], file=sys.stderr)
     sys.exit(1)
 
 headers = initdutils.scan_initfile(initfile)
@@ -25,18 +28,18 @@ if provides:
     for facility in provides:
         if facility in facilities:
             entries = {}
-            for entry in facilities[facility].items():
+            for entry in list(facilities[facility].items()):
                 if entry[0] != initfile:
                     entries[entry[0]] = entry[1]
             facilities[facility] = entries
 
-    for (initscript, needed) in depends.iteritems():
+    for (initscript, needed) in list(depends.items()):
         for facility in needed:
             if facility[0] == "$":
                 continue
             if not facilities.get(facility) and facility in provides:
-                print >> sys.stderr, 'Unable to remove %s: %s needs %s\n' % (
-                    initfile, initscript, facility)
+                print('Unable to remove %s: %s needs %s\n' % (
+                    initfile, initscript, facility), file=sys.stderr)
                 sys.exit(1)
 
     if initfile in depends:
signature.asc (application/pgp-signature, 663 B)
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.17 (MingW32)

iQGcBAEBAgAGBQJPn6FSAAoJEIvPpx7KFjRVnM4L/j4F0uH3xrr6vSkVshafl21F
C86IuQk7p5aVBeXYIE8T+9GdF4SGPzrx8Zv/hAy7GAnqs95oy7TWVxExchEqU0Un
0hV1HDylvIcmdgsG+lzt219Z3UEb93vjcFsdTIZxs9sXB3mEMwkaEU6g5tXyfc4I
LrzMSQ38KGVkDO8/yCbCF31j5lO9IIpUq2yS7S0vaSyikjiV2RghrZeVml+g/kIE
iH6EaFfXz9Ln17LBq8sdm83byMwAEhqIyBmsEPpfKV9XRBh0I+cDn+HA1/J1rHal
YV27BoBL6lCpljnyihFILxf2zK+YXJqia+nl2k1zfJAjTGcsee6wdRSVUlBaQCT/
EwKBRDg32j5eMacwsuSuq1pn7LVvjuqnsydt/NdSJQHpRHaHqDxGC2lbKLV/uI9o
ZhLmy0INzOW1vMUMqMd+iwbldBkrdCD6dMfQIlJh924svtVbbNY3pW330V28MaqO
6VJV3ws5WvkCTqehoiELAfhijoqQWVG3UZz2cM9VsQ==
=kzbU
-----END PGP SIGNATURE-----
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.