188 lines
5.0 KiB
C
188 lines
5.0 KiB
C
/*
|
|
# File: dialHDB.c
|
|
# Author: Daniel Hagerty , hag@eddie.mit.edu
|
|
# Copyright (C) 1993
|
|
# Date: Fri Nov 26 19:22:31 1993
|
|
# Description: Program for using HDB dialers for dialing modems, exiting
|
|
with 0 on success, else failure.
|
|
# Version: 1.0
|
|
# Revision History:
|
|
######
|
|
### 11/26/93 Hag - File creation
|
|
######
|
|
### 1/5/94 Hag - Finally got around to finishing this damn thing.
|
|
######
|
|
*/
|
|
/* Basic theory behind this program-
|
|
dialHDB forks into two processes, a monitor parent, and a child
|
|
that does the exec of the dialer. Child pretty much just execs the
|
|
dialer program, unless there's an exec problem, in which case the
|
|
child sends the parent a SIGUSR1 to indicate failed execution.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <sys/types.h>
|
|
#include <sys/wait.h>
|
|
#include <signal.h>
|
|
|
|
#define kUsage "Usage:\n\t%s dialerPath device number speed\n\
|
|
%s dialer -h device speed\n"
|
|
|
|
#define kExitErrFlag 0x80 /* & in with exit code to determine error */
|
|
#define kErrorMask 0x0f /* Mask to determine error code */
|
|
|
|
/* Error code defines as lifted from an HDB dialer */
|
|
#define RCE_NULL 0 /* general purpose or unknown error code */
|
|
#define RCE_INUSE 1 /* line in use */
|
|
#define RCE_SIG 2 /* signal aborted dialer */
|
|
#define RCE_ARGS 3 /* invalid arguments */
|
|
#define RCE_PHNO 4 /* invalid phone number */
|
|
#define RCE_SPEED 5 /* invalid baud rate -or- bad connect baud */
|
|
#define RCE_OPEN 6 /* can't open line */
|
|
#define RCE_IOCTL 7 /* ioctl error */
|
|
#define RCE_TIMOUT 8 /* timeout */
|
|
#define RCE_NOTONE 9 /* no dial tone */
|
|
#define RCE_BUSY 13 /* phone is busy */
|
|
#define RCE_NOCARR 14 /* no carrier */
|
|
#define RCE_ANSWER 15 /* no answer */
|
|
|
|
/* Structure definition to map error codes to strings */
|
|
typedef struct
|
|
{
|
|
int errNum;
|
|
char *errString;
|
|
} errTable;
|
|
|
|
const errTable errors[]=
|
|
{
|
|
{ RCE_NULL, "Unknown Error" },
|
|
{ RCE_INUSE, "Line is being used" },
|
|
{ RCE_SIG, "Recieved fatal signal" },
|
|
{ RCE_ARGS, "Bad arguments" },
|
|
{ RCE_PHNO, "Invalid phone number" },
|
|
{ RCE_SPEED, "Invalid baud rate or bad connection" },
|
|
{ RCE_OPEN, "Unable to open line" },
|
|
{ RCE_IOCTL, "ioctl error" },
|
|
{ RCE_TIMOUT, "Timed out" },
|
|
{ RCE_NOTONE, "No dialtone" },
|
|
{ RCE_BUSY, "Phone number is busy" },
|
|
{ RCE_NOCARR, "No carrier" },
|
|
{ RCE_ANSWER, "No answer" },
|
|
{ 0,NULL}
|
|
};
|
|
|
|
/* Function Prototypes */
|
|
int figureStat(int stat);
|
|
char *findInTable(int error);
|
|
void badExec(void);
|
|
|
|
char *dialerName; /* basename of our dialer program */
|
|
char *dialerPath; /* full path of dialer program */
|
|
|
|
main(int argc,char *argv[])
|
|
{
|
|
int parent; /* pid of parent process */
|
|
int child; /* pid of child process */
|
|
int stat; /* exit status of child process */
|
|
char *temp; /* used to get basename of dialer */
|
|
|
|
if(argc!=5)
|
|
{
|
|
fprintf(stderr,kUsage,argv[0],argv[0]);
|
|
exit(1);
|
|
}
|
|
|
|
dialerPath=argv[1];
|
|
dialerName= (temp=strrchr(argv[1],'/'))!=NULL ? temp+1 : argv[1];
|
|
|
|
parent=getpid();
|
|
|
|
signal(SIGUSR1,badExec); /* set up for possible failed exec */
|
|
|
|
if((child=fork())<0)
|
|
{
|
|
perror("fork");
|
|
exit(2);
|
|
}
|
|
if(child>0) /* We're parent, wait for child to exit */
|
|
{
|
|
/* Set up to ignore signals so we can report them on stderror */
|
|
signal(SIGHUP,SIG_IGN);
|
|
signal(SIGINT,SIG_IGN);
|
|
signal(SIGTERM,SIG_IGN);
|
|
|
|
wait(&stat); /* wait for child to exit */
|
|
exit(figureStat(stat)); /* figure out our exit code and die */
|
|
}
|
|
else /* child process */
|
|
{
|
|
close(0); /* close of modem file desc, since HDB */
|
|
close(1); /* doesn't use them */
|
|
dup2(2,1); /* and remap stdout to stderr, just in case */
|
|
if(execvp(argv[1],argv+1)<0) /* exec program with argv shifted by 1 */
|
|
{ /* if exec fails, send SIGUSR1 to parent */
|
|
kill(parent,SIGUSR1);
|
|
exit(0);
|
|
}
|
|
}
|
|
exit(0);
|
|
}
|
|
|
|
/* Figure out whether or not dialer ran succesfully, and return
|
|
with 0 if it worked, otherwise error */
|
|
int figureStat(int stat)
|
|
{
|
|
int exit;
|
|
int errFlag;
|
|
int error;
|
|
|
|
if(WIFSIGNALED(stat)) /* determine if exit was from signal or what */
|
|
{
|
|
fprintf(stderr,"Error: Dialer %s recieved signal %d.\n",dialerName,
|
|
WTERMSIG(stat));
|
|
return(1);
|
|
}
|
|
if(WIFSTOPPED(stat))
|
|
{
|
|
fprintf(stderr,"Error: Dialer %s recieved signal %d.\n",dialerName,
|
|
WSTOPSIG(stat));
|
|
return(1);
|
|
}
|
|
exit=WEXITSTATUS(stat);
|
|
|
|
errFlag=exit&kExitErrFlag; /* Is the error flag set? */
|
|
if(errFlag)
|
|
{
|
|
char *errString;
|
|
|
|
error=exit&kErrorMask;
|
|
errString=findInTable(error); /* find it's string, print it on stderr */
|
|
fprintf(stderr,"Error: %s - %s.\n",dialerName,errString); /* and return */
|
|
return(1);
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
/* Support routine, look up exit code in error table, and return pointer
|
|
to proper string */
|
|
char *findInTable(int error)
|
|
{
|
|
int i=0;
|
|
|
|
for(i=0;errors[i].errString!=NULL;i++)
|
|
{
|
|
if(errors[i].errNum==error)
|
|
return(errors[i].errString);
|
|
}
|
|
/* Still here, return the top entry, for unknown error */
|
|
return(errors[0].errString);
|
|
}
|
|
|
|
/* Called by signal if we recieve SIGUSR 1 */
|
|
void badExec(void)
|
|
{
|
|
fprintf(stderr,"Error: %s - Execution problem.\n",dialerPath);
|
|
exit(1);
|
|
}
|