2 * Copyright (c) 1997, 2001 Hellmuth Michaelis. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 *---------------------------------------------------------------------------
27 * exec.h - supplemental program/script execution
28 * ----------------------------------------------
30 * $FreeBSD: src/usr.sbin/i4b/isdnd/exec.c,v 1.6.2.4 2001/12/10 09:42:52 hm Exp $
31 * $DragonFly: src/usr.sbin/i4b/isdnd/exec.c,v 1.3 2004/03/26 00:30:12 cpressey Exp $
33 * last edit-date: [Mon Dec 10 10:39:53 2001]
35 *---------------------------------------------------------------------------*/
40 #include <sys/socket.h>
42 #include <netinet/in.h>
43 #include <arpa/inet.h>
48 static struct pid_tab
{
53 /*---------------------------------------------------------------------------*
54 * SIGCHLD signal handler
55 *---------------------------------------------------------------------------*/
57 sigchild_handler(int sig
)
63 if((pid
= waitpid(-1, &retstat
, WNOHANG
)) <= 0)
65 log(LL_ERR
, "ERROR, sigchild_handler, waitpid: %s", strerror(errno
));
66 error_exit(1, "ERROR, sigchild_handler, waitpid: %s", strerror(errno
));
70 if(WIFEXITED(retstat
))
72 DBGL(DL_PROC
, (log(LL_DBG
, "normal child (pid=%d) termination, exitstat = %d",
73 pid
, WEXITSTATUS(retstat
))));
75 else if(WIFSIGNALED(retstat
))
77 if(WCOREDUMP(retstat
))
78 log(LL_WRN
, "child (pid=%d) termination due to signal %d (coredump)",
79 pid
, WTERMSIG(retstat
));
81 log(LL_WRN
, "child (pid=%d) termination due to signal %d",
82 pid
, WTERMSIG(retstat
));
86 /* check if hangup required */
88 for(i
=0; i
< MAX_PIDS
; i
++)
90 if(pid_tab
[i
].pid
== pid
)
92 if(pid_tab
[i
].cep
->cdid
!= CDID_UNUSED
)
94 DBGL(DL_PROC
, (log(LL_DBG
, "sigchild_handler: scheduling hangup for cdid %d, pid %d",
95 pid_tab
[i
].cep
->cdid
, pid_tab
[i
].pid
)));
96 pid_tab
[i
].cep
->hangup
= 1;
104 /*---------------------------------------------------------------------------*
105 * execute prog as a subprocess and pass an argumentlist
106 *---------------------------------------------------------------------------*/
108 exec_prog(char *prog
, char **arglist
)
110 char tmp
[MAXPATHLEN
];
111 char path
[MAXPATHLEN
+1];
115 snprintf(path
, sizeof(path
), "%s/%s", ETCPATH
, prog
);
121 for(a
=1; arglist
[a
] != NULL
; ++a
)
124 strcat(tmp
, arglist
[a
]);
127 DBGL(DL_PROC
, (log(LL_DBG
, "exec_prog: %s, args:%s", path
, tmp
)));
132 log(LL_ERR
, "ERROR, exec_prog/fork: %s", strerror(errno
));
133 error_exit(1, "ERROR, exec_prog/fork: %s", strerror(errno
));
136 default: /* parent */
140 /* this is the child now */
143 * close files used only by isdnd, e.g.
145 * 2. /var/log/isdnd.acct (or similar, when used)
146 * 3. /var/log/isdnd.log (or similar, when used)
150 if(useacctfile
&& acctfp
)
153 if(uselogfile
&& logfp
)
156 if(execvp(path
,arglist
) < 0 )
162 /*---------------------------------------------------------------------------*
163 * run interface up/down script
164 *---------------------------------------------------------------------------*/
166 exec_connect_prog(cfg_entry_t
*cep
, const char *prog
, int link_down
)
168 char *argv
[32], **av
= argv
;
169 char devicename
[MAXPATHLEN
], addr
[100];
174 /* the obvious things */
175 device
= bdrivername(cep
->usrdevicename
);
176 snprintf(devicename
, sizeof(devicename
), "%s%d", device
, cep
->usrdeviceunit
);
181 *av
++ = link_down
? "down" : "up";
183 /* try to figure AF_INET address of interface */
185 memset(&ifr
, 0, sizeof ifr
);
186 ifr
.ifr_addr
.sa_family
= AF_INET
;
187 strncpy(ifr
.ifr_name
, devicename
, sizeof(ifr
.ifr_name
));
188 s
= socket(AF_INET
, SOCK_DGRAM
, 0);
190 if (ioctl(s
, SIOCGIFADDR
, (caddr_t
)&ifr
) >= 0) {
191 struct sockaddr_in
*sin
= (struct sockaddr_in
*)&ifr
.ifr_addr
;
192 strcpy(addr
, inet_ntoa(sin
->sin_addr
));
202 return exec_prog((char*)prog
, argv
);
205 /*---------------------------------------------------------------------------*
206 * run answeringmachine application
207 *---------------------------------------------------------------------------*/
209 exec_answer(cfg_entry_t
*cep
)
212 u_char devicename
[MAXPATHLEN
];
216 device
= bdrivername(cep
->usrdevicename
);
218 snprintf(devicename
, sizeof(devicename
), "%si4b%s%d", _PATH_DEV
, device
,
221 argv
[0] = cep
->answerprog
;
223 argv
[2] = devicename
;
230 /* if destination telephone number avail, add it as argument */
232 if(*cep
->local_phone_incoming
)
233 argv
[4] = cep
->local_phone_incoming
;
235 /* if source telephone number avail, add it as argument */
237 if(*cep
->real_phone_incoming
)
238 argv
[6] = cep
->real_phone_incoming
;
243 argv
[8] = cep
->display
;
249 DBGL(DL_PROC
, (log(LL_DBG
, "exec_answer: prog=[%s]", cep
->answerprog
)));
251 pid
= exec_prog(cep
->answerprog
, argv
);
253 /* enter pid and conf ptr entry addr into table */
259 for(i
=0; i
< MAX_PIDS
; i
++)
261 if(pid_tab
[i
].pid
== 0)
263 pid_tab
[i
].pid
= pid
;
264 pid_tab
[i
].cep
= cep
;
273 /*---------------------------------------------------------------------------*
274 * check if a connection has an outstanding process, if yes, kill it
275 *---------------------------------------------------------------------------*/
277 check_and_kill(cfg_entry_t
*cep
)
281 for(i
=0; i
< MAX_PIDS
; i
++)
283 if(pid_tab
[i
].cep
== cep
)
287 DBGL(DL_PROC
, (log(LL_DBG
, "check_and_kill: killing pid %d", pid_tab
[i
].pid
)));
297 /*---------------------------------------------------------------------------*
298 * update budget callout/callback statistics counter file
299 *---------------------------------------------------------------------------*/
301 upd_callstat_file(char *filename
, int rotateflag
)
310 fp
= fopen(filename
, "r+");
314 /* file not there, create it and exit */
316 log(LL_WRN
, "upd_callstat_file: creating %s", filename
);
318 fp
= fopen(filename
, "w");
321 log(LL_ERR
, "ERROR, upd_callstat_file: cannot create %s, %s", filename
, strerror(errno
));
325 ret
= fprintf(fp
, "%ld %ld 1", now
, now
);
327 log(LL_ERR
, "ERROR, upd_callstat_file: fprintf failed: %s", strerror(errno
));
335 ret
= fscanf(fp
, "%ld %ld %d", &s
, &l
, &n
);
343 /* file corrupt ? anyway, initialize */
345 log(LL_WRN
, "upd_callstat_file: initializing %s", filename
);
356 /* get day of month for last timestamp */
357 stmp
= localtime(&l
);
360 /* get day of month for just now */
361 stmp
= localtime(&now
);
363 if(dom
!= stmp
->tm_mday
)
366 char buf
[MAXPATHLEN
];
368 /* new day, write last days stats */
370 sprintf(buf
, "%s-%02d", filename
, stmp
->tm_mday
);
372 nfp
= fopen(buf
, "w");
375 log(LL_ERR
, "ERROR, upd_callstat_file: cannot open for write %s, %s", buf
, strerror(errno
));
379 ret
= fprintf(nfp
, "%ld %ld %d", s
, l
, n
);
381 log(LL_ERR
, "ERROR, upd_callstat_file: fprintf failed: %s", strerror(errno
));
385 /* init new days stats */
389 log(LL_WRN
, "upd_callstat_file: rotate %s, new s=%ld l=%ld n=%d", filename
, s
, l
, n
);
393 n
++; /* increment call count */
396 * the "%-3d" is necessary to overwrite any
397 * leftovers from previous contents!
400 ret
= fprintf(fp
, "%ld %ld %-3d", s
, now
, n
);
403 log(LL_ERR
, "ERROR, upd_callstat_file: fprintf failed: %s", strerror(errno
));