|
1 // Copyright (C) 2000 Mike Bell <mike@mikebell.org>, |
|
2 // Bruce Guenter <bruceg@em.ca> |
|
3 // |
|
4 // This program is free software; you can redistribute it and/or modify |
|
5 // it under the terms of the GNU General Public License as published by |
|
6 // the Free Software Foundation; either version 2 of the License, or |
|
7 // (at your option) any later version. |
|
8 // |
|
9 // This program is distributed in the hope that it will be useful, |
|
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 // GNU General Public License for more details. |
|
13 // |
|
14 // You should have received a copy of the GNU General Public License |
|
15 // along with this program; if not, write to the Free Software |
|
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
17 |
|
18 #include <config.h> |
|
19 #include <stdlib.h> |
|
20 #include <sys/stat.h> |
|
21 #include <stdio.h> |
|
22 #include "daemon.h" |
|
23 #include "config/configrc.h" |
|
24 #include "misc/response.h" |
|
25 #include "misc/lookup.h" |
|
26 #include "misc/maildir.h" |
|
27 #include "misc/pwentry_table.h" |
|
28 #include "misc/stat_fns.h" |
|
29 |
|
30 response autoresponse_write(const mystring& directory, |
|
31 const mystring& location, |
|
32 const mystring& disabled, |
|
33 const mystring& msg) |
|
34 { |
|
35 mystring tmpfile = location + ".lock"; |
|
36 |
|
37 if(!is_dir(directory.c_str())) { |
|
38 if(mkdir(directory.c_str(), 0755)) |
|
39 RETURN(err, "Could not create autoresponse directory"); |
|
40 } |
|
41 |
|
42 if(is_exist(tmpfile.c_str())) |
|
43 RETURN(err, "Temporary autoresponse file already exists"); |
|
44 |
|
45 if(is_exist(disabled.c_str())) |
|
46 RETURN(err, "Autoresponse is disabled, reenable it before writing a new message"); |
|
47 |
|
48 fdobuf out(tmpfile.c_str(), fdobuf::create | fdobuf::excl, 0644); |
|
49 if(!out) |
|
50 RETURN(err, "Unable to open temporary autoresponse file for writing"); |
|
51 |
|
52 out << msg; |
|
53 if(!out.flush() || !out.close()) { |
|
54 unlink(tmpfile.c_str()); |
|
55 RETURN(err, "Unable to write message to file"); |
|
56 } |
|
57 if(rename(tmpfile.c_str(), location.c_str())) { |
|
58 unlink(tmpfile.c_str()); |
|
59 RETURN(err, "Unable to rename temporary autoresponse file"); |
|
60 } |
|
61 |
|
62 RETURN(ok, "Message successfully written to autoresponse file"); |
|
63 } |
|
64 |
|
65 response autoresponse_disable(const mystring& location, |
|
66 const mystring& disabled) |
|
67 { |
|
68 if(!is_exist(location.c_str())) |
|
69 RETURN(ok, "Autoresponse file did not exist"); |
|
70 if(is_exist(disabled.c_str())) |
|
71 RETURN(err, "Disabled autoresponse file already exists"); |
|
72 if(rename(location.c_str(), disabled.c_str())) |
|
73 RETURN(err, "Unable to rename autoresponse file"); |
|
74 RETURN(ok, "Autoresponse file sucessfully disabled"); |
|
75 } |
|
76 |
|
77 response autoresponse_enable(const mystring& location, |
|
78 const mystring& disabled) |
|
79 { |
|
80 if(is_exist(location.c_str())) |
|
81 RETURN(ok, "Autoresponse is already enabled"); |
|
82 if(!is_exist(disabled.c_str())) |
|
83 RETURN(err, "Disabled autoresponse file did not exist"); |
|
84 if(rename(disabled.c_str(), location.c_str())) |
|
85 RETURN(err, "Unable to rename previously disabled autoresponse file"); |
|
86 RETURN(ok, "Autoresponse file sucessfully restored"); |
|
87 } |
|
88 |
|
89 static bool read_file(const mystring& filename, mystring& out) |
|
90 { |
|
91 fdibuf in(filename.c_str()); |
|
92 if(!in) |
|
93 return false; |
|
94 char contents[65536]; |
|
95 unsigned contentlen; |
|
96 in.read(contents, 65536); |
|
97 contentlen = in.last_count(); |
|
98 out = mystring(contents, contentlen); |
|
99 return true; |
|
100 } |
|
101 |
|
102 response autoresponse_read(const mystring& location, |
|
103 const mystring& disabled, int fd) |
|
104 { |
|
105 mystring line; |
|
106 if(!is_exist(location.c_str()) && |
|
107 !is_exist(disabled.c_str())) |
|
108 RETURN(err, "Autoresponder file does not exist"); |
|
109 |
|
110 mystring contents; |
|
111 if(!read_file(location, contents) && |
|
112 !read_file(disabled, contents)) |
|
113 RETURN(err, "Unable to read data from autoresponse file"); |
|
114 response resp(response::ok, contents); |
|
115 resp.write(fd); |
|
116 RETURN(ok, "Retrieved autoresponse file"); |
|
117 } |
|
118 |
|
119 response autoresponse_delete(const mystring& directory) |
|
120 { |
|
121 if(!is_dir(directory.c_str())) |
|
122 RETURN(err, "Autoresponse directory does not exist."); |
|
123 if(!delete_directory(directory)) |
|
124 RETURN(err, "Could not delete autoresponse directory."); |
|
125 RETURN(ok, "Autoresponse directory deleted."); |
|
126 } |
|
127 |
|
128 response autoresponse_status(const mystring& directory, |
|
129 const mystring& location, |
|
130 const mystring& disabled) |
|
131 { |
|
132 const char* msg; |
|
133 if(is_exist(location.c_str())) |
|
134 msg = "enabled"; |
|
135 else if(is_exist(disabled.c_str())) |
|
136 msg = "disabled"; |
|
137 else if(is_dir(directory.c_str())) |
|
138 msg = "missing message file"; |
|
139 else |
|
140 msg = "nonexistant"; |
|
141 RETURN(ok, msg); |
|
142 } |
|
143 |
|
144 CMD_FD(autoresponse) |
|
145 // Usage: autoresponse baseuser-virtuser pass action [autorespmessage] |
|
146 { |
|
147 |
|
148 mystring user = args[0]; |
|
149 mystring pass = args[1]; |
|
150 args[1] = LOG_PASSWORD; |
|
151 mystring action = args[2]; |
|
152 mystring message; |
|
153 if(args.count() == 4) { |
|
154 message = args[3]; |
|
155 args[3] = LOG_MESSAGE; |
|
156 } |
|
157 logcommand(args); |
|
158 |
|
159 pwentry* pw; |
|
160 vpwentry* vpw; |
|
161 OK_RESPONSE(lookup_and_validate(user, pw, vpw, pass, true, true)); |
|
162 |
|
163 const mystring directory = vpw->mailbox + "/" + config->autoresponse_dir(); |
|
164 const mystring filename = directory + "/" + config->autoresponse_file(); |
|
165 const mystring disabled = filename + ".disabled"; |
|
166 |
|
167 if(action == "disable") |
|
168 return autoresponse_disable(filename, disabled); |
|
169 else if(action == "enable") |
|
170 return autoresponse_enable(filename, disabled); |
|
171 else if(action == "read") |
|
172 return autoresponse_read(filename, disabled, fd); |
|
173 else if(action == "write") |
|
174 if(!message) |
|
175 RETURN(bad, "Missing autoresponse message argument"); |
|
176 else |
|
177 return autoresponse_write(directory, filename, disabled, message); |
|
178 else if(action == "delete") |
|
179 return autoresponse_delete(directory); |
|
180 else if(action == "status") |
|
181 return autoresponse_status(directory, filename, disabled); |
|
182 |
|
183 RETURN(err, "Unrecognized command"); |
|
184 } |