Simplify prune plugins and fix array difference error.
[mailshears.git] / bin / mailshears
1 #!/usr/bin/ruby -wU
2 #
3 # mailshears, to prune unused mail directories.
4 #
5
6 # Define a usage string using the program name.
7 exe = File.basename($PROGRAM_NAME)
8 usage = "#{exe} [prune | rm <target> | mv <src> <dst>]"
9
10 # Defaults
11 mode_name = 'prune'
12 mode = :prune
13
14 # Now, if a mode was supplied, it should be in ARGV[0].
15 if ARGV.length() > 0
16 mode_names = ['prune', 'rm', 'mv']
17 if mode_names.include?(ARGV.first().downcase()) then
18 # Peel the mode name off the head of the list.
19 mode_name = ARGV.shift()
20 end
21 end
22
23 if mode_name == 'rm' then
24 mode = :rm
25 elsif mode_name == 'mv' then
26 mode = :mv
27 end
28
29 # Need this before referencing ExitCodes.
30 require 'mailshears'
31
32 # Since we removed both the executable name and the mode name (if it
33 # existed) from ARGV, what remains should be the required arguments.
34 # Figure out if we have the wrong number of arguments, and store the
35 # associated error message in args_error_message if we do.
36 args_error_message = nil
37 if mode == :prune and ARGV.length() != 0 then
38 args_error_message = "ERROR: prune mode takes no additional arguments."
39 elsif mode == :rm and ARGV.length() < 1 then
40 args_error_message = "ERROR: rm mode takes two or more user arguments."
41 elsif mode == :mv and ARGV.length() != 2 then
42 args_error_message = "ERROR: mv mode takes exactly two user arguments."
43 end
44
45 # If we got the wrong number of arguments, we'll have some error
46 # message. Report it and quit.
47 if not args_error_message.nil? then
48 STDERR.puts args_error_message
49 puts "Usage: #{usage}"
50 Kernel.exit(ExitCodes::BAD_COMMAND_LINE)
51 end
52
53
54 cfg = Configuration.new()
55
56 # Load each of the plugins that we'll need.
57 cfg.plugins.each do |plugin_file|
58 require "#{mode_name}/plugins/#{plugin_file}"
59 end
60
61 # And the runners.
62 require "#{mode_name}/#{mode_name}_runner"
63 require "#{mode_name}/#{mode_name}_dummy_runner"
64
65 def make_header(plugin_name)
66 # The header that we output before the list of domains/users.
67 # Just the path of this script, the current time, and the plugin name.
68 exe = File.basename($PROGRAM_NAME)
69 header = "#{exe}, "
70
71 current_time = Time.now()
72 if current_time.respond_to?(:iso8601)
73 # Somehow this method is missing on some machines.
74 header += current_time.iso8601.to_s
75 else
76 # Fall back to whatever this looks like.
77 header += current_time.to_s
78 end
79
80 header += ' (Plugin: ' + plugin_name + ")\n"
81 header += '-' * header.size # Underline the header.
82
83 return header
84 end
85
86
87 plugin_module = nil
88
89 if mode == :rm then
90 plugin_module = RmPlugin
91 elsif mode == :mv then
92 plugin_module = MvPlugin
93 else
94 # Safe, catch-all default
95 plugin_module = PrunePlugin
96 end
97
98 # Buffer the output so that we can avoid printing the informational
99 # header when no plugins produce output.
100 require 'stringio'
101 output_buffer = StringIO.new()
102 $stdout = output_buffer
103
104 # Parse the remaining arguments as User/Domain objects. If we get some
105 # other argument that isn't one of those, it's an error.
106 parsed_args = []
107 ARGV.each do |arg|
108 begin
109 u = User.new(arg)
110 parsed_args << u
111 rescue InvalidUserError
112 begin
113 d = Domain.new(arg)
114 parsed_args << d
115 rescue InvalidDomainError
116 STDERR.puts "ERROR: invalid user/domain argument #{arg}"
117 Kernel.exit(ExitCodes::BAD_COMMAND_LINE)
118 end
119 end
120 end
121
122 begin
123 plugin_module.run(cfg, *parsed_args)
124 ensure
125 # Now restore stdout, and print the header plus whatever the plugins
126 # produced if they produced anything. If they didn't produce any
127 # output, then we avoid printing the header.
128 #
129 # This gets wrapped in an "ensure" block because otherwise, if
130 # plugin_module.run() crashes, the traceback will get stored in
131 # output_buffer and never get printed.
132 $stdout = STDOUT
133 if output_buffer.size > 0 then
134 puts make_header(plugin_module.to_s())
135 puts output_buffer.string()
136 end
137 end