main.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. /*
  2. * Server main function
  3. *
  4. * Copyright (C) 1998 Alexandre Julliard
  5. *
  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.
  10. *
  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.
  15. *
  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
  19. */
  20. #include "config.h"
  21. #include <assert.h>
  22. #include <ctype.h>
  23. #include <fcntl.h>
  24. #include <signal.h>
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27. #include <sys/time.h>
  28. #include <unistd.h>
  29. #include "object.h"
  30. #include "file.h"
  31. #include "thread.h"
  32. #include "request.h"
  33. #include "unicode.h"
  34. /* command-line options */
  35. int debug_level = 0;
  36. int foreground = 0;
  37. timeout_t master_socket_timeout = 3 * -TICKS_PER_SEC; /* master socket timeout, default is 3 seconds */
  38. const char *server_argv0;
  39. /* parse-line args */
  40. static void usage( FILE *fh )
  41. {
  42. fprintf(fh, "Usage: %s [options]\n\n", server_argv0);
  43. fprintf(fh, "Options:\n");
  44. fprintf(fh, " -d[n], --debug[=n] set debug level to n or +1 if n not specified\n");
  45. fprintf(fh, " -f, --foreground remain in the foreground for debugging\n");
  46. fprintf(fh, " -h, --help display this help message\n");
  47. fprintf(fh, " -k[n], --kill[=n] kill the current wineserver, optionally with signal n\n");
  48. fprintf(fh, " -p[n], --persistent[=n] make server persistent, optionally for n seconds\n");
  49. fprintf(fh, " -v, --version display version information and exit\n");
  50. fprintf(fh, " -w, --wait wait until the current wineserver terminates\n");
  51. fprintf(fh, "\n");
  52. }
  53. static void option_callback( int optc, char *optarg )
  54. {
  55. int ret;
  56. switch (optc)
  57. {
  58. case 'd':
  59. if (optarg && isdigit(*optarg))
  60. debug_level = atoi( optarg );
  61. else
  62. debug_level++;
  63. break;
  64. case 'f':
  65. foreground = 1;
  66. break;
  67. case 'h':
  68. usage(stdout);
  69. exit(0);
  70. break;
  71. case 'k':
  72. if (optarg && isdigit(*optarg))
  73. ret = kill_lock_owner( atoi( optarg ) );
  74. else
  75. ret = kill_lock_owner(-1);
  76. exit( !ret );
  77. case 'p':
  78. if (optarg && isdigit(*optarg))
  79. master_socket_timeout = (timeout_t)atoi( optarg ) * -TICKS_PER_SEC;
  80. else
  81. master_socket_timeout = TIMEOUT_INFINITE;
  82. break;
  83. case 'v':
  84. fprintf( stderr, "%s\n", PACKAGE_STRING );
  85. exit(0);
  86. case 'w':
  87. wait_for_lock();
  88. exit(0);
  89. }
  90. }
  91. /* command-line option parsing */
  92. /* partly based on the GLibc getopt() implementation */
  93. static struct long_option
  94. {
  95. const char *name;
  96. int has_arg;
  97. int val;
  98. } long_options[] =
  99. {
  100. {"debug", 2, 'd'},
  101. {"foreground", 0, 'f'},
  102. {"help", 0, 'h'},
  103. {"kill", 2, 'k'},
  104. {"persistent", 2, 'p'},
  105. {"version", 0, 'v'},
  106. {"wait", 0, 'w'},
  107. { NULL }
  108. };
  109. static void parse_options( int argc, char **argv, const char *short_opts,
  110. const struct long_option *long_opts, void (*callback)( int, char* ) )
  111. {
  112. const char *flag;
  113. char *start, *end;
  114. int i;
  115. for (i = 1; i < argc; i++)
  116. {
  117. if (argv[i][0] != '-' || !argv[i][1]) /* not an option */
  118. continue;
  119. if (!strcmp( argv[i], "--" ))
  120. break;
  121. start = argv[i] + 1 + (argv[i][1] == '-');
  122. if (argv[i][1] == '-')
  123. {
  124. /* handle long option */
  125. const struct long_option *opt, *found = NULL;
  126. int count = 0;
  127. if (!(end = strchr( start, '=' ))) end = start + strlen(start);
  128. for (opt = long_opts; opt && opt->name; opt++)
  129. {
  130. if (strncmp( opt->name, start, end - start )) continue;
  131. if (!opt->name[end - start]) /* exact match */
  132. {
  133. found = opt;
  134. count = 1;
  135. break;
  136. }
  137. if (!found)
  138. {
  139. found = opt;
  140. count++;
  141. }
  142. else if (found->has_arg != opt->has_arg || found->val != opt->val)
  143. {
  144. count++;
  145. }
  146. }
  147. if (count > 1) goto error;
  148. if (found)
  149. {
  150. if (*end)
  151. {
  152. if (!found->has_arg) goto error;
  153. end++; /* skip '=' */
  154. }
  155. else if (found->has_arg == 1)
  156. {
  157. if (i == argc - 1) goto error;
  158. end = argv[++i];
  159. }
  160. else end = NULL;
  161. callback( found->val, end );
  162. continue;
  163. }
  164. goto error;
  165. }
  166. /* handle short option */
  167. for ( ; *start; start++)
  168. {
  169. if (!(flag = strchr( short_opts, *start ))) goto error;
  170. if (flag[1] == ':')
  171. {
  172. end = start + 1;
  173. if (!*end) end = NULL;
  174. if (flag[2] != ':' && !end)
  175. {
  176. if (i == argc - 1) goto error;
  177. end = argv[++i];
  178. }
  179. callback( *start, end );
  180. break;
  181. }
  182. callback( *start, NULL );
  183. }
  184. }
  185. return;
  186. error:
  187. usage( stderr );
  188. exit(1);
  189. }
  190. static void sigterm_handler( int signum )
  191. {
  192. exit(1); /* make sure atexit functions get called */
  193. }
  194. int main( int argc, char *argv[] )
  195. {
  196. setvbuf( stderr, NULL, _IOLBF, 0 );
  197. server_argv0 = argv[0];
  198. parse_options( argc, argv, "d::fhk::p::vw", long_options, option_callback );
  199. /* setup temporary handlers before the real signal initialization is done */
  200. signal( SIGPIPE, SIG_IGN );
  201. signal( SIGHUP, sigterm_handler );
  202. signal( SIGINT, sigterm_handler );
  203. signal( SIGQUIT, sigterm_handler );
  204. signal( SIGTERM, sigterm_handler );
  205. signal( SIGABRT, sigterm_handler );
  206. sock_init();
  207. open_master_socket();
  208. if (debug_level) fprintf( stderr, "wineserver: starting (pid=%ld)\n", (long) getpid() );
  209. set_current_time();
  210. init_signals();
  211. init_directories( load_intl_file() );
  212. init_registry();
  213. main_loop();
  214. return 0;
  215. }