summaryrefslogtreecommitdiffstats
path: root/usr.sbin/i4b/isdnd/exec.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/i4b/isdnd/exec.c')
-rw-r--r--usr.sbin/i4b/isdnd/exec.c280
1 files changed, 280 insertions, 0 deletions
diff --git a/usr.sbin/i4b/isdnd/exec.c b/usr.sbin/i4b/isdnd/exec.c
new file mode 100644
index 0000000..1ed81a1
--- /dev/null
+++ b/usr.sbin/i4b/isdnd/exec.c
@@ -0,0 +1,280 @@
+/*
+ * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * exec.h - supplemental program/script execution
+ * ----------------------------------------------
+ *
+ * $Id: exec.c,v 1.10 1998/12/05 18:03:11 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:06:49 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#include "isdnd.h"
+
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#define MAX_PIDS 32
+
+static struct pid_tab {
+ pid_t pid;
+ cfg_entry_t *cep;
+} pid_tab[MAX_PIDS];
+
+/*---------------------------------------------------------------------------*
+ * SIGCHLD signal handler
+ *---------------------------------------------------------------------------*/
+void
+sigchild_handler(int sig)
+{
+ int retstat;
+ register int i;
+ pid_t pid;
+
+ if((pid = waitpid(-1, &retstat, WNOHANG)) <= 0)
+ {
+ log(LL_ERR, "ERROR, waitpid: %s", strerror(errno));
+ do_exit(1);
+ }
+ else
+ {
+ if(WIFEXITED(retstat))
+ {
+ DBGL(DL_PROC, (log(LL_DBG, "normal child (pid=%d) termination, exitstat = %d",
+ pid, WEXITSTATUS(retstat))));
+ }
+ else if(WIFSIGNALED(retstat))
+ {
+ if(WCOREDUMP(retstat))
+ log(LL_WRN, "child (pid=%d) termination due to signal %d (coredump)",
+ pid, WTERMSIG(retstat));
+ else
+ log(LL_WRN, "child (pid=%d) termination due to signal %d",
+ pid, WTERMSIG(retstat));
+ }
+ }
+
+ /* check if hangup required */
+
+ for(i=0; i < MAX_PIDS; i++)
+ {
+ if(pid_tab[i].pid == pid)
+ {
+ if(pid_tab[i].cep->cdid != CDID_UNUSED)
+ {
+ DBGL(DL_PROC, (log(LL_DBG, "sigchild_handler: scheduling hangup for cdid %d, pid %d",
+ pid_tab[i].cep->cdid, pid_tab[i].pid)));
+ pid_tab[i].cep->hangup = 1;
+ }
+ pid_tab[i].pid = 0;
+ break;
+ }
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * execute prog as a subprocess and pass an argumentlist
+ *---------------------------------------------------------------------------*/
+pid_t
+exec_prog(char *prog, char **arglist)
+{
+ char tmp[MAXPATHLEN];
+ char path[MAXPATHLEN+1];
+ pid_t pid;
+ int a;
+
+ sprintf(path, "%s/%s", ETCPATH, prog);
+
+ arglist[0] = path;
+
+ tmp[0] = '\0';
+
+ for(a=1; arglist[a] != NULL; ++a )
+ {
+ strcat(tmp, " " );
+ strcat(tmp, arglist[a]);
+ }
+
+ DBGL(DL_PROC, (log(LL_DBG, "exec_prog: %s, args:%s", path, tmp)));
+
+ switch(pid = fork())
+ {
+ case -1: /* error */
+ log(LL_ERR, "ERROR, exec_prog/fork: %s", strerror(errno));
+ do_exit(1);
+ case 0: /* child */
+ break;
+ default: /* parent */
+ return(pid);
+ }
+
+ /* this is the child now */
+
+ if(execvp(path,arglist) < 0 )
+ _exit(127);
+
+ return(-1);
+}
+
+/*---------------------------------------------------------------------------*
+ * run interface up/down script
+ *---------------------------------------------------------------------------*/
+int
+exec_connect_prog(cfg_entry_t *cep, const char *prog, int link_down)
+{
+ char *argv[32], **av = argv;
+ char devicename[MAXPATHLEN], addr[100];
+ char *device;
+ int s;
+ struct ifreq ifr;
+
+ /* the obvious things */
+ device = bdrivername(cep->usrdevicename);
+ sprintf(devicename, "%s%d", device, cep->usrdeviceunit);
+ *av++ = (char*)prog;
+ *av++ = "-d";
+ *av++ = devicename;
+ *av++ = "-f";
+ *av++ = link_down ? "down" : "up";
+
+ /* try to figure AF_INET address of interface */
+ addr[0] = '\0';
+ memset(&ifr, 0, sizeof ifr);
+ ifr.ifr_addr.sa_family = AF_INET;
+ strncpy(ifr.ifr_name, devicename, sizeof(ifr.ifr_name));
+ s = socket(AF_INET, SOCK_DGRAM, 0);
+ if (s >= 0) {
+ if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) >= 0) {
+ struct sockaddr_in *sin = (struct sockaddr_in *)&ifr.ifr_addr;
+ strcpy(addr, inet_ntoa(sin->sin_addr));
+ *av++ = "-a";
+ *av++ = addr;
+ }
+ close(s);
+ }
+
+ /* terminate argv */
+ *av++ = NULL;
+
+ return exec_prog((char*)prog, argv);
+}
+
+/*---------------------------------------------------------------------------*
+ * run answeringmachine application
+ *---------------------------------------------------------------------------*/
+int
+exec_answer(cfg_entry_t *cep)
+{
+ char *argv[32];
+ u_char devicename[MAXPATHLEN];
+ int pid;
+ char *device;
+
+ device = bdrivername(cep->usrdevicename);
+
+ sprintf(devicename, "/dev/i4b%s%d", device, cep->usrdeviceunit);
+
+ argv[0] = cep->answerprog;
+ argv[1] = "-D";
+ argv[2] = devicename;
+ argv[3] = "-d";
+ argv[4] = "unknown";
+ argv[5] = "-s";
+ argv[6] = "unknown";
+ argv[7] = NULL;
+
+ /* if destination telephone number avail, add it as argument */
+
+ if(*cep->local_phone_incoming)
+ argv[4] = cep->local_phone_incoming;
+
+ /* if source telephone number avail, add it as argument */
+
+ if(*cep->real_phone_incoming)
+ argv[6] = cep->real_phone_incoming;
+
+ if(*cep->display)
+ {
+ argv[7] = "-t";
+ argv[8] = cep->display;
+ argv[9] = NULL;
+ }
+
+ /* exec program */
+
+ DBGL(DL_PROC, (log(LL_DBG, "exec_answer: prog=[%s]", cep->answerprog)));
+
+ pid = exec_prog(cep->answerprog, argv);
+
+ /* enter pid and conf ptr entry addr into table */
+
+ if(pid != -1)
+ {
+ int i;
+
+ for(i=0; i < MAX_PIDS; i++)
+ {
+ if(pid_tab[i].pid == 0)
+ {
+ pid_tab[i].pid = pid;
+ pid_tab[i].cep = cep;
+ break;
+ }
+ }
+ return(GOOD);
+ }
+ return(ERROR);
+}
+
+/*---------------------------------------------------------------------------*
+ * check if a connection has an outstanding process, if yes, kill it
+ *---------------------------------------------------------------------------*/
+void
+check_and_kill(cfg_entry_t *cep)
+{
+ int i;
+
+ for(i=0; i < MAX_PIDS; i++)
+ {
+ if(pid_tab[i].cep == cep)
+ {
+ pid_t kp;
+
+ DBGL(DL_PROC, (log(LL_DBG, "check_and_kill: killing pid %d", pid_tab[i].pid)));
+
+ kp = pid_tab[i].pid;
+ pid_tab[i].pid = 0;
+ kill(kp, SIGHUP);
+ break;
+ }
+ }
+}
+
+/* EOF */
OpenPOWER on IntegriCloud