fun validName s = CharVector.all (fn ch => Char.isAlphaNum ch orelse ch = #"_" orelse ch = #"-" orelse ch = #".") s
andalso (size s > 0 andalso String.sub (s, 0) <> #"-")
+
+(* 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 installed name =
validName name