ntdll: Add RtlDosPathNameToRelativeNtPathName_U.
[wine.git] / server / main.c
blob4021d55d52ca7651ae1429cc4a05f404db36712a
1 /*
2 * Server main function
4 * Copyright (C) 1998 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "config.h"
23 #include <assert.h>
24 #include <ctype.h>
25 #include <fcntl.h>
26 #include <signal.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <sys/time.h>
30 #include <unistd.h>
32 #include "object.h"
33 #include "file.h"
34 #include "thread.h"
35 #include "request.h"
36 #include "unicode.h"
38 /* command-line options */
39 int debug_level = 0;
40 int foreground = 0;
41 timeout_t master_socket_timeout = 3 * -TICKS_PER_SEC; /* master socket timeout, default is 3 seconds */
42 const char *server_argv0;
44 /* parse-line args */
46 static void usage( FILE *fh )
48 fprintf(fh, "Usage: %s [options]\n\n", server_argv0);
49 fprintf(fh, "Options:\n");
50 fprintf(fh, " -d[n], --debug[=n] set debug level to n or +1 if n not specified\n");
51 fprintf(fh, " -f, --foreground remain in the foreground for debugging\n");
52 fprintf(fh, " -h, --help display this help message\n");
53 fprintf(fh, " -k[n], --kill[=n] kill the current wineserver, optionally with signal n\n");
54 fprintf(fh, " -p[n], --persistent[=n] make server persistent, optionally for n seconds\n");
55 fprintf(fh, " -v, --version display version information and exit\n");
56 fprintf(fh, " -w, --wait wait until the current wineserver terminates\n");
57 fprintf(fh, "\n");
60 static void option_callback( int optc, char *optarg )
62 int ret;
64 switch (optc)
66 case 'd':
67 if (optarg && isdigit(*optarg))
68 debug_level = atoi( optarg );
69 else
70 debug_level++;
71 break;
72 case 'f':
73 foreground = 1;
74 break;
75 case 'h':
76 usage(stdout);
77 exit(0);
78 break;
79 case 'k':
80 if (optarg && isdigit(*optarg))
81 ret = kill_lock_owner( atoi( optarg ) );
82 else
83 ret = kill_lock_owner(-1);
84 exit( !ret );
85 case 'p':
86 if (optarg && isdigit(*optarg))
87 master_socket_timeout = (timeout_t)atoi( optarg ) * -TICKS_PER_SEC;
88 else
89 master_socket_timeout = TIMEOUT_INFINITE;
90 break;
91 case 'v':
92 fprintf( stderr, "%s\n", PACKAGE_STRING );
93 exit(0);
94 case 'w':
95 wait_for_lock();
96 exit(0);
100 /* command-line option parsing */
101 /* partly based on the GLibc getopt() implementation */
103 static struct long_option
105 const char *name;
106 int has_arg;
107 int val;
108 } long_options[] =
110 {"debug", 2, 'd'},
111 {"foreground", 0, 'f'},
112 {"help", 0, 'h'},
113 {"kill", 2, 'k'},
114 {"persistent", 2, 'p'},
115 {"version", 0, 'v'},
116 {"wait", 0, 'w'},
117 { NULL }
120 static void parse_options( int argc, char **argv, const char *short_opts,
121 const struct long_option *long_opts, void (*callback)( int, char* ) )
123 const char *flag;
124 char *start, *end;
125 int i;
127 for (i = 1; i < argc; i++)
129 if (argv[i][0] != '-' || !argv[i][1]) /* not an option */
130 continue;
131 if (!strcmp( argv[i], "--" ))
132 break;
133 start = argv[i] + 1 + (argv[i][1] == '-');
135 if (argv[i][1] == '-')
137 /* handle long option */
138 const struct long_option *opt, *found = NULL;
139 int count = 0;
141 if (!(end = strchr( start, '=' ))) end = start + strlen(start);
142 for (opt = long_opts; opt && opt->name; opt++)
144 if (strncmp( opt->name, start, end - start )) continue;
145 if (!opt->name[end - start]) /* exact match */
147 found = opt;
148 count = 1;
149 break;
151 if (!found)
153 found = opt;
154 count++;
156 else if (found->has_arg != opt->has_arg || found->val != opt->val)
158 count++;
162 if (count > 1) goto error;
164 if (found)
166 if (*end)
168 if (!found->has_arg) goto error;
169 end++; /* skip '=' */
171 else if (found->has_arg == 1)
173 if (i == argc - 1) goto error;
174 end = argv[++i];
176 else end = NULL;
178 callback( found->val, end );
179 continue;
181 goto error;
184 /* handle short option */
185 for ( ; *start; start++)
187 if (!(flag = strchr( short_opts, *start ))) goto error;
188 if (flag[1] == ':')
190 end = start + 1;
191 if (!*end) end = NULL;
192 if (flag[2] != ':' && !end)
194 if (i == argc - 1) goto error;
195 end = argv[++i];
197 callback( *start, end );
198 break;
200 callback( *start, NULL );
203 return;
205 error:
206 usage( stderr );
207 exit(1);
210 static void sigterm_handler( int signum )
212 exit(1); /* make sure atexit functions get called */
215 int main( int argc, char *argv[] )
217 setvbuf( stderr, NULL, _IOLBF, 0 );
218 server_argv0 = argv[0];
219 parse_options( argc, argv, "d::fhk::p::vw", long_options, option_callback );
221 /* setup temporary handlers before the real signal initialization is done */
222 signal( SIGPIPE, SIG_IGN );
223 signal( SIGHUP, sigterm_handler );
224 signal( SIGINT, sigterm_handler );
225 signal( SIGQUIT, sigterm_handler );
226 signal( SIGTERM, sigterm_handler );
227 signal( SIGABRT, sigterm_handler );
229 sock_init();
230 open_master_socket();
232 if (debug_level) fprintf( stderr, "wineserver: starting (pid=%ld)\n", (long) getpid() );
233 set_current_time();
234 init_signals();
235 init_directories( load_intl_file() );
236 init_registry();
237 main_loop();
238 return 0;