Mercurial > cgi-bin > hgweb.cgi > PassMan
comparison src/main/kotlin/name/blackcap/passman/Main.kt @ 22:07406c4af4a5
More interactive mode stuff.
author | David Barts <n5jrn@me.com> |
---|---|
date | Tue, 02 Jul 2024 17:34:52 -0700 |
parents | ea65ab890f66 |
children | af86b8e0b88c |
comparison
equal
deleted
inserted
replaced
21:ea65ab890f66 | 22:07406c4af4a5 |
---|---|
7 import kotlin.reflect.jvm.javaMethod | 7 import kotlin.reflect.jvm.javaMethod |
8 import kotlin.reflect.jvm.kotlinFunction | 8 import kotlin.reflect.jvm.kotlinFunction |
9 import kotlin.system.exitProcess | 9 import kotlin.system.exitProcess |
10 | 10 |
11 fun main(args: Array<String>) { | 11 fun main(args: Array<String>) { |
12 val NOPASSWORD = setOf<String>("help") | |
12 if (args.isEmpty()) { | 13 if (args.isEmpty()) { |
13 error("expecting subcommand") | 14 openDatabase() |
15 runInteractive() | |
16 } | |
17 val subcommand = args[0] | |
18 val scArgs = args.sliceArray(1 until args.size) | |
19 if (subcommand !in NOPASSWORD) { | |
20 openDatabase() | |
21 } | |
22 runNonInteractive(subcommand, scArgs) | |
23 } | |
24 | |
25 fun openDatabase() { | |
26 try { | |
27 Database.default = Database.open() | |
28 } catch (e: DatabaseException) { | |
29 handleMessagedException(e) | |
14 exitProcess(2) | 30 exitProcess(2) |
15 } | 31 } |
16 val subcommand = args[0]; | 32 } |
17 val scArgs = args.sliceArray(1 until args.size) | 33 |
18 Database.default = Database.open() | 34 fun runNonInteractive(subcommand: String, scArgs: Array<String>): Unit { |
19 runSubcommand(subcommand, scArgs) | 35 try { |
36 runSubcommand(subcommand, scArgs) | |
37 } catch (e: SubcommandException) { | |
38 handleSubcommandException(e) | |
39 exitProcess(e.status) | |
40 } catch (e: MessagedException) { | |
41 handleMessagedException(e) | |
42 exitProcess(1) | |
43 } | |
44 exitProcess(0) | |
45 } | |
46 | |
47 fun runInteractive() { | |
48 val DISALLOWED = setOf<String>("password") | |
49 val QUIT = setOf<String>("exit", "quit") | |
50 var lastStatus = 0 | |
51 while (true) { | |
52 val rawLine = System.console()?.readLine("passman> ") ?: break | |
53 val s = Shplitter() | |
54 s.feed(rawLine) | |
55 if (!s.complete) { | |
56 error("unterminated quoting") | |
57 lastStatus = 1 | |
58 continue | |
59 } | |
60 val line = s.split().toList() | |
61 if (line.isEmpty()) { | |
62 continue | |
63 } | |
64 val subcommand = line.first() | |
65 val scArgs = line.drop(1).toTypedArray() | |
66 if (subcommand in QUIT) { | |
67 break | |
68 } | |
69 if (subcommand in DISALLOWED) { | |
70 error("$subcommand subcommand not allowed in interactive mode") | |
71 lastStatus = 2 | |
72 continue | |
73 } | |
74 try { | |
75 runSubcommand(subcommand, scArgs) | |
76 lastStatus = 0 | |
77 } catch(e: SubcommandException) { | |
78 handleSubcommandException(e) | |
79 lastStatus = e.status | |
80 } catch(e: MessagedException) { | |
81 handleMessagedException(e) | |
82 lastStatus = 1 | |
83 } | |
84 } | |
85 println() // ensure shell prompt comes out on a line of its own | |
86 exitProcess(lastStatus) | |
20 } | 87 } |
21 | 88 |
22 fun runSubcommand(name: String, args: Array<String>): Unit { | 89 fun runSubcommand(name: String, args: Array<String>): Unit { |
23 val instance = getInstanceForClass(getClassForSubcommand(name)) | 90 val instance = getInstanceForClass(getClassForSubcommand(name)) |
24 if (instance == null) { | 91 if (instance == null) { |
25 die("${see(name)} - unknown subcommand", 2) | 92 throw SubcommandException(message = "${see(name)} - unknown subcommand", status = 2) |
26 } else { | 93 } else { |
27 instance.run(args) | 94 instance.run(args) |
28 } | 95 } |
29 } | 96 } |
30 | 97 |
40 fun getInstanceForClass(klass: Class<Subcommand>?) = try { | 107 fun getInstanceForClass(klass: Class<Subcommand>?) = try { |
41 klass?.getDeclaredConstructor()?.newInstance() | 108 klass?.getDeclaredConstructor()?.newInstance() |
42 } catch (e: ReflectiveOperationException) { | 109 } catch (e: ReflectiveOperationException) { |
43 null | 110 null |
44 } | 111 } |
112 | |
113 fun handleMessagedException(e: MessagedException) = error(e.message) | |
114 | |
115 fun handleSubcommandException(e: SubcommandException): Unit { | |
116 if (e.message != null) { | |
117 error(e.message!!) | |
118 } | |
119 } |