1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
|
/*
# 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);
}
|