int main(int argc, char **argv)
{
  int error=0;
  char **argv_to_free;
  MY_INIT(argv[0]);

  my_getopt_use_args_separator= TRUE;
  if (load_defaults("my",load_default_groups,&argc,&argv))
    return 1;
  my_getopt_use_args_separator= FALSE;

  /* argv is changed in the program */
  argv_to_free= argv;
  if (get_options(&argc, &argv))
  {
    free_defaults(argv_to_free);
    return(1);
  }

  if (opt_use_threads && !lock_tables)
  {
    char **save_argv;
    uint worker_thread_count= 0, table_count= 0, i= 0;
    pthread_t *worker_threads;       /* Thread descriptor */
    pthread_attr_t attr;             /* Thread attributes */
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr,
                                PTHREAD_CREATE_JOINABLE);

    pthread_mutex_init(&init_mutex, NULL);
    pthread_mutex_init(&counter_mutex, NULL);
    pthread_cond_init(&count_threshhold, NULL);

    /* Count the number of tables. This number denotes the total number
       of threads spawn.
    */
    save_argv= argv;
    for (table_count= 0; *argv != NULL; argv++)
      table_count++;
    argv= save_argv;

    if (!(worker_threads= (pthread_t*) my_malloc(table_count *
                                                 sizeof(*worker_threads),
                                                 MYF(0))))
      return -2;

    for (counter= 0; *argv != NULL; argv++) /* Loop through tables */
    {
      pthread_mutex_lock(&counter_mutex);
      while (counter == opt_use_threads)
      {
        struct timespec abstime;

        set_timespec(abstime, 3);
        pthread_cond_timedwait(&count_threshhold, &counter_mutex, &abstime);
      }
      /* Before exiting the lock we set ourselves up for the next thread */
      counter++;
      pthread_mutex_unlock(&counter_mutex);
      /* now create the thread */
      if (pthread_create(&worker_threads[worker_thread_count], &attr,
                         worker_thread, (void *)*argv) != 0)
      {
        pthread_mutex_lock(&counter_mutex);
        counter--;
        pthread_mutex_unlock(&counter_mutex);
        fprintf(stderr,"%s: Could not create thread\n", my_progname);
        continue;
      }
      worker_thread_count++;
    }

    /*
      We loop until we know that all children have cleaned up.
    */
    pthread_mutex_lock(&counter_mutex);
    while (counter)
    {
      struct timespec abstime;

      set_timespec(abstime, 3);
      pthread_cond_timedwait(&count_threshhold, &counter_mutex, &abstime);
    }
    pthread_mutex_unlock(&counter_mutex);
    pthread_mutex_destroy(&init_mutex);
    pthread_mutex_destroy(&counter_mutex);
    pthread_cond_destroy(&count_threshhold);
    pthread_attr_destroy(&attr);

    for(i= 0; i < worker_thread_count; i++)
    {
      if (pthread_join(worker_threads[i], NULL))
        fprintf(stderr,"%s: Could not join worker thread.\n", my_progname);
    }

    my_free(worker_threads);
  }
  else
  {
    MYSQL *mysql= 0;
    if (!(mysql= db_connect(current_host,current_db,current_user,opt_password)))
    {
      free_defaults(argv_to_free);
      return(1); /* purecov: deadcode */
    }

    if (mysql_query(mysql, "/*!40101 set @@character_set_database=binary */;"))
    {
      db_error(mysql); /* We shall countinue here, if --force was given */
      return(1);
    }

    if (lock_tables)
      lock_table(mysql, argc, argv);
    for (; *argv != NULL; argv++)
      if ((error= write_to_table(*argv, mysql)))
        if (exitcode == 0)
          exitcode= error;
    db_disconnect(current_host, mysql);
  }
  my_free(opt_password);
#ifdef HAVE_SMEM
  my_free(shared_memory_base_name);
#endif
  free_defaults(argv_to_free);
  my_end(my_end_arg);
  return(exitcode);
}