home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 620.lha / ShellTimer / ShellTimer.c < prev    next >
C/C++ Source or Header  |  1992-02-05  |  9KB  |  406 lines

  1. ;/* Execute me to Compile and link ShellTimer.c
  2. ;shelltimer start verbose
  3. ; For debugging, use the following command:
  4. ;lc -. -b1 -cfistq -j73 -v -Lit -d3 -isrc:memlib -dMWDEBUG=1 ShellTimer.c
  5. ; For production, use the following command:
  6. lc -. -O -ms -b1 -cfistq -j73 -Lit -tr ShellTimer.c
  7. ;echo "Time to compile and link: " NOLINE
  8. ;shelltimer stop
  9. quit
  10. */
  11.  
  12. /***
  13. ****    SHELLTIMER.C
  14. ****
  15. ****    Creation:        John Lindwall
  16. ****                    19 Jan 1992
  17. ****
  18. ****    Description:    Client program for ShellTimer system.  The user
  19. ****        invokes timer commands via this program.  The commands are
  20. ****        passed to the ShellTimerDaemon for processing.  The client
  21. ****        displays the results of the command, if any.
  22. ****
  23. ****        As written, this program requires AmigaDOS 2.04.  It could
  24. ****        be modified to run under 1.3, but I don't have the inclination.
  25. ****        2.0 features used include local shell environment variables,
  26. ****        ReadArgs(), and System().
  27. ****
  28. ****        This program must be run from the shell.  ShellTimer exits
  29. ****        gracefully if AmigaDOS 2.0 is not in charge, or if not run
  30. ****        from the shell.
  31. ****
  32. ****        See ShellTimer.doc for more information.
  33. ****
  34. ****        The ShellTimer System (which includes the programs
  35. ****        ShellTimerDaemon and ShellTimer) is released into the Public
  36. ****        Domain by the author, John Lindwall.  I ask that the archive
  37. ****        be kept intact with the docs and the source code.  Bug reports
  38. ****        should be sent to me at johnl@crash.cts.com.
  39. ****
  40. ****    Note:    The code is not commented ... sorry.
  41. ****
  42. ****    Overhauls:
  43. ***/
  44.  
  45.  
  46. #include <exec/ports.h>
  47. #include <dos/dos.h>
  48. #include <dos/var.h>
  49. #include <dos/rdargs.h>
  50. #include <dos/dostags.h>
  51. #include <devices/timer.h>
  52. #include <utility/tagitem.h>
  53.  
  54. #include <proto/exec.h>
  55. #include <proto/dos.h>
  56.  
  57. #include <stdlib.h>
  58. #include <stdio.h>
  59. #include <string.h>
  60.  
  61. #include "ShellTimer.h"
  62.  
  63. /* Command line parsing stuff */
  64. #define ARGTEMPLATE            "START/S,STOP/S,CANCEL/S,QUIT/S,HELP/S,V=VERBOSE/S,Q=QUERY/S"
  65. #define OPT_START            0
  66. #define OPT_STOP            1
  67. #define OPT_CANCEL            2
  68. #define OPT_QUIT            3
  69. #define OPT_HELP            4
  70. #define OPT_VERBOSE            5
  71. #define OPT_QUERY            6
  72. #define OPT_COUNT            7
  73.  
  74. #define SECONDS_PER_MINUTE    60
  75. #define SECONDS_PER_HOUR    3600
  76. #define SECONDS_PER_DAY        (SECONDS_PER_HOUR * 24)
  77.  
  78. #define APPNAME                "ShellTimer"
  79. #define ADOS2_VERSION        37
  80.  
  81. int ParseCommandLine(void);
  82. BOOL SendCommand(int command);
  83. void PrintResults(int command);
  84. void PrintElapsedTime(struct timeval *diffTime);
  85. void Print(char *s);
  86. void ShowHelp(void);
  87.  
  88. struct ST_Message message;
  89. static int verbose = FALSE;
  90. UBYTE versionTag[] = "\0$VER: " APPNAME " 1.0 (03.02.92)";
  91.  
  92. void
  93. main(int argc, char *argv[])
  94. {
  95.     int command;
  96.  
  97.     extern struct DOSLibrary *DOSBase;
  98.  
  99.     if( argc == 0 )        /* Bail out if started from WorkBench */
  100.     {
  101.         exit(-10);
  102.     }
  103.  
  104.     if( DOSBase->dl_lib.lib_Version < ADOS2_VERSION )
  105.     {
  106.         Print(APPNAME " Requires AmigaDOS 2.0!\n");
  107.         exit(-20);
  108.     }
  109.  
  110.  
  111. #ifdef MWDEBUG
  112.     MWInit(NULL, 0, "CON:0/200/639/199/MemLib");
  113. #endif
  114.     command = ParseCommandLine();
  115.     if( command != ST_ERR )
  116.     {
  117.         if( command != ST_HELP )
  118.         {
  119.             if( SendCommand(command) )
  120.             {
  121.                 PrintResults(command);
  122.             }
  123.         }
  124.         else
  125.         {
  126.             ShowHelp();
  127.         }
  128.     }
  129.     else
  130.     {
  131.         Print("Invalid parameters\n");
  132.     }
  133. #ifdef MWDEBUG
  134.     MWTerm();
  135. #endif
  136.     exit(0);
  137. }
  138.  
  139. int
  140. ParseCommandLine()
  141. {
  142.     ULONG result[OPT_COUNT];
  143.     struct RDArgs *rda;
  144.  
  145.     memset(result, '\0', sizeof(result));
  146.     if( (rda = ReadArgs(ARGTEMPLATE, result, NULL)) != NULL )
  147.     {
  148.         FreeArgs(rda);
  149.         if( result[OPT_VERBOSE] )
  150.         {
  151.             verbose = TRUE;
  152.         }
  153.         if( result[OPT_START] )
  154.         {
  155.             return(ST_START);
  156.         }
  157.         if( result[OPT_STOP] )
  158.         {
  159.             return(ST_STOP);
  160.         }
  161.         if( result[OPT_CANCEL] )
  162.         {
  163.             return(ST_CANCEL);
  164.         }
  165.         if( result[OPT_QUIT] )
  166.         {
  167.             return(ST_QUIT);
  168.         }
  169.         if( result[OPT_HELP] )
  170.         {
  171.             return(ST_HELP);
  172.         }
  173.         if( result[OPT_QUERY] )
  174.         {
  175.             return(ST_QUERY);
  176.         }
  177.         return(ST_TOGGLE);    /* Default action if no args supplied */
  178.     }
  179.     return(ST_ERR);
  180. }
  181.  
  182. BOOL
  183. SendCommand(int command)
  184. {
  185.     struct LocalVar *shellPID;
  186.     struct MsgPort *publicPort, *myPort;
  187.     BPTR file;
  188.     int systemStat, i;
  189.     static struct TagItem daemonTags[] =
  190.     {
  191.         SYS_Input, 0,
  192.         SYS_Output, NULL,
  193.         SYS_Asynch, TRUE,
  194.         SYS_UserShell, TRUE,
  195.         TAG_DONE
  196.     };
  197.  
  198.     shellPID = FindVar("process", GVF_LOCAL_ONLY);
  199.     if( shellPID == NULL )
  200.     {
  201.         Print("Can't get shell PID!\n");
  202. #ifndef DEBUG
  203.         exit(-1);
  204. #endif
  205.     }
  206.  
  207. #ifdef DEBUG
  208.     message.requestID = 999;
  209. #else
  210.     message.requestID = atoi(shellPID->lv_Value);
  211. #endif
  212.     message.code = command;
  213.     message.msg.mn_Length = sizeof(struct ST_Message);;
  214.  
  215.     Forbid();
  216.     if( (publicPort = FindPort(ST_PORT)) == NULL )
  217.     {
  218.         Permit();
  219.         if( command == ST_QUIT )
  220.         {
  221.             return(FALSE);
  222.         }
  223.         file = Open("NIL:", MODE_OLDFILE);
  224.         daemonTags[0].ti_Data = file;
  225.         systemStat = SystemTagList("ShellTimerDaemon", daemonTags);
  226.         if( systemStat == 0 )
  227.         {
  228.             if( verbose )
  229.             {
  230.                 Print("Timer daemon loaded.\n");
  231.             }
  232.         }
  233.         else
  234.         {
  235.             Print("Unable to load ShellTimerDaemon!\n");
  236.             return(FALSE);
  237.         }
  238.         /* Give the daemon a little while to start up */
  239.         for( i = 0; i < 4; i++ )
  240.         {
  241.             Delay(25);
  242.             if( FindPort(ST_PORT) != NULL )
  243.             {
  244.                 break;
  245.             }
  246.         }
  247.         Forbid();
  248.     }
  249.  
  250.     if( (publicPort = FindPort(ST_PORT)) == NULL )
  251.     {
  252.         Permit();
  253.         Print("Can't locate timer daemon.\n");
  254.         return(FALSE);
  255.     }
  256.     else
  257.     {
  258.         if( (myPort = CreateMsgPort()) != NULL )
  259.         {
  260.             message.msg.mn_ReplyPort = myPort;
  261.             PutMsg(publicPort,&message);
  262.             Permit();
  263.             WaitPort(myPort);
  264.             DeletePort(myPort);
  265.             return(TRUE);
  266.         }
  267.     }
  268. }
  269.  
  270. void
  271. PrintResults(int command)
  272. {
  273.     if( message.code != ST_ERR )
  274.     {
  275.         switch( message.code )
  276.         {
  277.             case ST_START:
  278.                 if( verbose )
  279.                 {
  280.                     Print("Timer started\n");
  281.                 }
  282.                 break;
  283.             case ST_STOP:
  284.                 if( verbose )
  285.                 {
  286.                     Print("Timer stopped - Elapsed Time: ");
  287.                 }
  288.                 PrintElapsedTime(&(message.diffTime));
  289.                 break;
  290.             case ST_CANCEL:
  291.                 if( verbose )
  292.                 {
  293.                     Print("Timer cancelled\n");
  294.                 }
  295.                 break;
  296.             case ST_QUERY:
  297.                 if( verbose )
  298.                 {
  299.                     Print("Timer Query - Current elapsed time: ");
  300.                 }
  301.                 PrintElapsedTime(&(message.diffTime));
  302.                 break;
  303.             case ST_ERR_NO_PENDING:
  304.                 if( verbose )
  305.                 {
  306.                     Print("No pending timer request\n");
  307.                 }
  308.                 break;
  309.             case ST_TIMEWARP:
  310.                 if( verbose )
  311.                 {
  312.                     Print("Let's do the TimeWarp again!\n");
  313.                 }
  314.                 Print("Error: System clock faulty or reset\n");
  315.                 break;
  316.             case ST_QUIT:
  317.                 Print("ShellTimerDaemon unloaded\n");
  318.                 break;
  319.         }
  320.     }
  321.     else
  322.     {
  323.         Print("ShellTimerDaemon returned an error\n");
  324.     }
  325. }
  326.  
  327. void
  328. PrintElapsedTime(struct timeval *diffTime)
  329. {
  330.     ULONG timedSeconds, days, hours, minutes, seconds;
  331.     char string[80];
  332.  
  333.     timedSeconds = diffTime->tv_secs;
  334.     days = hours = minutes = seconds = 0;
  335.     if( timedSeconds >= SECONDS_PER_DAY )
  336.     {
  337.         days = timedSeconds / SECONDS_PER_DAY;
  338.         timedSeconds %= SECONDS_PER_DAY;
  339.     }
  340.     if( timedSeconds >= SECONDS_PER_HOUR )
  341.     {
  342.         hours = timedSeconds / SECONDS_PER_HOUR;
  343.         timedSeconds %= SECONDS_PER_HOUR;
  344.     }
  345.     if( timedSeconds >= SECONDS_PER_MINUTE )
  346.     {
  347.         minutes = timedSeconds / SECONDS_PER_MINUTE;
  348.         timedSeconds %= SECONDS_PER_MINUTE;
  349.     }
  350.     seconds = timedSeconds;
  351.     timedSeconds = diffTime->tv_secs;
  352.  
  353.     if( verbose )
  354.     {
  355.         if( days > 0 )
  356.         {
  357.             sprintf(string, "%ld Day%s, ", days, days == 1 ? NULL : "s");
  358.             Print(string);
  359.         }
  360.         if( timedSeconds >= SECONDS_PER_HOUR )
  361.         {
  362.             sprintf(string, "%ld Hour%s, ", hours, hours == 1 ? NULL : "s");
  363.             Print(string);
  364.         }
  365.         if( timedSeconds >= SECONDS_PER_MINUTE )
  366.         {
  367.             sprintf(string, "%ld Minute%s, ", minutes, minutes == 1 ? NULL : "s");
  368.             Print(string);
  369.         }
  370.         sprintf(string, "%ld Second%s\n", seconds, seconds == 1 ? NULL : "s");
  371.         Print(string);
  372.     }
  373.     else
  374.     {
  375.         if( days > 0 )
  376.         {
  377.             sprintf(string, "%ld ", hours);
  378.             Print(string);
  379.         }
  380.         sprintf(string, "%02ld:%02ld:%02ld\n", hours, minutes, seconds);
  381.         Print(string);
  382.     }
  383. }
  384.  
  385. void
  386. Print(char *string)
  387. {
  388.     Write(Output(), string, strlen(string));
  389. }
  390.  
  391. void
  392. ShowHelp(void)
  393. {
  394.     Print("\n");
  395.     Print(&versionTag[7]);
  396.     Print("       - A shell-based stopwatch by John Lindwall");
  397.     Print("\n\n" APPNAME " " ARGTEMPLATE);
  398.     Print("\n\n  START  - Starts the timer              STOP    - Stops timer & prints time");
  399.     Print(  "\n  CANCEL - Abort the timer session       QUIT    - Kill daemon and quit");
  400.     Print(  "\n  HELP   - Show help message             VERBOSE - Use wordy messages");
  401.     Print(  "\n  QUERY  - Show current timer value");
  402.     Print(  "\n\nIf no arguments are supplied,  ShellTimer toggles between performing START");
  403.     Print(  "\nand STOP. So, typing 'ShellTimer' once starts the timer; typing 'ShellTimer'");
  404.     Print(  "\nagain will stop the timer and display the result.\n\n");
  405. }
  406.