- Moving lots of stuff from stdout to stderr
authorgenone <genone@gentoo.org>
Tue, 15 Nov 2005 21:20:49 +0000 (21:20 -0000)
committergenone <genone@gentoo.org>
Tue, 15 Nov 2005 21:20:49 +0000 (21:20 -0000)
- Replace all "print" calls with matching write() calls
- add new "affected" target
- add support for a EMERGE_OPTS env var
- check that GLSA_DIR exists
- add --cve option requested by solar
- show title on --test --verbose
- better exception handling

svn path=/; revision=258

trunk/src/glsa-check/glsa-check

index a922a516b92208fff5b56c4068a46fbc8a5ca1d6..d680d6229b317729bb5d4eda2a753524ada8d127 100644 (file)
@@ -11,7 +11,7 @@ from getopt import getopt,GetoptError
 
 __program__ = "glsa-check"
 __author__ = "Marius Mauch <genone@gentoo.org>"
-__version__ = "0.5"
+__version__ = "0.6"
 
 optionmap = [
 ["-l", "--list", "list all unapplied GLSA"],
@@ -23,23 +23,24 @@ optionmap = [
 ["-n", "--nocolor", "disable colors (option)"],
 ["-h", "--help", "show this help message"],
 ["-V", "--version", "some information about this tool"],
-["-v", "--verbose", "print more messages (option)"],
+["-v", "--verbose", "print more information (option)"],
+["-c", "--cve", "show CAN ids n listing mode (option)"],
 ]
 
-# print a warning as this is beta code
-sys.stderr.write("WARNING: This tool is completely new and not very tested, so it should not be\n")
-sys.stderr.write("used on production systems. It's mainly a test tool for the new GLSA release\n")
-sys.stderr.write("and distribution system, it's functionality will later be merged into emerge\n")
-sys.stderr.write("and equery.\n")
-sys.stderr.write("Please read http://www.gentoo.org/proj/en/portage/glsa-integration.xml\n")
-sys.stderr.write("before using this tool AND before reporting a bug.\n\n")
+# print a warning as this is beta code (but proven by now, so no more warning)
+#sys.stderr.write("WARNING: This tool is completely new and not very tested, so it should not be\n")
+#sys.stderr.write("used on production systems. It's mainly a test tool for the new GLSA release\n")
+#sys.stderr.write("and distribution system, it's functionality will later be merged into emerge\n")
+#sys.stderr.write("and equery.\n")
+#sys.stderr.write("Please read http://www.gentoo.org/proj/en/portage/glsa-integration.xml\n")
+#sys.stderr.write("before using this tool AND before reporting a bug.\n\n")
 
 # option parsing
 args = []
 params = []
 try:
-       args, params = getopt(sys.argv[1:], "dplfchinvVt", \
-               ["dump", "print", "list", "pretend", "fix", "inject", "help", "info", "version", "test", "nocolor"])
+       args, params = getopt(sys.argv[1:], "dplfchinvVtc", \
+               ["dump", "print", "list", "pretend", "fix", "inject", "help", "info", "version", "test", "nocolor", "cve"])
        args = [a for a,b in args]
        
        for option in ["--nocolor", "-n"]:
@@ -53,12 +54,18 @@ try:
                        verbose = True
                        args.remove(option)
 
+       list_cve = False
+       for option in ["--cve", "-c"]:
+               if option in args:
+                       list_cve = True
+                       args.remove(option)
+
        # sanity checking
        if len(args) <= 0:
-               print "no option given: what should I do ?"
+               sys.stderr.write("no option given: what should I do ?\n")
                mode="help"
        elif len(args) > 1:
-               print "please use only one command per call"
+               sys.stderr.write("please use only one command per call\n")
                mode = "help"
        else:
                # in what mode are we ?
@@ -68,50 +75,41 @@ try:
                                mode = m[1][2:]
 
 except GetoptError, e:
-       print "unknown option given:", e
+       sys.stderr.write("unknown option given: ")
+       sys.stderr.write(str(e)+"\n")
        mode = "help"
 
 # we need a set of glsa for most operation modes
 if len(params) <= 0 and mode in ["fix", "test", "pretend", "dump", "inject"]:
-       print
-       print "no GLSA given, so we'll do nothing for now. "
-       print "If you want to run on all GLSA please tell me so "
-       print "(specify \"all\" as parameter)"
-       print
+       sys.stderr.write("\nno GLSA given, so we'll do nothing for now. \n")
+       sys.stderr.write("If you want to run on all GLSA please tell me so \n")
+       sys.stderr.write("(specify \"all\" as parameter)\n\n")
        mode = "help"
 elif len(params) <= 0 and mode == "list":
        params.append("new")
        
 # show help message
 if mode == "help":
-       print
-       print "Syntax: glsa-check <option> [glsa-list]"
-       print
+       sys.stderr.write("\nSyntax: glsa-check <option> [glsa-list]\n\n")
        for m in optionmap:
-               print m[0] + "\t" + m[1] + "   \t: " + m[-1]
+               sys.stderr.write(m[0] + "\t" + m[1] + "   \t: " + m[-1] + "\n")
                for o in m[2:-1]:
-                       print "\t" + o
-       print
-       print "glsa-list can contain an arbitrary number of GLSA ids, "
-       print "filenames containing GLSAs or the special identifiers "
-       print "'all' and 'new'"
-       print
+                       sys.stderr.write("\t" + o + "\n")
+       sys.stderr.write("\nglsa-list can contain an arbitrary number of GLSA ids, \n")
+       sys.stderr.write("filenames containing GLSAs or the special identifiers \n")
+       sys.stderr.write("'all', 'new' and 'affected'\n")
        sys.exit(1)
 
 # we need root priviledges for write access
 if mode in ["fix", "inject"] and os.geteuid() != 0:
-       print
-       print "This tool needs root access to "+mode+" this GLSA"
-       print
+       sys.stderr.write("\nThis tool needs root access to "+mode+" this GLSA\n\n")
        sys.exit(2)
 
 # show version and copyright information
 if mode == "version":
-       print
-       print __program__ + ", version " + __version__
-       print "Author: " + __author__
-       print "This program is licensed under the GPL, version 2"
-       print
+       sys.stderr.write("\n"+ __program__ + ", version " + __version__ + "\n")
+       sys.stderr.write("Author: " + __author__ + "\n")
+       sys.stderr.write("This program is licensed under the GPL, version 2\n\n")
        sys.exit(0)
 
 # delay this for speed increase
@@ -119,6 +117,11 @@ from glsa import *
 
 glsaconfig = checkconfig(portage.config(clone=portage.settings))
 
+# Check that we really have a glsa dir to work on
+if not (os.path.exists(glsaconfig["GLSA_DIR"]) and os.path.isdir(glsaconfig["GLSA_DIR"])):
+       sys.stderr.write(red("ERROR")+": GLSA_DIR %s doesn't exist. Please fix this.\n" % glsaconfig["GLSA_DIR"])
+       sys.exit(1)
+
 # build glsa lists
 completelist = get_glsa_list(glsaconfig["GLSA_DIR"], glsaconfig)
 
@@ -135,27 +138,39 @@ if "new" in params:
 if "all" in params:
        glsalist = completelist
        params.remove("all")
+if "affected" in params:
+       # maybe this should be todolist instead
+       for x in completelist:
+               try:
+                       myglsa = Glsa(x, glsaconfig)
+               except (GlsaTypeException, GlsaFormatException), e:
+                       if verbose:
+                               sys.stderr.write(("invalid GLSA: %s (error message was: %s)\n" % (x, e)))
+                       continue
+               if myglsa.isVulnerable():
+                       glsalist.append(x)
+       params.remove("affected")
 
 # remove invalid parameters
 for p in params[:]:
        if not (p in completelist or os.path.exists(p)):
-               print "(removing %s from parameter list as it isn't a valid GLSA specification)" % p
+               sys.stderr.write(("(removing %s from parameter list as it isn't a valid GLSA specification)\n" % p))
                params.remove(p)
 
 glsalist.extend([g for g in params if g not in glsalist])
 
 # list short information for given or new GLSA
 if mode == "list":
-       print white("[A]")+" means this GLSA was already applied,"
-       print green("[U]")+" means the system is not affected and"
-       print red("[N]")+" indicates that the system might be affected."
-       print
+       sys.stderr.write(white("[A]")+" means this GLSA was already applied,\n")
+       sys.stderr.write(green("[U]")+" means the system is not affected and\n")
+       sys.stderr.write(red("[N]")+" indicates that the system might be affected.\n\n")
+
        for myid in glsalist:
                try:
                        myglsa = Glsa(myid, glsaconfig)
-               except GlsaTypeException, e:
+               except (GlsaTypeException, GlsaFormatException), e:
                        if verbose:
-                               print "invalid GLSA: %s (error message was: %s)" % (myid, e)
+                               sys.stderr.write(("invalid GLSA: %s (error message was: %s)\n" % (myid, e)))
                        continue
                if myglsa.isApplied():
                        status = "[A]"
@@ -166,12 +181,15 @@ if mode == "list":
                else:
                        status = "[U]"
                        color = green
-               print color(myglsa.nr), color(status), myglsa.title, "(", 
+               sys.stdout.write(color(myglsa.nr) + " " + color(status) + " " + myglsa.title + " (") 
                for pkg in myglsa.packages.keys()[:3]:
-                       print pkg,
+                       sys.stdout.write(" " + pkg + " ")
                if len(myglsa.packages) > 3:
-                       print "...",
-               print ")"
+                       sys.stdout.write("... ")
+               sys.stdout.write(")")
+               if list_cve:
+                       sys.stdout.write(" "+(",".join([r[:13] for r in myglsa.references if r[:4] == "CAN-"])))
+               sys.stdout.write("\n")          
        sys.exit(0)
 
 # dump, fix, inject and fix are nearly the same code, only the glsa method call differs
@@ -179,45 +197,43 @@ if mode in ["dump", "fix", "inject", "pretend"]:
        for myid in glsalist:
                try:
                        myglsa = Glsa(myid, glsaconfig)
-               except GlsaTypeException, e:
+               except (GlsaTypeException, GlsaFormatException), e:
                        if verbose:
-                               print "invalid GLSA: %s (error message was: %s)" % (myid, e)
+                               sys.stderr.write(("invalid GLSA: %s (error message was: %s)\n" % (myid, e)))
                        continue
                if mode == "dump":
                        myglsa.dump()
                elif mode == "fix":
-                       print "fixing "+myid
+                       sys.stdout.write("fixing "+myid+"\n")
                        mergelist = myglsa.getMergeList()
                        for pkg in mergelist:
-                               print ">>> merging "+pkg
+                               sys.stdout.write(">>> merging "+pkg+"\n")
                                # using emerge for the actual merging as it contains the dependency
                                # code and we want to be consistent in behaviour. Also this functionality
                                # will be integrated in emerge later, so it shouldn't hurt much.
-                               exitcode = os.system("emerge --oneshot ="+pkg)
+                               emergecmd = "emerge --oneshot " + glsaconfig["EMERGE_OPTS"] + " =" + pkg
+                               if verbose:
+                                       sys.stderr.write(emergecmd+"\n")
+                               exitcode = os.system(emergecmd)
                                if exitcode:
                                        sys.exit(exitcode)
                        myglsa.inject()
                elif mode == "pretend":
-                       print "Checking GLSA "+myid
+                       sys.stdout.write("Checking GLSA "+myid+"\n")
                        mergelist = myglsa.getMergeList()
                        if mergelist:
-                               print "The following updates will be performed for this GLSA:"
+                               sys.stdout.write("The following updates will be performed for this GLSA:\n")
                                for pkg in mergelist:
                                        # we simplify a bit here
                                        oldver = portage.db["/"]["vartree"].dbapi.match(portage.dep_getkey(pkg))[-1]
                                        oldver = oldver[len(portage.dep_getkey(oldver))+1:]
-                                       print "    ", pkg, "("+oldver+")"
+                                       sys.stdout.write("     " + pkg + " (" + oldver + ")\n")
                        else:
-                               print "Nothing to do for this GLSA"
+                               sys.stdout.write("Nothing to do for this GLSA\n")
                elif mode == "inject":
-                       print "injecting " + myid
+                       sys.stdout.write("injecting " + myid + "\n")
                        myglsa.inject()
-               if glsalist[-1] != myid:
-                       print 
-                       print 70*'*'
-                       print
-               else:
-                       print
+               sys.stdout.write("\n")
        sys.exit(0)
 
 # test is a bit different as Glsa.test() produces no output
@@ -226,20 +242,24 @@ if mode == "test":
        for myid in glsalist:
                try:
                        myglsa = Glsa(myid, glsaconfig)
-               except GlsaTypeException, e:
+               except (GlsaTypeException, GlsaFormatException), e:
                        if verbose:
-                               print "invalid GLSA: %s (error message was: %s)" % (myid, e)
+                               sys.stderr.write(("invalid GLSA: %s (error message was: %s)\n" % (myid, e)))
                        continue
                if myglsa.isVulnerable():
                        outputlist.append(myglsa.nr)
        if len(outputlist) > 0:
-               print "This system is affected by the following GLSA:"
+               sys.stderr.write("This system is affected by the following GLSAs:\n")
                for g in outputlist:
-                       print g
+                       sys.stdout.write(g)
+                       if verbose:
+                               sys.stdout.write(" ( " + myglsa.title + " )\n")
+                       else:
+                               sys.stdout.write("\n")
        else:
-               print "This system is not affected by any of the listed GLSA"
+               sys.stderr.write("This system is not affected by any of the listed GLSAs\n")
        sys.exit(0)
        
 # something wrong here, all valid paths are covered with sys.exit()
-print "nothing more to do"
+sys.stderr.write("nothing more to do\n")
 sys.exit(2)