nfs-ganesha 1.4

main.c

Go to the documentation of this file.
00001 /*
00002  * vim:expandtab:shiftwidth=8:tabstop=8:
00003  *
00004  * Copyright CEA/DAM/DIF  (2008)
00005  * contributeur : Philippe DENIEL   philippe.deniel@cea.fr
00006  *                Thomas LEIBOVICI  thomas.leibovici@cea.fr
00007  *
00008  *
00009  * This program is free software; you can redistribute it and/or
00010  * modify it under the terms of the GNU Lesser General Public
00011  * License as published by the Free Software Foundation; either
00012  * version 3 of the License, or (at your option) any later version.
00013  * 
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017  * Lesser General Public License for more details.
00018  * 
00019  * You should have received a copy of the GNU Lesser General Public
00020  * License along with this library; if not, write to the Free Software
00021  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00022  * 
00023  * ---------------------------------------
00024  */
00025 
00048 #ifdef HAVE_CONFIG_H
00049 #include "config.h"
00050 #endif
00051 
00052 #include "shell.h"
00053 #include "Getopt.h"
00054 #include <libgen.h>
00055 #include <pthread.h>
00056 #include <stdlib.h>
00057 #include <string.h>
00058 
00059 #include <stdio.h>
00060 
00061 #ifdef HAVE_LIBREADLINE
00062 #include <readline/readline.h>
00063 #include <readline/history.h>
00064 #endif
00065 
00066 #define NBTHRMAX 64
00067 
00068 /* ServerEpoch is ServerBootTime unless overriden by -E command line option */
00069 time_t ServerBootTime;
00070 time_t ServerEpoch;
00071 
00072 typedef struct shell_info__
00073 {
00074 
00075   int shell_id;
00076 
00077   char prompt[32];
00078   char script_file[128];
00079 
00080   pthread_t thread;
00081   pthread_attr_t attrs;
00082 
00083   int status;
00084 
00085 } shell_info_t;
00086 
00087 shell_info_t thrlist[NBTHRMAX];
00088 
00089 int verbose = 0;
00090 
00091 void *LaunchShell(void *arg)
00092 {
00093   int rc;
00094 
00095   shell_info_t *p_info = (shell_info_t *) arg;
00096 
00097   rc = shell_Init(verbose, p_info->script_file, p_info->prompt, p_info->shell_id);
00098 
00099   if(rc)
00100     {
00101       fprintf(stderr, "GANESHELL: ERROR %d in shell_Init\n", rc);
00102       p_info->status = rc;
00103       pthread_exit(&p_info->status);
00104     }
00105 
00106   rc = shell_Launch();
00107 
00108   if(rc)
00109     {
00110       fprintf(stderr, "GANESHELL: ERROR %d in shell_Launch\n", rc);
00111       p_info->status = rc;
00112       pthread_exit(&p_info->status);
00113     }
00114 
00115   p_info->status = 0;
00116 
00117   /* never reached */
00118   return &p_info->status;
00119 
00120 }
00121 
00122 int main(int argc, char **argv)
00123 {
00124 
00125   static char *format = "h@vn:E:";
00126   static char *help = "Usage: %s [-h][-v][-n <nb>][-E <epoch>][Script_File1 [Script_File2]...]\n";
00127 
00128   int option, rc;
00129 
00130   int err_flag = 0;
00131   int flag_h = 0;
00132 
00133   int nb_instance = 0;
00134 
00135   char *prompt = "ganeshell>";
00136   char *script_file = NULL;
00137 
00138   char *progname = basename(argv[0]);
00139 
00140   int nb_threads = 0;
00141 
00142   /* Set the server's boot time and epoch */
00143   ServerBootTime = time(NULL);
00144   ServerEpoch    = ServerBootTime;
00145 
00146   /* disables Getopt error message */
00147   Opterr = 0;
00148 
00149   /* reinits Getopt processing */
00150   Optind = 1;
00151 
00152   while((option = Getopt(argc, argv, format)) != -1)
00153     {
00154       switch (option)
00155         {
00156         case 'h':
00157           if(flag_h)
00158             fprintf(stderr,
00159                     "%s: warning: option 'h' has been specified more than once.\n",
00160                     progname);
00161           else
00162             flag_h++;
00163           break;
00164 
00165         case '@':
00166           /* A litlle backdoor to keep track of binary versions */
00167           printf("%s compiled on %s at %s\n", progname, __DATE__, __TIME__);
00168           printf("Release = %s\n", VERSION);
00169           printf("Release comment = %s\n", VERSION_COMMENT);
00170           exit(0);
00171           break;
00172 
00173         case 'n':
00174           if(nb_instance)
00175             fprintf(stderr,
00176                     "%s: warning: option 'n' has been specified more than once.\n",
00177                     progname);
00178           else
00179             nb_instance = atoi(Optarg);
00180 
00181           break;
00182 
00183         case 'v':
00184           if(verbose)
00185             fprintf(stderr,
00186                     "%s: warning: option 'v' has been specified more than once.\n",
00187                     progname);
00188           else
00189             verbose++;
00190           break;
00191 
00192         case 'E':
00193           ServerEpoch = (time_t) atoll(Optarg);
00194           break;
00195 
00196         case '?':
00197           fprintf(stderr, "%s: unknown option : %c\n", progname, Optopt);
00198           err_flag++;
00199           break;
00200         }
00201     }
00202 
00203   /* help flag */
00204   if(flag_h || err_flag)
00205     {
00206       fprintf(stderr, help, basename(progname));
00207       exit(err_flag);
00208     }
00209 #ifdef HAVE_LIBREADLINE
00210   /* Initialize history */
00211   using_history();
00212 #endif
00213 
00214   /* case when the 'n' option is specified */
00215   if(nb_instance != 0)
00216     {
00217       int i;
00218       /* case when there two or more threads */
00219 
00220       for(i = 0; i < nb_instance; i++)
00221         {
00222 
00223           if(verbose)
00224             fprintf(stderr, "Starting thread %d using file %s...\n",
00225                     nb_threads, argv[Optind]);
00226 
00227           thrlist[nb_threads].shell_id = nb_threads;
00228 
00229           snprintf(thrlist[nb_threads].prompt, 32, "ganeshell-%d>", nb_threads);
00230           strncpy(thrlist[nb_threads].script_file, argv[Optind], 128);
00231 
00232           pthread_attr_init(&thrlist[nb_threads].attrs);
00233           pthread_attr_setscope(&thrlist[nb_threads].attrs, PTHREAD_SCOPE_SYSTEM);
00234 
00235           nb_threads++;
00236 
00237           if(nb_threads >= NBTHRMAX)
00238             {
00239               fprintf(stderr, "GANESHELL: Too much threads (%d > %d)\n", nb_threads,
00240                       NBTHRMAX);
00241               exit(1);
00242             }
00243 
00244         }
00245 
00246       /* inits shell barriers */
00247 
00248       rc = shell_BarrierInit(nb_threads);
00249 
00250       if(rc)
00251         {
00252           fprintf(stderr, "GANESHELL: ERROR %d in shell_BarrierInit\n", rc);
00253           exit(1);
00254         }
00255 
00256       /* launching threads */
00257 
00258       for(i = 0; i < nb_threads; i++)
00259         {
00260           rc = pthread_create(&thrlist[i].thread,
00261                               &thrlist[i].attrs, LaunchShell, &thrlist[i]);
00262 
00263           if(rc)
00264             {
00265               fprintf(stderr, "GANESHELL: ERROR %d in pthread_create\n", rc);
00266               exit(1);
00267             }
00268 
00269         }
00270 
00271       /* waiting for thread termination */
00272 
00273       for(i = 0; i < nb_threads; i++)
00274         {
00275           void *ret;
00276           pthread_join(thrlist[i].thread, &ret);
00277 
00278         }
00279 
00280       exit(0);
00281 
00282     }
00283   /* case when there is only zero or one script file */
00284   else if(Optind >= (argc - 1))
00285     {
00286 
00287       if(Optind == (argc - 1))
00288         {
00289           script_file = argv[Optind];
00290         }
00291 
00292       rc = shell_Init(verbose, script_file, prompt, 0);
00293 
00294       if(rc)
00295         {
00296           fprintf(stderr, "GANESHELL: ERROR %d in shell_Init\n", rc);
00297           exit(1);
00298         }
00299 
00300       rc = shell_Launch();
00301 
00302       if(rc)
00303         {
00304           fprintf(stderr, "GANESHELL: ERROR %d in shell_Launch\n", rc);
00305           exit(1);
00306         }
00307 
00308       exit(0);
00309 
00310     }
00311   else
00312     {
00313       int i;
00314       /* case when there two or more threads */
00315 
00316       for(i = Optind; i < argc; i++)
00317         {
00318 
00319           if(verbose)
00320             fprintf(stderr, "Starting thread %d using file %s...\n", nb_threads, argv[i]);
00321 
00322           thrlist[nb_threads].shell_id = nb_threads;
00323 
00324           snprintf(thrlist[nb_threads].prompt, 32, "ganeshell-%d>", nb_threads);
00325           strncpy(thrlist[nb_threads].script_file, argv[i], 128);
00326 
00327           pthread_attr_init(&thrlist[nb_threads].attrs);
00328           pthread_attr_setscope(&thrlist[nb_threads].attrs, PTHREAD_SCOPE_SYSTEM);
00329 
00330           nb_threads++;
00331 
00332           if(nb_threads >= NBTHRMAX)
00333             {
00334               fprintf(stderr, "GANESHELL: Too much threads (%d > %d)\n", nb_threads,
00335                       NBTHRMAX);
00336               exit(1);
00337             }
00338 
00339         }
00340 
00341       /* inits shell barriers */
00342 
00343       rc = shell_BarrierInit(nb_threads);
00344 
00345       if(rc)
00346         {
00347           fprintf(stderr, "GANESHELL: ERROR %d in shell_BarrierInit\n", rc);
00348           exit(1);
00349         }
00350 
00351       /* launching threads */
00352 
00353       for(i = 0; i < nb_threads; i++)
00354         {
00355           rc = pthread_create(&thrlist[i].thread,
00356                               &thrlist[i].attrs, LaunchShell, &thrlist[i]);
00357 
00358           if(rc)
00359             {
00360               fprintf(stderr, "GANESHELL: ERROR %d in pthread_create\n", rc);
00361               exit(1);
00362             }
00363 
00364         }
00365 
00366       /* waiting for thread termination */
00367 
00368       for(i = 0; i < nb_threads; i++)
00369         {
00370           void *ret;
00371           pthread_join(thrlist[i].thread, &ret);
00372 
00373         }
00374 
00375       exit(0);
00376 
00377     }
00378 
00379 }