home *** CD-ROM | disk | FTP | other *** search
/ Netware Super Library / Netware Super Library.iso / remote / jservr / jserver.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-01-15  |  19.0 KB  |  597 lines

  1. /***************************************************************************** 
  2.  * 
  3.  * Program Name:jserver - Generic Job Server Front-End 
  4.  * 
  5.  * Filename:jserver.c 
  6.  * 
  7.  * Date Created:  November 21, 1988 
  8.  * 
  9.  * Version:  1.0 
  10.  * 
  11.  * Programmers:Tom Brough, Milt Anderson, Cliff Ross, Greg Peto 
  12.  * 
  13.  * Files used:..\genjob.obj 
  14.  * 
  15.  * Date Modified: Jan. 28, 1989 
  16.  * 
  17.  * Modifications: Reformated by Gregory J. Peto 
  18.  * 
  19.  * Comments:   
  20.  * 
  21.  *   This command line utility works in conjucntion with the generic job 
  22.  *      server utilities JSUPER, and JSERVER.  It is designed to let the 
  23.  *      user submit a dos command line to the job queue for remote 
  24.  *      execution on a job server machine. 
  25.  *   See the function of badUsage for summary of possible command line arguments 
  26.  *      to this utility.  All command line arguments are expected in the 
  27.  *      form: 
  28.  *        /<command keyword>=<command argument> 
  29.  *   To locate where global variables are initialized or set, look at 
  30.  *      ComAndInit for command line settings or for the variables as 
  31.  *      output variables passed to a function call. 
  32.  *   BUGS:  A TSR utility should be designed that can catch the acknowledge 
  33.  *       signal from the server machine to the client that displays the 
  34.  *      message when sitting idol at command.com (similar to UNIX) 
  35.  *       instead of forcing user to respond. 
  36.  ****************************************************************************/ 
  37.  
  38. /* functions in this file: 
  39. */                            
  40. #include "..\genjob.h" 
  41. /* #include<nitipx.h> */ 
  42. #include<sys\types.h> 
  43. #include<sys\stat.h> 
  44. #include<signal.h> 
  45. #include<process.h> 
  46. #include<ctype.h> 
  47.  
  48. /* constants definitions */ 
  49. #defineVERB_TEST1        /* want verbose test messages */ 
  50.  
  51.  
  52. /* global variables and data types */ 
  53. COMMAND_ARGS command_args[] = 
  54.  /* token,     keyword     num sig,req. string,req. int */ 
  55. #  defineCOM_DELAY1 
  56.  { COM_DELAY,  "DELAY",    1,FALSE,TRUE}, 
  57. #  defineCOM_SERVERCOM_DELAY + 1 
  58.  { COM_SERVER, "SERVER",   1,TRUE,FALSE} 
  59. }; 
  60.  
  61. int  secWaitForCheckJob= 10;/* number seconds wait to check for job */ 
  62.  
  63. JobStruct    job;          /* QMS job struct to be used in calls */ 
  64. WORD         jobType = 0xffff;/* job type number, default is any */ 
  65. JOBFILE      jobFile;    /* buffer of job file */ 
  66. CLIENT_REC_AREAjobClientArea;/* buffer of job client record area */ 
  67. JOBFILE      serverEnviron;/* server workstation environ for 
  68.                            restoration after job finishes */ 
  69.       
  70. /* module specific varables and data types */ 
  71. /* macro definitions */ 
  72.  
  73. /*****************************************************************************/ 
  74.  
  75. main(argc,argv,envp) 
  76.  /* Descrip: 
  77.      This program supports the generic job server.  This utility 
  78.      allow the user ot submit DOS command lines to be executed 
  79.      remotely. 
  80.     Algorithm:// 
  81.          Parse and handle command line arguments, initialize defaults 
  82.      Initialize queue server status. 
  83.      Catch signals so server removed from queue if ends abnormally. 
  84.      while server is running 
  85.         if console input, handle it. 
  86.         if still running and time to check 
  87.           reset wait count 
  88.           if job to service 
  89.              service it 
  90.         wait minimum time and decrement wait count 
  91.  */ 
  92.  /* Input: */ 
  93. int argc; 
  94. char *argv[]; 
  95. char *envp[]; 
  96.   
  97. {    /* main // */ 
  98.  BOOLEANserverRunning= TRUE; 
  99.  int    waitCount= 0;    /* check immediate for job */ 
  100.  BOOLEANserverWasActive = TRUE;/* get unactive message first time 
  101.                            through */ 
  102.  int    shandler();        /* signal handler */ 
  103.  /*--------------------------------------------------main body */ 
  104. #if 0 
  105.  if (argc == 1) 
  106.    BadUsage(NULL);/* missing command line arguments */ 
  107. #endif 
  108.  
  109.  ComAndInit(--argc,++argv);/* skip past program name */ 
  110.  InitServer(jobServerConID,jobQueueID); 
  111.  /* catch any abnormal temination signals so can disconnect from queue */ 
  112.  signal(SIGINT,shandler); 
  113.  signal(SIGFPE,shandler); 
  114.  signal(SIGABRT,shandler); 
  115.  /* save server environment so can restore later */ 
  116.  GetJobEnviron(NULL,&serverEnviron); 
  117.  
  118.  while (serverRunning) 
  119.  { 
  120.    if (kbhit()) 
  121.      serverRunning= HandleConsoleInput(); 
  122.  
  123.    if (serverRunning AND waitCount <= 0) 
  124.    {   /* check for job to service */ 
  125.      waitCount= secWaitForCheckJob; 
  126.      if (CheckForJob()) 
  127.      {  /* found job to execute, and did it */ 
  128.         serverWasActive= TRUE; 
  129.         waitCount   = 0;/* check immediate again */ 
  130.      } else if (serverWasActive) 
  131.      { 
  132.         printf("\nJob Server: idle, no jobs to service.\n"); 
  133.         serverWasActive= FALSE; 
  134.      } 
  135.    } /* if waitCount */ 
  136.  
  137.    WaitIPX(18);/* wait 18 clock ticks, approx. 1 second */ 
  138.    --waitCount; 
  139.  } /* while serverRunning */ 
  140.  
  141.  JobServerExit(0); 
  142. }    /* of main */ 
  143.  
  144. /********************************************************************/ 
  145.  
  146. int shandler(ecode) 
  147.  /* Descrip: 
  148.      This function catches interrupts from OS, terminates gracefully. 
  149.     Algorithm:// 
  150.  */ 
  151.  /* Input: */ 
  152. intecode; 
  153.   
  154. {    /* // */ 
  155.  /*--------------------------------------------------main body */ 
  156.  JobServerExit(1); 
  157. }    /* end of shandler */ 
  158.   
  159. /********************************************************************/ 
  160.  
  161. BadUsage(message) 
  162.  /* Descrip: 
  163.      This function is called when a fatal error is detected in the 
  164.         command line.  It displays the command format and options 
  165.         and then exits the program. 
  166.     Algorithm:// 
  167.  */ 
  168.  /* Input: */ 
  169. char*message;/* optional explanatory message */ 
  170.  /* Output: */ 
  171.   
  172. {    /* BadUsage // */ 
  173.  /*--------------------------------------------------main body */ 
  174.  if (message) 
  175.    printf("Error: %s\n\n",message); 
  176.  printf("usage: jserver [<command parameters>]\n\n"); 
  177.  printf("   /Server=<target server with job queue>\n"); 
  178.  printf("   /Delay=<number seconds wait to query for job>\n"); 
  179.  
  180.  exit(1); 
  181. }    /* end of BadUsage */ 
  182.   
  183. /********************************************************************/ 
  184.  
  185. ComAndInit(argc,argv) 
  186.  /* Descrip: 
  187.          This function parses command line input and sets default values. 
  188.      Several global variables may be changed from their default values 
  189.         by command line arguments. 
  190.     Algorithm:// 
  191.          Scans command line arguments, overiding defaults as needed. 
  192.         See top of this file for notes on expected form of command 
  193.           line option and badUsage for specific form of commands. 
  194.      Saves remote execution command line in jobClientArea. 
  195.      Find server of target queue and save in global variable. 
  196.    BUGS: 
  197.      Not all command line options implemented yet. 
  198.  */ 
  199.  /* Input: */ 
  200. int argc; 
  201. char *argv[]; 
  202.  /* Output: */ 
  203.   
  204. {    /* ComAndInit // */ 
  205.  /* name of server with job queue */ 
  206.  char   queueServerName[MAX_FSERVER_NAME]; 
  207.  char   argString[MAX_ARG_VAR];/* command parameter variable buffer */ 
  208.  long   argInt;            /* numeric parameter variable */ 
  209.  JOB_TIMEargTime;        /* time parameter */ 
  210.  JOB_DATEargDate;        /* date parameter */ 
  211.  /*--------------------------------------------------main body */ 
  212.  queueServerName[0]= '\0'; 
  213.  
  214.  for (;argc; --argc, ++argv) 
  215.  { 
  216.    if (*argv[0] NOT= '/') 
  217.      badUsage("Unrecognized command line arguement"); 
  218.    switch (ScanArg((*argv) + 1,command_args, 
  219.           sizeof(command_args)/sizeof(COMMAND_ARGS), 
  220.           argString,&argInt,&argTime,&argDate)) 
  221.    { 
  222.      caseCOM_DELAY: 
  223.         printf("Seconds to wait to check for job set to %d\n", 
  224.           secWaitForCheckJob = argInt); 
  225.         break; 
  226.      caseCOM_SERVER: 
  227.         if (strlen(argString) > (MAX_FSERVER_NAME - 1)) 
  228.         { 
  229.           printf("Server name length must be less than %d, aborting\n", 
  230.              MAX_FSERVER_NAME - 1); 
  231.           exit(1); 
  232.         } 
  233.         strcpy(queueServerName,argString); 
  234.         break; 
  235.      default: 
  236.         printf("Internal error: ComAndInit"); 
  237.         exit(1); 
  238.    }   /* end of switch on ScanArg */ 
  239.     
  240.  } /* end of for argc loop */ 
  241.  
  242.  FindJobServer(queueServerName,TRUE); 
  243.  if (jobQueueID == NULL) 
  244.  { 
  245.    printf("Could not find any server with job queue.\n"); 
  246.    exit(1); 
  247.  } 
  248.  
  249. #  if VERB_TEST 
  250.    printf("Found server %s, connection ID %x\n", 
  251.      queueServerName ? "(default)" : queueServerName, 
  252.      jobServerConID); 
  253. #  endif 
  254. }    /* end of ComAndInit */ 
  255.   
  256. /********************************************************************/ 
  257.  
  258. InitServer(conID,queueID) 
  259.  /* Descrip: 
  260.      This function attempts register this program as a job server 
  261.         at the server conID for queue queueID. 
  262.     Algorithm:// 
  263.  */ 
  264.  /* Input: */ 
  265. BYTE conID;  /* connection ID to server with queue */ 
  266. long queueID;/* queue bindery ID for queue on server */ 
  267.  
  268.  /* Output: */ 
  269.   
  270. {    /* InitServer // */ 
  271.  intccode; 
  272.  /*--------------------------------------------------main body */ 
  273.  SetPreferredConnectionID(conID); 
  274.  if (ccode = AttachQueueServerToQueue(queueID)) 
  275.  { 
  276.    switch (ccode) 
  277.    { 
  278.      case NO_Q_RIGHTS: 
  279.         printf("Insufficient rights to be server for job queue.\n"); 
  280.         break; 
  281.      case NO_SUCH_MEMBER: 
  282.         printf("Not member of queue server list.\n"); 
  283.         break; 
  284.      case Q_HALTED: 
  285.         printf("Job queue is halted, unable to serve it.\n"); 
  286.         break; 
  287.      case SERVER_BINDERY_LOCKED: 
  288.      case BINDERY_FAILURE: 
  289.         printf("Server bindery locked or broken, unable to service.\n"); 
  290.         break; 
  291.      default: 
  292.         printf("Unable to attach to queue as server.\n"); 
  293.    }   /* end of switch ccode */ 
  294.    exit(1); 
  295.  }   /* end of if */ 
  296. }    /* end of InitServer */ 
  297.   
  298. /********************************************************************/ 
  299.  
  300. BOOLEAN HandleConsoleInput() 
  301.  /* Descrip: 
  302.      This function is called when user keyboard interraction 
  303.         detected.  Gets user input, and executes user request. 
  304.      Returns TRUE if user wished to continue as server, else FALSE. 
  305.     Algorithm:// 
  306.      Stubbed for now. 
  307.  */ 
  308.   
  309. {    /* HandleConsoleInput // */ 
  310.  /*--------------------------------------------------main body */ 
  311.  return(TRUE); 
  312. }    /* end of HandleConsoleInput  */ 
  313.   
  314. /********************************************************************/ 
  315.  
  316. BOOLEAN CheckForJob() 
  317.  /* Descrip: 
  318.      This function checks to see if there is a job in the queue it 
  319.         can service.  If one is found and executed then it returns 
  320.         TRUE, else FALSE. 
  321.     Algorithm:// 
  322.  */ 
  323.   
  324. {    /* CheckForJob // */ 
  325.  int ccode; 
  326.  int assocFile;/* associated file for job 
  327.  /*--------------------------------------------------main body */ 
  328.  SetPreferredConnectionID(jobServerConID); 
  329.  if ((ccode = ServiceQueueJobAndOpenFile(jobQueueID,jobType, 
  330.      &job,&assocFile)) == SUCCESSFUL) 
  331.  { 
  332.    DoJob(assocFile); 
  333.    return(TRUE); 
  334.  } else 
  335.    switch (ccode) 
  336.    { 
  337.      case Q_ERROR: 
  338.         printf("Server getting queue error on request to service job.\n"); 
  339.         break; 
  340.      case Q_HALTED: 
  341.         printf("Job queue is halted\n."); 
  342.         break; 
  343.      case NO_Q_JOB:/* OK, normal operation, just no jobs */ 
  344.         break; 
  345.      case SERVER_BINDERY_LOCKED: 
  346.      case BINDERY_FAILURE: 
  347.         printf("Job server experiencing problems with bindery.\n"); 
  348.         break; 
  349.      default: 
  350.         printf("Job server detected abnormal problem requesting job to service,\n"); 
  351.         printf("aborting job server program.\n"); 
  352.         JobServerExit(1); 
  353.    } 
  354.  
  355.  return(FALSE); 
  356. }    /* end of CheckForJob */ 
  357.   
  358. /********************************************************************/ 
  359.  
  360. DoJob(assocFile) 
  361.  /* Descrip: 
  362.      This fucntion uses global variables and assocFile to execute 
  363.         job attached to from job queue. 
  364.     Algorithm:// 
  365.    BUGS: 
  366.      It should detach itself from all file servers but one with queue 
  367.         so all 8 slots are available for the job.  Would then have 
  368.         to be restored later. 
  369.      It should attempt to strip memory of any TSR's that may have been 
  370.         started and are hanging in memory that could get control with 
  371.         a different job's security rights.  Maybe moot question if 
  372.         implement Reboot option in server. 
  373.      This routine should check the monitor mode and reset it to text 
  374.         if necessary. 
  375.  */ 
  376.  /* Input: */ 
  377. int  assocFile; 
  378.   
  379. {    /* DoJob // */ 
  380.  intcommandStatus; 
  381.  /*--------------------------------------------------main body */ 
  382.  printf("Setting up job #%d\n",job.jobNumber); 
  383.  ClearServerEnviron(); 
  384.  ChangeToClientRights(jobQueueID,job.jobNumber); 
  385.  read(assocFile,(char *) &jobFile,sizeof(jobFile)); 
  386.  if (SetJobEnviron(&jobFile)) 
  387.    /* environment setup successful, proceed */ 
  388.    commandStatus= SpawnJob(); 
  389.  else 
  390.    commandStatus= 1;/* mark as unsuccessful */ 
  391.  
  392.  /* signal done, no charge for doing job */ 
  393.  RestoreQueueServerRights(); 
  394.  
  395.  /* restore server environment */ 
  396.  ClearServerEnviron();/* strip any attachments gained by job */ 
  397.  SetJobEnviron(&serverEnviron); 
  398.  if (FinishServicingQueueJobAndFile(jobQueueID,job.jobNumber,(long) 0, 
  399.      assocFile)) 
  400.    printf("Job server received error when signaling done with job.\n"); 
  401.  if (jobFile.flags & DO_ACK_MESS) 
  402.    AcknowledgeClient(commandStatus); 
  403. }    /* end of DoJob */ 
  404.   
  405. /********************************************************************/ 
  406.  
  407. ClearServerEnviron() 
  408.  /* Descrip: 
  409.      This function clears the workstation internal tables so that 
  410.         they can be rebuilt for the job. 
  411.     Algorithm:// 
  412.  */ 
  413.  /* Input: */ 
  414.  /* Output: */ 
  415.   
  416. {    /* // */ 
  417.  int drive;    /* drive number checking */ 
  418.  WORD   conID;   /* connection ID for drive (1-8) */ 
  419.  /*--------------------------------------------------main body */ 
  420.  for (conID = 1; conID <= MAX_SERVER_ATTACHES; ++conID) 
  421.    if (conID NOT= jobServerConID AND IsConnectionIDInUse(conID)) 
  422.    { 
  423.      LogoutFromFileServer(conID); 
  424.      DetachFromFileServer(conID); 
  425.    } 
  426. }    /* end of ClearServerEnviron */ 
  427.   
  428. /********************************************************************/ 
  429.  
  430. int SpawnJob() 
  431.  /* Descrip: 
  432.      Spawn job command using command.com 
  433.      Returns termination code of spawned process. 
  434.     Algorithm:// 
  435.      Construct spawn execute variables.  envp is array of pointer 
  436.         to environment variable sets.  execbuf contains fullpath 
  437.         with command.com.  paramsbuf is array of ptrs to command.com 
  438.         arguments. 
  439.      Disable End Of Job (so command.com doesn't generate one) 
  440.      Spawn command.com command 
  441.      Reset End OF Job Status to old value. 
  442.      Return job completion code. 
  443.  */ 
  444.  /* Input: */ 
  445.  /* Output: */ 
  446.   
  447. {    /* SpawnJob // */ 
  448.  int i; 
  449.  char   *envp[MAX_ENV_ENTRIES + 2]; 
  450.  char   *comspec; 
  451.  char   *path; 
  452. #  defineMAXCOMPARAMS50 
  453.  char   *argv[MAXCOMPARAMS]; 
  454.  char   *comptr;           /* ptr into command string */ 
  455.  int ccode; 
  456. #  defineJOBCOMMAND (((CLIENT_REC_AREA *) &job.clientRecordArea[0])->jobCommand) 
  457.  /*--------------------------------------------------main body */ 
  458.  for (i = 0; i < jobFile.numEntries; ++i) 
  459.    envp[i]= jobFile.envEntries[i]; 
  460. #if 0 
  461.  /* try to figure out why getting garbage at end of envp vector in spawned job */ 
  462.  envp[i]= "DUMMY=DUMMY"; 
  463.  envp[i+1]= NULL; 
  464. #else 
  465.  envp[i]= NULL; 
  466.  envp[i+1]= NULL; 
  467. #endif 
  468.  
  469.  if ((comspec = getenv("COMSPEC")) == NULL) 
  470.  { 
  471.    printf("COMSPEC missing from server environment.\n"); 
  472.    JobServerExit(1); 
  473.  } 
  474.  
  475.  argv[0]= comspec; 
  476.  argv[1]= "/c";/* tell command.com only execute one command */ 
  477.  i      = 2;   /* start at third entry in argv */ 
  478.  /* skip leading "space" characters */ 
  479.  while (isspace(*comptr)) 
  480.    ++comptr; 
  481.  for (comptr = JOBCOMMAND; *comptr; ++i) 
  482.  { 
  483.    if (i == MAXCOMPARAMS) 
  484.    { 
  485.      printf("Too many command line parameters to setup job.\n"); 
  486.      return(1);/* return error code */ 
  487.    } 
  488.    argv[i]= comptr; 
  489.    /* skip past parameter */ 
  490.    while (isspace(*comptr) == FALSE) 
  491.      ++comptr; 
  492.    if (*comptr == '\0') 
  493.      break;                /* nothing left */ 
  494.    *comptr++ = '\0';     /* mark end of parameter */ 
  495.    /* skip to beginning of next parameter */ 
  496.    while (isspace(*comptr)) 
  497.      ++comptr; 
  498.  } 
  499.  argv[i]= NULL; 
  500.  
  501.  printf("Spawning command: %s\n",JOBCOMMAND); 
  502.  if ((ccode = spawnve(P_WAIT,comspec,argv,envp)) < 0) 
  503.  { 
  504.    printf("Job server could not execute command:\n   %s\n\n", 
  505.      JOBCOMMAND); 
  506.    perror("Spawn failed"); 
  507.    return(1); 
  508.  } 
  509.  return(ccode); 
  510. }    /* end of SpawnJob */ 
  511.   
  512. /********************************************************************/ 
  513.  
  514. AcknowledgeClient(commandStatus) 
  515.  /* Descrip: 
  516.      This function sends the client (the job submitter) 
  517.         a broadcast message that job finished. 
  518.     Algorithm:// 
  519.  */ 
  520.  /* Input: */ 
  521.  /* Output: */ 
  522.   
  523. {    /* AcknowledgeClient // */ 
  524.  char   mesBuffer[128];/* client braodcast message buffer */ 
  525.  WORD   clientStation;/* buffer for WORD value needed for 
  526.                            broadcast */ 
  527.  BYTE   resultList; 
  528.  /*--------------------------------------------------main body */ 
  529.  sprintf(mesBuffer,"Job %d %s.",job.jobNumber,(commandStatus == 0) ? 
  530.    "finished with successful completion code" : 
  531.    "failed"); 
  532.  
  533.  clientStation= job.clientStation;/* convert to WORD */ 
  534.  if (SendBroadcastMessage(mesBuffer,&clientStation,&resultList,(WORD) 1)) 
  535.    printf("Unable to broadcast messages to client.\n"); 
  536.  switch (resultList) 
  537.  { 
  538.    case0: 
  539.      break;  /* broadcast successful */ 
  540.    case0xFC: 
  541.      printf("Job client broadcast pipe full, acknowledgement failed.\n"); 
  542.      break; 
  543.    case0xFE: 
  544.      printf("Job client task does not exist, acknowledgement failed.\n"); 
  545.      break; 
  546.    case 0xFF: 
  547.      printf("Job client acknowlegement braodcast failed.\n"); 
  548.  } 
  549.  
  550. }    /* end of AcknowledgeClient */ 
  551.   
  552. /********************************************************************/ 
  553.  
  554. WaitIPX(ticks) 
  555.  /* Descrip: 
  556.      This function will loop waiting for ticks number of ticks to 
  557.         expire using IPX interface calls. 
  558.     Algorithm:// 
  559.  */ 
  560.  /* Input: */ 
  561. unsigned intticks; 
  562.   
  563. {    /* WaitIPX // */ 
  564.  static intfirsttime= 1; 
  565.  unsigned intfinishTime; 
  566.  /*--------------------------------------------------main body */ 
  567.  if (firsttime) 
  568.  { 
  569.    firsttime = 0; 
  570.    IPXInitialize();/* need to initialize internal variables */ 
  571.  } 
  572.  
  573.  finishTime = IPXGetIntervalMarker() + ticks; 
  574.  while (finishTime > IPXGetIntervalMarker()) 
  575.    ; 
  576. }    /* end of WaitIPX */ 
  577.   
  578. /********************************************************************/ 
  579.  
  580. JobServerExit(ecode) 
  581.  /* Descrip: 
  582.      Exit job server program. 
  583.     Algorithm:// 
  584.  */ 
  585.  /* Input: */ 
  586. intecode;    /* exit code to return to DOS */ 
  587.   
  588. {    /* JobServerExit // */ 
  589.  /*--------------------------------------------------main body */ 
  590.  if (DetachQueueServerFromQueue(jobQueueID)) 
  591.    printf("Job server received error code back when detaching from queue.\n"); 
  592.  exit(ecode); 
  593. }    /* end of JobServerExit */ 
  594.   
  595. /********************************************************************/ 
  596.