Listing 3

void idle(unsigned priority)
{
       printf("idle @ %3u\n", priority);
}

/* --------------------------------------------------------- */

void pro1(unsigned priority)
{
       printf("pro1 @ %3u\n", priority);
}

/* --------------------------------------------------------- */

void pro2(unsigned priority)
{
       printf("pro2 @ %3u\n", priority);
}

/* --------------------------------------------------------- */

void pro3(unsigned priority)
{
       printf("pro3 @ %3u\n", priority);
}

/* --------------------------------------------------------------

FUNCTION PROC_CMD: The steps to process a command are:

Note that handlers registered using signal require one int argument.
When a handler is invoked, the argument passed to it is the type of
signal that caused its invocation. Since, in this case it is always
SIGINT, the argument is never used within this handler.

actions is a jump table whose index is the menu option chosen by
the user.

A.  Since we have just trapped a SIGINT signal, the library will now
    revert to using the SIG_DFL method for future SIGINT signals that
    occur while this signal handler is executing. This default
    method generally results in the program being abnormally
    terminated and that is unsuitable behavior here. As such, we ask
    to have such signals ignored until we are again ready to them.

B.  Prompt the user for their menu choice.

C.  Call the corresponding function.

D.  Reregister this handler for future SIGINT signals.

-------------------------------------------------------------- */

void proc_cmd(int dummy)
{
       int code;
       static const void (*actions[])(void) = {
              myexit,
              help,
              add_node

       };

/*A*/   if (signal(SIGINT, SIG_IGN) == SIG_ERR) {
              fprintf(stderr, "can't ignore signal\n");
              exit(EXIT_FAILURE);
       }

       while (1) {
/*B*/            printf("\nEnter Action Code (1 for help): ");
              scanf("%d", &code);

              if (code < 0 || code >= NUMELEM(actions)) {
                     fprintf(stderr, "\n  Invalid command\n");
                     continue;
              }

/*C*/           (*actions[code])();       /* call selected action */
              break;
       }

/*D*/   if (signal(SIGINT, proc_cmd) == SIG_ERR) {
              fprintf(stderr, "can't register handler\n");
              exit(EXIT_FAILURE);
       }
}

/* ----------------------------------------------------------- */

void myexit(void)
{
       exit(EXIT_SUCCESS);
}

/* ----------------------------------------------------------- */

void help(void)
{
       printf("\n The action codes are:\n");
       printf("\t0 - Exit this program\n");
       printf("\t1 - Produce this help message\n");
       printf("\t2 - Add a node\n");
}

/* -------------------------------------------------------------

FUNCTION ADD_NODE: The steps to add a new node to the list in
       ascending alphabetic order are:

Note that process_name_table is a lookup table that allows a
user-entered process name to be translated to the corresponding
processing function.

A.  Get the process name and priority from the user.

B.  Get a free node from free node list. If no more, complain and
    get out.

C.  Find place to insert new node. The pointer returned from
    locate_node is the address of the node after which the new
    node should be inserted.

D.  Insert new node and initialize its members. Since the list is
    maintained in decreasing order of priority, we need to update
    the root pointer when a new higher priority process node
    arrives. If the new node's priority equals to the current
    highest priority, the new node is inserted ahead of that
    duplicate.

-------------------------------------------------------------- */

void add_node(void)
{
       int i;
       Node *pnew_node;        /* ptr to new node */
       Node *ploc_node;        /* ptr to located node */
       char process_name[21];  /* selected process name */
       unsigned priority;      /* function priority */
       static const struct {
              char *ppname;
              void (*pprocess)(unsigned);
       } process_name_table[] = {
              {"pro1", pro1},
              {"pro2", pro2},
              {"pro3", pro3}
       };
       static unsigned highest_priority = 0;

/*A*/   while (1) {
              printf("\n Enter process name: ");
              scanf("%20s", process_name);

              for (i = 0; i < NUMELEM(process_name_table); ++i) {
                    if (strcmp(process_name_table[i].ppname,
                       process_name) == 0)
                          goto found;
              }

              printf("invalid process name\n");
       }

found:  while (1) {
              printf("\n Enter process priority: ");
              scanf("%3u", &priority);
              if (priority > 0 && priority <= 100) {
                     break;
              }

              printf("1<=priority<=100\n");
       }

/*B*/   pnew_node = get_free_node();
       if (pnew_node == NULL) {
              printf("\n   No nodes available\n");
              return;
       }

/*C*/   ploc_node = locate_node(priority, INEXACT);

/*D*/   pnew_node->pfwd = ploc_node->pfwd;
       pnew_node->pbwd = ploc_node;
       ploc_node->pfwd = pnew_node;
       pnew_node->pfwd->pbwd = pnew_node;
       pnew_node->process = process_name_table[i].pprocess;
       pnew_node->priority = priority;
       if (priority >= highest_priority) {
              proot_node = pnew_node;
              highest_priority = priority;
       }

       printf(" Node added\n");
}

/* End of File */