From f296c49694436583aa6194852bae5df395dacd05 Mon Sep 17 00:00:00 2001 From: Clinton Ebadi Date: Sun, 6 Jan 2013 06:18:52 -0500 Subject: [PATCH] Change package-exists to return section/description Kind of ugly, will break in wheezy (fields are localized and names change), but we need this information for the portal. Possible evil use of MsgNo without MsgYes. --- src/main.sml | 13 +++++++++---- src/msg.sml | 6 ++++++ src/msgTypes.sml | 2 ++ src/plugins/apt.sig | 4 ++-- src/plugins/apt.sml | 47 +++++++++++++++++++++++++-------------------- 5 files changed, 45 insertions(+), 27 deletions(-) diff --git a/src/main.sml b/src/main.sml index 4b8123d..e2df22b 100644 --- a/src/main.sml +++ b/src/main.sml @@ -795,10 +795,13 @@ fun requestAptExists {node, pkg} = OS.Process.failure) | SOME m => case m of - MsgYes => (print "Package exists.\n"; - OS.Process.success) + MsgAptQuery {section,description} => (print "Package exists.\n"; + print ("Section: " ^ section ^ "\n"); + print ("Description: " ^ description ^ "\n"); + OS.Process.success) | MsgNo => (print "Package does not exist.\n"; - OS.Process.failure) + OS.Process.failure + (* It might be the Wrong Thing (tm) to use MsgNo like this *)) | MsgError s => (print ("APT existence query failed: " ^ s ^ "\n"); OS.Process.failure) | _ => (print "Unexpected server reply.\n"; @@ -1213,7 +1216,9 @@ fun now () = Date.toString (Date.fromTimeUniv (Time.now ())) fun answerQuery q = case q of QApt pkg => if Apt.installed pkg then MsgYes else MsgNo - | QAptExists pkg => if Apt.exists pkg then MsgYes else MsgNo + | QAptExists pkg => (case Apt.info pkg of + SOME {section, description} => MsgAptQuery {section = section, description = description} + | NONE => MsgNo) | QCron user => if Cron.allowed user then MsgYes else MsgNo | QFtp user => if Ftp.allowed user then MsgYes else MsgNo | QTrustedPath user => if TrustedPath.query user then MsgYes else MsgNo diff --git a/src/msg.sml b/src/msg.sml index 0a50b6e..22f548c 100644 --- a/src/msg.sml +++ b/src/msg.sml @@ -242,6 +242,9 @@ fun send (bio, m) = | MsgReUsers => OpenSSL.writeInt (bio, 41) | MsgVmailChanged => OpenSSL.writeInt (bio, 42) | MsgFirewallRegen => OpenSSL.writeInt (bio, 43) + | MsgAptQuery {section, description} => (OpenSSL.writeInt (bio, 44); + OpenSSL.writeString (bio, section); + OpenSSL.writeString (bio, description)) fun checkIt v = case v of @@ -357,6 +360,9 @@ fun recv bio = | 41 => SOME MsgReUsers | 42 => SOME MsgVmailChanged | 43 => SOME MsgFirewallRegen + | 44 => (case (OpenSSL.readString bio, OpenSSL.readString bio) of + (SOME section, SOME description) => SOME (MsgAptQuery {section = section, description = description}) + | _ => NONE) | _ => NONE) end diff --git a/src/msgTypes.sml b/src/msgTypes.sml index dcd04cb..9b7d02c 100644 --- a/src/msgTypes.sml +++ b/src/msgTypes.sml @@ -132,5 +132,7 @@ datatype msg = (* Server tells slave that vmail user information has changed *) | MsgFirewallRegen (* Regenerate firewall on user machines *) + | MsgAptQuery of {section : string, description : string} + (* Answer to QAptExists query *) end diff --git a/src/plugins/apt.sig b/src/plugins/apt.sig index 2546fd5..b44f81b 100644 --- a/src/plugins/apt.sig +++ b/src/plugins/apt.sig @@ -20,8 +20,8 @@ signature APT = sig - val exists : string -> bool - (* Does the package exist on this host? *) + val info : string -> {section : string, description : string} option + (* Package information *) val installed : string -> bool (* Is the named package installed on this host? *) diff --git a/src/plugins/apt.sml b/src/plugins/apt.sml index e97ec82..a7ae93a 100644 --- a/src/plugins/apt.sml +++ b/src/plugins/apt.sml @@ -26,27 +26,32 @@ fun validName s = CharVector.all (fn ch => Char.isAlphaNum ch orelse ch = #"_" o (* Copyed from the portal, doesn't exactly go out this in the most direct way, or does it? *) -fun exists name = - validName name andalso let - val proc = Unix.execute ("/usr/bin/apt-cache", ["show", name]) - val inf = Unix.textInstreamOf proc - - val _ = TextIO.inputLine inf (* in every let* lies an imperative program in disguise *) - - fun loop _ = - case TextIO.inputLine inf of - NONE => false - | SOME line => - if size line >= 9 andalso String.substring (line, 0, 9) = "Section: " then - true - else if size line >= 13 andalso String.substring (line, 0, 13) = "Description: " then - false - else - loop () - in - loop () - before ignore (Unix.reap proc) - end +fun info name = + if not (validName name) then + NONE + else + let + val proc = Unix.execute ("/usr/bin/apt-cache", ["show", name]) + val inf = Unix.textInstreamOf proc + + val _ = TextIO.inputLine inf (* in every let* lies an imperative program in disguise *) + + fun loop (section, descr) = + case TextIO.inputLine inf of + NONE => (section, descr) + | SOME line => + if size line >= 9 andalso String.substring (line, 0, 9) = "Section: " then + loop (SOME (String.substring (line, 9, size line - 10)), descr) + else if size line >= 13 andalso String.substring (line, 0, 13) = "Description: " then + loop (section, SOME (String.substring (line, 13, size line - 14))) + else + loop (section, descr) + in + (case loop (NONE, NONE) of + (SOME section, SOME descr) => SOME {section = section, description = descr} + | _ => NONE) + before ignore (Unix.reap proc) + end fun installed name = validName name -- 2.20.1