Passing Parameters to a C Program using the Command Line.

The section shows how to pass information to a C program using command line parameters using argc and argv. It also shows how to determine whether a sscanf failed.

This program was used in an application, where a PC was controlling critical tasks. Lets call it PC_critical. Unfortunately, PC_critical occasionally stalled and had to be manually reset.

Thus, a second PC (PC_monitor) was used. PC_critical was to send a message to PC_monitor every five minutes to assure that it was "alive". If no message was received, PC_monitor forced a hard reset of PC_critical by applying a momentary relay closure across the manual reset switch on PC_critical. The operation of the relay was caused by outputting the pattern 0x0a on the Data Port.

The end user was uncertain as to how long the closure was to be applied and we were uncertain as to the address of the parallel port. Thus, to provide maximum flexibility while enabling us to get on with the development, it was decided to pass the time and parallel port address via the command line. For example;

     hdboot 5 0x0378

was to be interpreted as forcing a closure for 500 ms using parallel port address 0x0378.

Note that in the following program, main is declared with arguments;

     int main(int argc, char *argv[])

When a user types (or another process calls this program) with the command;

     hdboot 5 0x0378

argc is set to the number of arguments appearing on the command line. In this case, it is three. In fact, in this example, anything other than three would be invalid.

Note that argv is an array of pointers to strings. Sufficient memory is allocated by the compiler to accommodate each argument as a null terminated string and each argument is placed into each of these string locations.

Thus, in the example, argv[0] would contain "hdboot", argv[1] would contain "5" and argv[2] would contain "0x0378".

Note that in the following program, if the number of arguments is not three, the program is exited with a value of -1. This value is returned to the calling process which may be used for some purpose. (Note that main is declared as returning an integer). Negative values are usually reserved for error conditions.

Argument 1 is then converted to an integer using;

     sscanf(argv[1], "%d", &tenths_sec);
However, the function sscanf actually returns an integer which is equal to the number of parameters that were successfully converted. Thus, this is tested;

     if (sscanf(argv[1], "%d", &tenths_sec) != 1)
     {
        /* it is an error */
        exit(-2);
     }

Thus, erroneous commands where the time parameter is a letter or punctuation the program is exited with a negative value.

The same process is used in obtaining the address of the parallel port;

     if (sscanf(argv[2], "%x", &Data) != 1)
     {
        /* it is an error */
        exit(-3);
     }

Clearly, more error checking could have been done. For example checking to eliminate negative values of the relay's "on" time and in the case of the address of the parallel port, the variable Data could have been tested to assure that it was a valid address; i.e., 0x03bc, 0x0378, 0x0278, etc.

Note that on successful completion, the program is exited with the value of 0.

/*
** Program HDBT
**
** Causes operation of relay for time period specified on command line. 
** Parallel port address passed on command line.
**
** Sample call:   HDBT 5 0x0378
**
** Operates relay for 5*100 msecs.  Parallel port at address 0x0378. 
**
** Towanda L. Malone, Baltimore, MD, Oct 11, '96
*/

#include <stdio.h>
#include <conio.h>
#include <dos.h>
#include <process.h>

int main(int argc, char *argv[])
{
   unsigned int t_delay, Data;
   int tenths_sec;

   clrscr();

   if(argc != 3)
   {
      printf("Incorrect number of args\n");
      exit(-1);
   }
   if(sscanf(argv[1],"%d", &tenths_sec)!=1)
   {
      printf("Time scanf failed.\n");
      exit(-2);
   }
   if (sscanf(argv[2],"%x", &Data) != 1)
   {
      printf("Parallel port scanf failed.\n");
      exit(-3);
   }
   t_delay = tenths_sec * 100;
   outportb(Data, 0x0a); /* operate the relay */
   delay(t_delay);
   outportb(Data, 0x00); /* release it */
   exit(0);
}