2 * rs-serve - (c) 2013 Niklas E. Cathor
4 * This program is distributed in the hope that it will be useful,
5 * but WITHOUT ANY WARRANTY; without even the implied warranty of
6 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7 * GNU Affero General Public License for more details.
9 * You should have received a copy of the GNU Affero General Public License
10 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 static void print_help(const char *progname) {
17 "Usage: %s [options]\n"
20 " -h | --help - Display this text and exit.\n"
21 " -v | --version - Print program version and exit.\n"
22 " -p <port> | --port=<port> - Bind to given port (default: 80).\n"
23 " -n <name> | --hostname=<name> - Set hostname (defaults to local.dev).\n"
24 " -f <file> | --log-file=<file> - Log to given file (defaults to stdout)\n"
25 " -d | --detach - After starting the server, detach server\n"
26 " process and exit. If you don't use this in\n"
27 " combination with the --log-file option, all\n"
28 " future output will be lost.\n"
29 " --dir=<directory-name> - Name of the directory relative to the user's\n"
30 " home directory to serve data from.\n"
31 " Defaults to: remotestorage\n"
32 " --static=<directory> - Directory from which to serve static files.\n"
33 " Defaults to: /var/www/krsd\n"
34 " --pid-file=<file> - Write PID to given file.\n"
35 " --stop - Stop a running rs-serve process. The process\n"
36 " is identified by the PID file specified via\n"
37 " the --pid-file option. NOTE: the --stop option\n"
38 " MUST precede the --pid-file option on the\n"
39 " command line for this to work.\n"
40 " --debug - Enable debug output.\n"
42 " --auth-uri=<uri-template> - URI of the OAuth2 endpoint. Required for webfinger.\n"
44 " --experimental - Enable experimental features\n"
45 " --ssl - Enable SSL.\n"
46 " --cert-path=<path> - Set path to SSL certificate file.\n"
47 " --key-path=<path> - Set path to SSL key file.\n"
48 " --ca-path=<path> - Set path to SSL CA file.\n"
49 " --no-xattr - Don't store meta information in extended attributes.\n"
50 " They will be stored in a separate Berkeley Database\n"
51 " instead. Use this option if your filesystem does not\n"
52 " support extended attributes or you don't want to use\n"
53 " them. (NOT IMPLEMENTED)\n"
55 "This program is distributed in the hope that it will be useful,\n"
56 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
57 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
58 "GNU Affero General Public License for more details.\n"
59 "(c) 2013 Niklas E. Cathor\n\n"
63 static void print_version() {
64 fprintf(stderr, "rs-serve %d.%d%s\n", RS_VERSION_MAJOR, RS_VERSION_MINOR, RS_VERSION_POSTFIX);
68 char *rs_scheme = "http";
69 char *rs_hostname = "local.dev";
71 FILE *rs_log_file = NULL;
72 FILE *rs_pid_file = NULL;
73 char *rs_pid_file_path = NULL;
74 char *rs_home_serve_root = NULL;
75 int rs_home_serve_root_len = 0;
76 char *rs_static_dir = NULL;
77 int rs_static_dir_len = 0;
78 int rs_stop_other = 0;
79 char *rs_auth_uri = NULL;
80 int rs_auth_uri_len = 0;
81 int rs_webfinger_enabled = 1;
82 int rs_experimental = 0;
84 char *rs_ssl_cert_path = NULL;
85 char *rs_ssl_key_path = NULL;
86 char *rs_ssl_ca_path = NULL;
89 void (*current_log_debug)(const char *file, int line, char *format, ...) = NULL;
91 static struct option long_options[] = {
92 { "port", required_argument, 0, 'p' },
93 { "hostname", required_argument, 0, 'n' },
94 { "dir", required_argument, 0, 0 },
95 { "pid-file", required_argument, 0, 0 },
96 { "stop", no_argument, 0, 0 },
97 { "log-file", required_argument, 0, 'f' },
98 { "debug", no_argument, 0, 0 },
99 { "detach", no_argument, 0, 'd' },
100 { "help", no_argument, 0, 'h' },
101 { "version", no_argument, 0, 'v' },
102 { "static", required_argument, 0, 0 },
104 { "auth-uri", required_argument, 0, 0 },
106 { "experimental", no_argument, 0, 0 },
107 { "ssl", no_argument, 0, 0 },
108 { "cert-path", required_argument, 0, 0 },
109 { "key-path", required_argument, 0, 0 },
110 { "ca-path", required_argument, 0, 0 },
111 { "no-xattr", no_argument, 0, 0 },
115 void close_pid_file() {
117 unlink(RS_PID_FILE_PATH);
120 void init_config(int argc, char **argv) {
124 opt = getopt_long(argc, argv, "p:n:r:f:dhv", long_options, &opt_index);
128 } else if(opt == -1) {
131 } else if(opt == 'p') {
132 rs_port = atoi(optarg);
133 } else if(opt == 'n') {
134 rs_hostname = optarg;
135 } else if(opt == 'f') {
136 rs_log_file = fopen(optarg, "a");
137 if(rs_log_file == NULL) {
138 perror("Failed to open log file");
141 } else if(opt == 'd') {
143 } else if(opt == 'h') {
146 } else if(opt == 'v') {
149 } else if(opt == 0) {
151 const char *arg_name = long_options[opt_index].name;
153 // long option with no short equivalent
154 if(strcmp(arg_name, "pid-file") == 0) { // --pid-file
155 rs_pid_file_path = optarg;
157 // stop was requested, kill other process by pid-file
159 rs_pid_file = fopen(rs_pid_file_path, "r");
160 if(rs_pid_file == NULL) {
161 perror("Failed to open pid file for reading");
165 fscanf(rs_pid_file, "%d", &pid);
166 if(kill(pid, SIGTERM) == 0) {
167 printf("Sent SIGTERM to process %d\n", pid);
170 fprintf(stderr, "Sending SIGTERM to process %d failed: %s\n", pid, strerror(errno));
175 // open pid file (process/main stores our pid there)
176 rs_pid_file = fopen(rs_pid_file_path, "wx");
177 if(rs_pid_file == NULL) {
178 perror("Failed to open pid file");
181 atexit(close_pid_file);
182 } else if(strcmp(arg_name, "stop") == 0) { // --stop
184 } else if(strcmp(arg_name, "debug") == 0) { // --debug
185 current_log_debug = do_log_debug;
186 } else if(strcmp(arg_name, "dir") == 0) { // --dir=<dirname>
187 rs_home_serve_root = optarg;
188 int len = strlen(rs_home_serve_root);
189 if(rs_home_serve_root[len - 1] == '/') {
190 // strip trailing slash.
191 rs_home_serve_root[--len] = 0;
193 rs_home_serve_root_len = len;
194 } else if(strcmp(arg_name, "static") == 0) { // --static=<dirname>
195 rs_static_dir = optarg;
196 int len = strlen(rs_static_dir);
197 if(rs_static_dir[len - 1] == '/') {
198 // strip trailing slash.
199 rs_static_dir[--len] = 0;
203 } else if(strcmp(arg_name, "auth-uri") == 0) { // --auth-uri=<uri-template>
204 rs_auth_uri = optarg;
205 rs_auth_uri_len = strlen(rs_auth_uri);
207 } else if(strcmp(arg_name, "experimental") == 0) { // --experimental
209 } else if(strcmp(arg_name, "ssl") == 0) { // --ssl
212 } else if(strcmp(arg_name, "cert-path") == 0) { // --cert-path
213 rs_ssl_cert_path = optarg;
214 } else if(strcmp(arg_name, "key-path") == 0) { // --key-path
215 rs_ssl_key_path = optarg;
216 } else if(strcmp(arg_name, "ca-path") == 0) { // --ca-path
217 rs_ssl_ca_path = optarg;
218 } else if(strcmp(arg_name, "no-xattr") == 0) { // --no-xattr
224 if(rs_home_serve_root == NULL) {
225 rs_home_serve_root = "remotestorage";
226 rs_home_serve_root_len = 13;
229 if(rs_static_dir == NULL) {
230 rs_static_dir = "/var/www/krsd";
231 rs_static_dir_len = 13;
235 fprintf(stderr, "ERROR: can't stop existing process without --pid-file option.\n");
239 if(current_log_debug == NULL) {
240 current_log_debug = dont_log_debug;
243 if(rs_log_file == NULL) {
244 rs_log_file = stdout;
248 if(RS_SSL_CERT_PATH == NULL || RS_SSL_KEY_PATH == NULL) {
249 log_error("You need to specify at least --cert-path and --key-path options to enable SSL");
258 if(rs_experimental) {
259 log_info("Experimental features enabled");
261 log_info("Running in strict mode");
265 if(rs_auth_uri == NULL) {
266 log_warn("No --auth-uri set, won't be able to do webfinger!");
267 rs_webfinger_enabled = 0;
273 void cleanup_config() {