ArGest Backup User Guide

  1. Home
  2. Docs
  3. ArGest Backup User Guide
  4. Appendix
  5. Appendix H – The brutalk Program

Appendix H – The brutalk Program

The following is a C language source code listing of the brutalk program. brutalk is a simple program that talks to a pair of fifos associated with a run of BRU. It uses the -I option and may be run under the control of the cron program.

NOTE: A compiled version of this program is included in your 
/bru directory.

/*****************************************************

brutalk.c simple program to talk to a pair of fifos for bru
DESCRIPTION
Simple-minded program to talk to a pair of fifos. Use as:
brutalk [-t tty] /bru/bru.r
or
brutalk [-t tty] /bru/bru.q /bru/bru.r

Normally brutalk will attempt to communicate with the user via /dev/tty. The -t option can be used to select any tty type stream to open in place of /dev/tty. We fork to create two processes. The child reads from the fifo where queries are posted and writes to the terminal. The parent reads the replies from the terminal and writes to the fifo where replies are expected. There are basically three normal ways to exit:
Before attempting to open explicitly named input and output fifos, we set a timer. If the timer goes off because bru has not yet opened the other end of the fifos, then we get a SIGALRM and exit. This basically means that either bru has exited normally, or has not yet requested any interaction.
Note that the timeout is only effective until bru opens the fifos for the first time. If you answer one query using brutalk, then interrupt brutalk, and come back and run it again later, it will wait until the next query is available. The initial timeout can be avoided by using the redirection form, since it is actually the shell that is opening the fifos in that case. The child dies when the program posting queries exits, closing the write side of the query fifo. The parent gets notified that the child has died by a SIGCLD and itself exits.
If the user types a ^D (EOF) then the parent sends the child a kill signal and exits. The original client at the other end of the fifos continues to execute. If it knows how to deal gracefully with the fact that we have exited (by closing and reopening the fifos), then we can reattach at a later time to answer more queries.
This program is normally used to interact with bru when bru is executed from cron by a command that includes the arguments:

-I q,/bru/bru.q (send queries to fifo bru.q)
-I r,/bru/bru.r (read replies from fifo bru.r)
-I l,/tmp/brulog (send verbosity info here)
The main function returns 1 to satisfy lint and also to cover the “impossible case” where exit returns rather than exiting.
AUTHOR
Fred Fish
Tim Jones

NOTE: This code sample is intended as an example ONLY. It will NOT compile as it exists. The finished version of brutalk is included with your BRU distribution and can be found in the /bru directory.
*/

#include
#include
#include
#include
#ifndef SIGCLD
#define SIGCLD SIGCHLD /* If no SIGCLD or SIGCHLD, we croak */
#endif
#if HAVE_PID_T
typedef pid_t PID_T;
#else
typedef int PID_T;
#endif
extern void perror ();
extern void exit ();
extern unsigned alarm ();
static void openfiles ();
static void passdata ();
static int rfifo;
static int wfifo;
static int ttyf;
int main (argc, argv)
int argc;
char *argv[];
{
int optchar;
char *infifo = NULL;
char *outfifo = NULL;
char *tty = NULL;
extern int optind;
extern char *optarg;
while ((optchar = getopt (argc, argv, “t:”)) != EOF) {
switch (optchar) {
case ‘t’:
tty = optarg;
break;
case ‘?’:
exit (1);
break;
}
}
for ( ; optind < argc; optind) { if (infifo == NULL) { infifo = argv[optind]; } else if (outfifo == NULL) { outfifo = argv[optind]; } else if (tty == NULL) { tty = argv[optind]; } else { fprintf (stderr, “brutalk: too many arguments\n”); fprintf (stderr, “usage: brutalk readfifo writefifo\n”); exit (1); } } if (tty == NULL) { tty = “/dev/tty”; } (void) signal (SIGALRM, exit); (void) alarm (5); openfiles (infifo, outfifo, tty); (void) alarm (0); passdata (); exit (0); return (1); } /* Open the read and write fifos, and the terminal stream. Any failure is fatal with an error message printed. */ static void openfiles (rname, wname, ttyname) char *rname; char *wname; char *ttyname; { if (rname == NULL) { rfifo = 0; } else if ((rfifo = open (rname, O_RDONLY)) == -1) { fprintf (stderr, “brutalk: can’t open ‘%s’”, rname); perror (“”); exit (1); } if (wname == NULL) { wfifo = 1; } else if ((wfifo = open (wname, O_WRONLY)) == -1) { fprintf (stderr, “brutalk: can’t open ‘%s’”, wname); perror (“”); exit (1); } if ((ttyf = open (ttyname, O_RDWR)) == -1) { fprintf (stderr, “brutalk: can’t open ‘%s’”, ttyname); perror (“”); exit (1); } } /* Fork to create bidirectional data paths and then loop, passing data through each path until a termination condition occurs. */ static void passdata () { int inbytes; int outbytes; int pid; char inbuf[1024]; char outbuf[1024]; if ((pid = fork ()) == -1) { perror (“brutalk: can’t fork”); exit (1); } else if (pid == 0) { while ((inbytes = read (rfifo, inbuf, sizeof(inbuf))) > 0) {
(void) write (ttyf, inbuf, (unsigned) inbytes);
}
} else {
(void) signal (SIGCLD, exit);
while ((outbytes = read (ttyf, outbuf,
sizeof (outbuf))) > 0) {
(void) write (wfifo, outbuf, (unsigned) outbytes);
}
(void) kill ((PID_T) pid, SIGTERM);
}
}