You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

751 lines
16 KiB

Bug #15327: configure: --with-tcp-port option being partially ignored make sure that if builder configured with a non-standard (!= 3306) default TCP port that value actually gets used throughout. if they didn't configure a value, assume "use a sensible default", which will be read from /etc/services or, failing that, from the factory default. That makes the order of preference - command-line option - my.cnf, where applicable - $MYSQL_TCP_PORT environment variable - /etc/services (unless configured --with-tcp-port) - default port (--with-tcp-port=... or factory default) client/mysql.cc: Bug #15327: configure: --with-tcp-port option being partially ignored make help on --port a little more clear client/mysql_upgrade.c: Bug #15327: configure: --with-tcp-port option being partially ignored make help on --port a little more clear client/mysqladmin.cc: Bug #15327: configure: --with-tcp-port option being partially ignored make help on --port a little more clear client/mysqlbinlog.cc: Bug #15327: configure: --with-tcp-port option being partially ignored make help on --port a little more clear client/mysqlcheck.c: Bug #15327: configure: --with-tcp-port option being partially ignored make help on --port a little more clear client/mysqldump.c: Bug #15327: configure: --with-tcp-port option being partially ignored make help on --port a little more clear client/mysqlimport.c: Bug #15327: configure: --with-tcp-port option being partially ignored make help on --port a little more clear client/mysqlmanagerc.c: Bug #15327: configure: --with-tcp-port option being partially ignored make help on --port a little more clear configure.in: Bug #15327: configure: --with-tcp-port option being partially ignored If MYSQL_TCP_PORT defaulted in configure (factory default 3306 at the time of this writing), set MYSQL_TCP_PORT to factory default, then clear factory default after. That way, we lose no information, and we can distinguish between "defaulted" and the pathological case "builder specifically configured a port that coincides with factory default." This can in theory happen if builder configures and builds several servers from a script (--with-tcp-port=3306, --with-tcp-port=3316, --with-tcp-port=3326). Not all that probable, but much preferable to having more "magic" happen in the server when we can solve this without any guesswork. client/mysqlshow.c: Bug #15327: configure: --with-tcp-port option being partially ignored make help on --port a little more clear client/mysqltest.c: Bug #15327: configure: --with-tcp-port option being partially ignored make help on --port a little more clear include/mysql_version.h.in: Bug #15327: configure: --with-tcp-port option being partially ignored make factory default for TCP port available as MYSQL_PORT_DEFAULT if build-time configured with a different default. (0 if unchanged) libmysql/libmysql.c: Bug #15327: configure: --with-tcp-port option being partially ignored initialize default tcp port for client, like so: - if user configured --with-tcp-port, use that value as default - otherwise assume "use a good default": search mysqld/tcp in /etc/services; if that doesn't exist, use factory default (3306) - environment variable MYSQL_TCP_PORT overrides this default - command-line option overrides all of the above mysql-test/Makefile.am: Bug #15327: configure: --with-tcp-port option being partially ignored make factory default for TCP port available as MYSQL_TCP_PORT_DEFAULT if build-time configured with a different default. (0 if unchanged) mysql-test/mysql-test-run-shell.sh: Bug #15327: configure: --with-tcp-port option being partially ignored set up MYSQL_TCP_PORT if not already set in environment: - if user configured --with-tcp-port, use that value as default - otherwise assume "use a good default": search mysqld/tcp in /etc/services; if that doesn't exist, use factory default (3306) netware/mysql_test_run.c: Bug #15327: configure: --with-tcp-port option being partially ignored account for non-standard default port-no. configured at build-time netware/mysqld_safe.c: Bug #15327: configure: --with-tcp-port option being partially ignored account for non-standard default port-no. configured at build-time scripts/Makefile.am: Bug #15327: configure: --with-tcp-port option being partially ignored make factory default for TCP port available as MYSQL_TCP_PORT_DEFAULT if build-time configured with a different default. (0 if unchanged) scripts/mysql_config.sh: Bug #15327: configure: --with-tcp-port option being partially ignored set up MYSQL_TCP_PORT if not already set in environment: - if user configured --with-tcp-port, use that value as default - otherwise assume "use a good default": search mysqld/tcp in /etc/services; if that doesn't exist, use factory default (3306) scripts/mysql_fix_privilege_tables.sh: Bug #15327: configure: --with-tcp-port option being partially ignored clarifying notice only scripts/mysqld_safe-watch.sh: Bug #15327: configure: --with-tcp-port option being partially ignored account for non-standard default port-no. configured at build-time server-tools/instance-manager/priv.h: Bug #15327: configure: --with-tcp-port option being partially ignored account for non-standard default port-no. configured at build-time sql/mysqld.cc: Bug #15327: configure: --with-tcp-port option being partially ignored if builder specifically requested a default port, use that (even if it coincides with our factory default). only if they didn't do we check /etc/services (and, failing on that, fall back to the factory default of 3306). either default can be overridden by the environment variable MYSQL_TCP_PORT, which in turn can be overridden with command line options. tests/mysql_client_test.c: Bug #15327: configure: --with-tcp-port option being partially ignored make help on --port a little more clear tests/ssl_test.c: Bug #15327: configure: --with-tcp-port option being partially ignored account for non-standard default port-no. configured at build-time tests/thread_test.c: Bug #15327: configure: --with-tcp-port option being partially ignored make help on --port a little more clear
18 years ago
  1. /*
  2. Copyright (c) 2003 Novell, Inc. All Rights Reserved.
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 2 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  14. */
  15. #include <stdlib.h>
  16. #include <stdio.h>
  17. #include <netdb.h>
  18. #include <sys/stat.h>
  19. #include <monitor.h>
  20. #include <strings.h>
  21. #include <getopt.h>
  22. #include <screen.h>
  23. #include <dirent.h>
  24. #include "my_config.h"
  25. #include "my_manage.h"
  26. #include "mysql_version.h"
  27. /******************************************************************************
  28. global variables
  29. ******************************************************************************/
  30. char autoclose;
  31. char basedir[PATH_MAX];
  32. char checktables;
  33. char datadir[PATH_MAX];
  34. char pid_file[PATH_MAX];
  35. char address[PATH_MAX];
  36. char port[PATH_MAX];
  37. char err_log[PATH_MAX];
  38. char safe_log[PATH_MAX];
  39. char mysqld[PATH_MAX];
  40. char hostname[PATH_MAX];
  41. char default_option[PATH_MAX];
  42. FILE *log_fd= NULL;
  43. /******************************************************************************
  44. prototypes
  45. ******************************************************************************/
  46. void usage(void);
  47. void vlog(char *, va_list);
  48. void log(char *, ...);
  49. void start_defaults(int, char *[]);
  50. void finish_defaults();
  51. void read_defaults(arg_list_t *);
  52. void parse_args(int, char *[]);
  53. void get_options(int, char *[]);
  54. void check_data_vol();
  55. void check_setup();
  56. void check_tables();
  57. void mysql_start(int, char *[]);
  58. void parse_setvar(char *arg);
  59. /******************************************************************************
  60. functions
  61. ******************************************************************************/
  62. /******************************************************************************
  63. usage()
  64. Show usage.
  65. ******************************************************************************/
  66. void usage(void)
  67. {
  68. // keep the screen up
  69. setscreenmode(SCR_NO_MODE);
  70. puts("\
  71. \n\
  72. usage: mysqld_safe [options]\n\
  73. \n\
  74. Program to start the MySQL daemon and restart it if it dies unexpectedly.\n\
  75. All options, besides those listed below, are passed on to the MySQL daemon.\n\
  76. \n\
  77. options:\n\
  78. \n\
  79. --autoclose Automatically close the mysqld_safe screen.\n\
  80. \n\
  81. --check-tables Check the tables before starting the MySQL daemon.\n\
  82. \n\
  83. --err-log=<file> Send the MySQL daemon error output to <file>.\n\
  84. \n\
  85. --help Show this help information.\n\
  86. \n\
  87. --mysqld=<file> Use the <file> MySQL daemon.\n\
  88. \n\
  89. ");
  90. exit(-1);
  91. }
  92. /******************************************************************************
  93. vlog()
  94. Log the message.
  95. ******************************************************************************/
  96. void vlog(char *format, va_list ap)
  97. {
  98. vfprintf(stdout, format, ap);
  99. fflush(stdout);
  100. if (log_fd)
  101. {
  102. vfprintf(log_fd, format, ap);
  103. fflush(log_fd);
  104. }
  105. }
  106. /******************************************************************************
  107. log()
  108. Log the message.
  109. ******************************************************************************/
  110. void log(char *format, ...)
  111. {
  112. va_list ap;
  113. va_start(ap, format);
  114. vlog(format, ap);
  115. va_end(ap);
  116. }
  117. /******************************************************************************
  118. start_defaults()
  119. Start setting the defaults.
  120. ******************************************************************************/
  121. void start_defaults(int argc, char *argv[])
  122. {
  123. struct stat buf;
  124. int i;
  125. // default options
  126. static char *default_options[]=
  127. {
  128. "--no-defaults",
  129. "--defaults-file=",
  130. "--defaults-extra-file=",
  131. NULL
  132. };
  133. // autoclose
  134. autoclose= FALSE;
  135. // basedir
  136. get_basedir(argv[0], basedir);
  137. // check-tables
  138. checktables= FALSE;
  139. // hostname
  140. if (gethostname(hostname, PATH_MAX) < 0)
  141. {
  142. // default
  143. strcpy(hostname, "mysql");
  144. }
  145. // address
  146. snprintf(address, PATH_MAX, "0.0.0.0");
  147. // port
  148. snprintf(port, PATH_MAX, "%d", MYSQL_PORT);
  149. // default option
  150. default_option[0]= NULL;
  151. for (i= 0; (argc > 1) && default_options[i]; i++)
  152. {
  153. if (!strnicmp(argv[1], default_options[i], strlen(default_options[i])))
  154. {
  155. strncpy(default_option, argv[1], PATH_MAX);
  156. break;
  157. }
  158. }
  159. // set after basedir is established
  160. datadir[0]= NULL;
  161. pid_file[0]= NULL;
  162. err_log[0]= NULL;
  163. safe_log[0]= NULL;
  164. mysqld[0]= NULL;
  165. }
  166. /******************************************************************************
  167. finish_defaults()
  168. Finish settig the defaults.
  169. ******************************************************************************/
  170. void finish_defaults()
  171. {
  172. struct stat buf;
  173. int i;
  174. // datadir
  175. if (!datadir[0])
  176. snprintf(datadir, PATH_MAX, "%s/data", basedir);
  177. // pid-file
  178. if (!pid_file[0])
  179. snprintf(pid_file, PATH_MAX, "%s/%s.pid", datadir, hostname);
  180. // err-log
  181. if (!err_log[0])
  182. snprintf(err_log, PATH_MAX, "%s/%s.err", datadir, hostname);
  183. // safe-log
  184. if (!safe_log[0])
  185. snprintf(safe_log, PATH_MAX, "%s/%s.safe", datadir, hostname);
  186. // mysqld
  187. if (!mysqld[0])
  188. snprintf(mysqld, PATH_MAX, "%s/bin/mysqld-max", basedir);
  189. if (stat(mysqld, &buf))
  190. {
  191. snprintf(mysqld, PATH_MAX, "%s/bin/mysqld", basedir);
  192. }
  193. }
  194. /******************************************************************************
  195. read_defaults()
  196. Read the defaults.
  197. ******************************************************************************/
  198. void read_defaults(arg_list_t *pal)
  199. {
  200. arg_list_t al;
  201. char defaults_file[PATH_MAX];
  202. char mydefaults[PATH_MAX];
  203. char line[PATH_MAX];
  204. FILE *fp;
  205. // defaults output file
  206. snprintf(defaults_file, PATH_MAX, "%s/bin/defaults.out", basedir);
  207. remove(defaults_file);
  208. // mysqladmin file
  209. snprintf(mydefaults, PATH_MAX, "%s/bin/my_print_defaults", basedir);
  210. // args
  211. init_args(&al);
  212. add_arg(&al, mydefaults);
  213. if (default_option[0])
  214. add_arg(&al, default_option);
  215. add_arg(&al, "mysqld");
  216. add_arg(&al, "server");
  217. add_arg(&al, "mysqld_safe");
  218. add_arg(&al, "safe_mysqld");
  219. spawn(mydefaults, &al, TRUE, NULL, defaults_file, NULL);
  220. free_args(&al);
  221. // gather defaults
  222. if ((fp= fopen(defaults_file, "r")) != NULL)
  223. {
  224. while (fgets(line, PATH_MAX, fp))
  225. {
  226. char *p;
  227. // remove end-of-line character
  228. if ((p= strrchr(line, '\n')) != NULL)
  229. *p= '\0';
  230. // add the option as an argument
  231. add_arg(pal, line);
  232. }
  233. fclose(fp);
  234. }
  235. // remove file
  236. remove(defaults_file);
  237. }
  238. /******************************************************************************
  239. parse_args()
  240. Get the options.
  241. ******************************************************************************/
  242. void parse_args(int argc, char *argv[])
  243. {
  244. int index= 0;
  245. int c;
  246. // parse options
  247. enum opts
  248. {
  249. OPT_BASEDIR= 0xFF,
  250. OPT_DATADIR,
  251. OPT_PID_FILE,
  252. OPT_BIND_ADDRESS,
  253. OPT_PORT,
  254. OPT_ERR_LOG,
  255. OPT_SAFE_LOG,
  256. OPT_MYSQLD,
  257. OPT_HELP,
  258. OPT_SETVAR
  259. };
  260. static struct option options[]=
  261. {
  262. {"autoclose", no_argument, &autoclose, TRUE},
  263. {"basedir", required_argument, 0, OPT_BASEDIR},
  264. {"check-tables", no_argument, &checktables, TRUE},
  265. {"datadir", required_argument, 0, OPT_DATADIR},
  266. {"pid-file", required_argument, 0, OPT_PID_FILE},
  267. {"bind-address", required_argument, 0, OPT_BIND_ADDRESS},
  268. {"port", required_argument, 0, OPT_PORT},
  269. {"err-log", required_argument, 0, OPT_ERR_LOG},
  270. {"safe-log", required_argument, 0, OPT_SAFE_LOG},
  271. {"mysqld", required_argument, 0, OPT_MYSQLD},
  272. {"help", no_argument, 0, OPT_HELP},
  273. {"set-variable", required_argument, 0, OPT_SETVAR},
  274. {0, 0, 0, 0}
  275. };
  276. // we have to reset getopt_long because we use it multiple times
  277. optind= 1;
  278. // turn off error reporting
  279. opterr= 0;
  280. while ((c= getopt_long(argc, argv, "b:h:P:", options, &index)) >= 0)
  281. {
  282. switch (c) {
  283. case OPT_BASEDIR:
  284. case 'b':
  285. strcpy(basedir, optarg);
  286. break;
  287. case OPT_DATADIR:
  288. case 'h':
  289. strcpy(datadir, optarg);
  290. break;
  291. case OPT_PID_FILE:
  292. strcpy(pid_file, optarg);
  293. break;
  294. case OPT_BIND_ADDRESS:
  295. strcpy(address, optarg);
  296. break;
  297. case OPT_PORT:
  298. case 'P':
  299. strcpy(port, optarg);
  300. break;
  301. case OPT_ERR_LOG:
  302. strcpy(err_log, optarg);
  303. break;
  304. case OPT_SAFE_LOG:
  305. strcpy(safe_log, optarg);
  306. break;
  307. case OPT_MYSQLD:
  308. strcpy(mysqld, optarg);
  309. break;
  310. case OPT_SETVAR:
  311. parse_setvar(optarg);
  312. break;
  313. case OPT_HELP:
  314. usage();
  315. break;
  316. default:
  317. // ignore
  318. break;
  319. }
  320. }
  321. }
  322. /*
  323. parse_setvar(char *arg)
  324. Pasrsing for port just to display the port num on the mysqld_safe screen
  325. */
  326. void parse_setvar(char *arg)
  327. {
  328. char *pos;
  329. if ((pos= strindex(arg, "port")))
  330. {
  331. for (; *pos && *pos != '='; pos++);
  332. if (*pos)
  333. strcpy(port, pos + 1);
  334. }
  335. }
  336. /******************************************************************************
  337. /******************************************************************************
  338. get_options()
  339. Get the options.
  340. ******************************************************************************/
  341. void get_options(int argc, char *argv[])
  342. {
  343. arg_list_t al;
  344. // start defaults
  345. start_defaults(argc, argv);
  346. // default file arguments
  347. init_args(&al);
  348. add_arg(&al, "ignore");
  349. read_defaults(&al);
  350. parse_args(al.argc, al.argv);
  351. free_args(&al);
  352. // command-line arguments
  353. parse_args(argc, argv);
  354. // finish defaults
  355. finish_defaults();
  356. }
  357. /******************************************************************************
  358. check_data_vol()
  359. Check the database volume.
  360. ******************************************************************************/
  361. void check_data_vol()
  362. {
  363. // warn if the data is on a Traditional volume
  364. struct volume_info vol;
  365. char buff[PATH_MAX];
  366. char *p;
  367. // clear struct
  368. memset(&vol, 0, sizeof(vol));
  369. // find volume name
  370. strcpy(buff, datadir);
  371. if (p= strchr(buff, ':'))
  372. {
  373. // terminate after volume name
  374. *p= 0;
  375. }
  376. else
  377. {
  378. // assume SYS volume
  379. strcpy(buff, "SYS");
  380. }
  381. // retrieve information
  382. netware_vol_info_from_name(&vol, buff);
  383. if ((vol.flags & VOL_NSS_PRESENT) == 0)
  384. {
  385. log("Error: Either the data directory does not exist or is not on an NSS volume!\n\n");
  386. exit(-1);
  387. }
  388. }
  389. /******************************************************************************
  390. check_setup()
  391. Check the current setup.
  392. ******************************************************************************/
  393. void check_setup()
  394. {
  395. struct stat info;
  396. char temp[PATH_MAX];
  397. // remove any current pid_file
  398. if (!stat(pid_file, &info) && (remove(pid_file) < 0))
  399. {
  400. log("ERROR: Unable to remove current pid file!\n\n");
  401. exit(-1);
  402. }
  403. // check the data volume
  404. check_data_vol();
  405. // check for a database
  406. snprintf(temp, PATH_MAX, "%s/mysql/host.frm", datadir);
  407. if (stat(temp, &info))
  408. {
  409. log("ERROR: No database found in the data directory!\n\n");
  410. exit(-1);
  411. }
  412. }
  413. /******************************************************************************
  414. check_tables()
  415. Check the database tables.
  416. ******************************************************************************/
  417. void check_tables()
  418. {
  419. arg_list_t al;
  420. char mycheck[PATH_MAX];
  421. char table[PATH_MAX];
  422. char db[PATH_MAX];
  423. DIR *datadir_entry, *db_entry, *table_entry;
  424. // status
  425. log("checking tables...\n");
  426. // list databases
  427. if ((datadir_entry= opendir(datadir)) == NULL)
  428. {
  429. return;
  430. }
  431. while ((db_entry= readdir(datadir_entry)) != NULL)
  432. {
  433. if (db_entry->d_name[0] == '.')
  434. {
  435. // Skip
  436. }
  437. else if (S_ISDIR(db_entry->d_type))
  438. {
  439. // create long db name
  440. snprintf(db, PATH_MAX, "%s/%s", datadir, db_entry->d_name);
  441. // list tables
  442. if ((db_entry= opendir(db)) == NULL)
  443. {
  444. continue;
  445. }
  446. while ((table_entry= readdir(db_entry)) != NULL)
  447. {
  448. // create long table name
  449. snprintf(table, PATH_MAX, "%s/%s", db, strlwr(table_entry->d_name));
  450. if (strindex(table, ".myi"))
  451. {
  452. // ** myisamchk
  453. // mysqladmin file
  454. snprintf(mycheck, PATH_MAX, "%s/bin/myisamchk", basedir);
  455. // args
  456. init_args(&al);
  457. add_arg(&al, mycheck);
  458. add_arg(&al, "--silent");
  459. add_arg(&al, "--force");
  460. add_arg(&al, "--fast");
  461. add_arg(&al, "--medium-check");
  462. add_arg(&al, "-O");
  463. add_arg(&al, "key_buffer=64M");
  464. add_arg(&al, "-O");
  465. add_arg(&al, "sort_buffer=64M");
  466. add_arg(&al, table);
  467. spawn(mycheck, &al, TRUE, NULL, NULL, NULL);
  468. free_args(&al);
  469. }
  470. else if (strindex(table, ".ism"))
  471. {
  472. // ** isamchk
  473. // mysqladmin file
  474. snprintf(mycheck, PATH_MAX, "%s/bin/isamchk", basedir);
  475. // args
  476. init_args(&al);
  477. add_arg(&al, mycheck);
  478. add_arg(&al, "--silent");
  479. add_arg(&al, "--force");
  480. add_arg(&al, "-O");
  481. add_arg(&al, "sort_buffer=64M");
  482. add_arg(&al, table);
  483. spawn(mycheck, &al, TRUE, NULL, NULL, NULL);
  484. free_args(&al);
  485. }
  486. }
  487. }
  488. }
  489. }
  490. /******************************************************************************
  491. mysql_start()
  492. Start the mysql server.
  493. ******************************************************************************/
  494. void mysql_start(int argc, char *argv[])
  495. {
  496. arg_list_t al;
  497. int i, j, err;
  498. struct stat info;
  499. time_t cal;
  500. struct tm lt;
  501. char stamp[PATH_MAX];
  502. char skip;
  503. // private options
  504. static char *private_options[]=
  505. {
  506. "--autoclose",
  507. "--check-tables",
  508. "--help",
  509. "--err-log=",
  510. "--mysqld=",
  511. NULL
  512. };
  513. // args
  514. init_args(&al);
  515. add_arg(&al, "%s", mysqld);
  516. // parent args
  517. for (i= 1; i < argc; i++)
  518. {
  519. skip= FALSE;
  520. // skip private arguments
  521. for (j= 0; private_options[j]; j++)
  522. {
  523. if (!strnicmp(argv[i], private_options[j], strlen(private_options[j])))
  524. {
  525. skip= TRUE;
  526. break;
  527. }
  528. }
  529. if (!skip)
  530. {
  531. add_arg(&al, "%s", argv[i]);
  532. }
  533. }
  534. // spawn
  535. do
  536. {
  537. // check the database tables
  538. if (checktables)
  539. check_tables();
  540. // status
  541. time(&cal);
  542. localtime_r(&cal, &lt);
  543. strftime(stamp, PATH_MAX, "%d %b %Y %H:%M:%S", &lt);
  544. log("mysql started : %s\n", stamp);
  545. // spawn mysqld
  546. spawn(mysqld, &al, TRUE, NULL, NULL, err_log);
  547. }
  548. while (!stat(pid_file, &info));
  549. // status
  550. time(&cal);
  551. localtime_r(&cal, &lt);
  552. strftime(stamp, PATH_MAX, "%d %b %Y %H:%M:%S", &lt);
  553. log("mysql stopped : %s\n\n", stamp);
  554. // free args
  555. free_args(&al);
  556. }
  557. /******************************************************************************
  558. main()
  559. ******************************************************************************/
  560. int main(int argc, char **argv)
  561. {
  562. char temp[PATH_MAX];
  563. // get the options
  564. get_options(argc, argv);
  565. // keep the screen up
  566. if (!autoclose)
  567. setscreenmode(SCR_NO_MODE);
  568. // create log file
  569. log_fd= fopen(safe_log, "w+");
  570. // header
  571. log("MySQL Server %s, for %s (%s)\n\n", VERSION, SYSTEM_TYPE, MACHINE_TYPE);
  572. // status
  573. log("address : %s\n", address);
  574. log("port : %s\n", port);
  575. log("daemon : %s\n", mysqld);
  576. log("base directory : %s\n", basedir);
  577. log("data directory : %s\n", datadir);
  578. log("pid file : %s\n", pid_file);
  579. log("error file : %s\n", err_log);
  580. log("log file : %s\n", safe_log);
  581. log("\n");
  582. // check setup
  583. check_setup();
  584. // start the MySQL server
  585. mysql_start(argc, argv);
  586. // close log file
  587. if (log_fd)
  588. fclose(log_fd);
  589. return 0;
  590. }