2 * Copyright (c) 1997, 2000 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 * $Id: exec.c,v 1.10 2009/04/16 05:56:32 lukem Exp $
34 * last edit-date: [Wed Sep 27 09:39:22 2000]
36 *---------------------------------------------------------------------------*/
41 #include <sys/socket.h>
43 #include <netinet/in.h>
44 #include <arpa/inet.h>
48 static struct pid_tab
{
50 struct cfg_entry
*cep
;
53 /*---------------------------------------------------------------------------*
54 * SIGCHLD signal handler
55 *---------------------------------------------------------------------------*/
57 sigchild_handler(int sig
)
63 if ((pid
= waitpid(-1, &retstat
, WNOHANG
)) <= 0)
65 logit(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
, (logit(LL_DBG
, "normal child (pid=%d) termination, exitstat = %d",
73 pid
, WEXITSTATUS(retstat
))));
75 else if (WIFSIGNALED(retstat
))
77 if (WCOREDUMP(retstat
))
78 logit(LL_WRN
, "child (pid=%d) termination due to signal %d (coredump)",
79 pid
, WTERMSIG(retstat
));
81 logit(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
, (logit(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(const char *prog
, const 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
)
123 strlcat(tmp
, " ", sizeof(tmp
));
124 strlcat(tmp
, arglist
[a
], sizeof(tmp
));
127 DBGL(DL_PROC
, (logit(LL_DBG
, "exec_prog: %s, args:%s", path
, tmp
)));
129 switch (pid
= fork())
132 logit(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)
155 if (execvp(path
, __UNCONST(arglist
)) < 0 )
161 /*---------------------------------------------------------------------------*
162 * run interface up/down script
163 *---------------------------------------------------------------------------*/
165 exec_connect_prog(struct cfg_entry
*cep
, const char *prog
, int link_down
)
167 const char *argv
[32], **av
= argv
;
168 char devicename
[MAXPATHLEN
], addr
[100];
172 /* the obvious things */
173 snprintf(devicename
, sizeof(devicename
), "%s%d", cep
->usrdevicename
, cep
->usrdeviceunit
);
178 *av
++ = link_down
? "down" : "up";
180 /* try to figure AF_INET address of interface */
182 memset(&ifr
, 0, sizeof ifr
);
183 ifr
.ifr_addr
.sa_family
= AF_INET
;
184 strncpy(ifr
.ifr_name
, devicename
, sizeof(ifr
.ifr_name
));
185 s
= socket(AF_INET
, SOCK_DGRAM
, 0);
187 if (ioctl(s
, SIOCGIFADDR
, (caddr_t
)&ifr
) >= 0) {
188 struct sockaddr_in
*sin
= (struct sockaddr_in
*)&ifr
.ifr_addr
;
189 strlcpy(addr
, inet_ntoa(sin
->sin_addr
), sizeof(addr
));
199 return exec_prog(prog
, argv
);
202 /*---------------------------------------------------------------------------*
203 * run answeringmachine application
204 *---------------------------------------------------------------------------*/
206 exec_answer(struct cfg_entry
*cep
)
208 const char *argv
[32];
209 char devicename
[MAXPATHLEN
];
212 snprintf(devicename
, sizeof(devicename
), "/dev/%s%d", cep
->usrdevicename
, cep
->usrdeviceunit
);
214 argv
[0] = cep
->answerprog
;
216 argv
[2] = devicename
;
223 /* if destination telephone number avail, add it as argument */
225 if (*cep
->local_phone_incoming
)
226 argv
[4] = cep
->local_phone_incoming
;
228 /* if source telephone number avail, add it as argument */
230 if (*cep
->real_phone_incoming
)
231 argv
[6] = cep
->real_phone_incoming
;
236 argv
[8] = cep
->display
;
242 DBGL(DL_PROC
, (logit(LL_DBG
, "exec_answer: prog=[%s]", cep
->answerprog
)));
244 pid
= exec_prog(cep
->answerprog
, argv
);
246 /* enter pid and conf ptr entry addr into table */
252 for (i
=0; i
< MAX_PIDS
; i
++)
254 if (pid_tab
[i
].pid
== 0)
256 pid_tab
[i
].pid
= pid
;
257 pid_tab
[i
].cep
= cep
;
266 /*---------------------------------------------------------------------------*
267 * check if a connection has an outstanding process, if yes, kill it
268 *---------------------------------------------------------------------------*/
270 check_and_kill(struct cfg_entry
*cep
)
274 for (i
=0; i
< MAX_PIDS
; i
++)
276 if (pid_tab
[i
].cep
== cep
)
280 DBGL(DL_PROC
, (logit(LL_DBG
, "check_and_kill: killing pid %d", pid_tab
[i
].pid
)));
290 /*---------------------------------------------------------------------------*
291 * update budget callout/callback statistics counter file
292 *---------------------------------------------------------------------------*/
294 upd_callstat_file(char *filename
, int rotateflag
)
304 fp
= fopen(filename
, "r+");
308 /* file not there, create it and exit */
310 logit(LL_WRN
, "upd_callstat_file: creating %s", filename
);
312 fp
= fopen(filename
, "w");
315 logit(LL_ERR
, "ERROR, upd_callstat_file: cannot create %s, %s", filename
, strerror(errno
));
319 ret
= fprintf(fp
, "%ld %ld 1", (long)now
, (long)now
);
321 logit(LL_ERR
, "ERROR, upd_callstat_file: fprintf failed: %s", strerror(errno
));
329 ret
= fscanf(fp
, "%ld %ld %d", &s_in
, &l_in
, &n
);
338 /* file corrupt ? anyway, initialize */
340 logit(LL_WRN
, "upd_callstat_file: initializing %s", filename
);
351 /* get day of month for last timestamp */
352 stmp
= localtime(&l
);
355 /* get day of month for just now */
356 stmp
= localtime(&now
);
358 if (dom
!= stmp
->tm_mday
)
361 char buf
[MAXPATHLEN
];
363 /* new day, write last days stats */
365 snprintf(buf
, sizeof(buf
), "%s-%02d", filename
,
368 nfp
= fopen(buf
, "w");
371 logit(LL_ERR
, "ERROR, upd_callstat_file: cannot open for write %s, %s", buf
, strerror(errno
));
375 ret
= fprintf(nfp
, "%ld %ld %d", (long)s
, (long)l
, n
);
377 logit(LL_ERR
, "ERROR, upd_callstat_file: fprintf failed: %s", strerror(errno
));
381 /* init new days stats */
385 logit(LL_WRN
, "upd_callstat_file: rotate %s, new s=%ld l=%ld n=%d", filename
, s
, l
, n
);
389 n
++; /* increment call count */
392 * the "%-3d" is necessary to overwrite any
393 * leftovers from previous contents!
396 ret
= fprintf(fp
, "%ld %ld %-3d", (long)s
, (long)now
, n
);
399 logit(LL_ERR
, "ERROR, upd_callstat_file: fprintf failed: %s", strerror(errno
));