xref: /freebsd/usr.sbin/ppp/exec.c (revision 6e8394b8baa7d5d9153ab90de6824bcd19b3b4e1)
1 /*-
2  * Copyright (c) 1999 Brian Somers <brian@Awfulhak.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  *	$Id: exec.c,v 1.5 1999/06/05 21:35:50 brian Exp $
27  */
28 
29 #include <sys/param.h>
30 #include <sys/socket.h>
31 #include <netinet/in.h>
32 #include <arpa/inet.h>
33 #include <netdb.h>
34 #include <netinet/in_systm.h>
35 #include <netinet/ip.h>
36 #include <sys/un.h>
37 
38 #include <errno.h>
39 #include <fcntl.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <sys/wait.h>
44 #include <sys/uio.h>
45 #include <termios.h>
46 #include <unistd.h>
47 
48 #include "layer.h"
49 #include "defs.h"
50 #include "mbuf.h"
51 #include "log.h"
52 #include "sync.h"
53 #include "timer.h"
54 #include "lqr.h"
55 #include "hdlc.h"
56 #include "throughput.h"
57 #include "fsm.h"
58 #include "lcp.h"
59 #include "ccp.h"
60 #include "link.h"
61 #include "async.h"
62 #include "slcompress.h"
63 #include "iplist.h"
64 #include "ipcp.h"
65 #include "filter.h"
66 #include "descriptor.h"
67 #include "physical.h"
68 #include "mp.h"
69 #ifndef NORADIUS
70 #include "radius.h"
71 #endif
72 #include "chat.h"
73 #include "command.h"
74 #include "bundle.h"
75 #include "prompt.h"
76 #include "auth.h"
77 #include "chap.h"
78 #include "cbcp.h"
79 #include "datalink.h"
80 #include "exec.h"
81 
82 static struct device execdevice = {
83   EXEC_DEVICE,
84   "exec",
85   NULL,
86   NULL,
87   NULL,
88   NULL,
89   NULL,
90   NULL,
91   NULL,
92   NULL,
93   NULL,
94   NULL
95 };
96 
97 struct device *
98 exec_iov2device(int type, struct physical *p, struct iovec *iov,
99                 int *niov, int maxiov)
100 {
101   if (type == EXEC_DEVICE) {
102     free(iov[(*niov)++].iov_base);
103     physical_SetupStack(p, execdevice.name, PHYSICAL_FORCE_ASYNC);
104     return &execdevice;
105   }
106 
107   return NULL;
108 }
109 
110 struct device *
111 exec_Create(struct physical *p)
112 {
113   if (p->fd < 0 && *p->name.full == '!') {
114     int fids[2];
115 
116     if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, fids) < 0)
117       log_Printf(LogPHASE, "Unable to create pipe for line exec: %s\n",
118 	         strerror(errno));
119     else {
120       int stat, argc;
121       pid_t pid, realpid;
122       char *argv[MAXARGS];
123 
124       stat = fcntl(fids[0], F_GETFL, 0);
125       if (stat > 0) {
126         stat |= O_NONBLOCK;
127         fcntl(fids[0], F_SETFL, stat);
128       }
129       realpid = getpid();
130       switch ((pid = fork())) {
131         case -1:
132           log_Printf(LogPHASE, "Unable to create pipe for line exec: %s\n",
133 	             strerror(errno));
134           break;
135 
136         case  0:
137           close(fids[0]);
138           timer_TermService();
139           setuid(geteuid());
140 
141           switch (fork()) {
142             case 0:
143               break;
144 
145             case -1:
146               log_Printf(LogPHASE, "Unable to fork to drop parent: %s\n",
147 	                 strerror(errno));
148             default:
149               _exit(127);
150           }
151 
152           fids[1] = fcntl(fids[1], F_DUPFD, 3);
153           dup2(fids[1], STDIN_FILENO);
154           dup2(fids[1], STDOUT_FILENO);
155           dup2(fids[1], STDERR_FILENO);
156 
157           log_Printf(LogDEBUG, "Exec'ing ``%s''\n", p->name.base);
158           argc = MakeArgs(p->name.base, argv, VECSIZE(argv));
159           command_Expand(argv, argc, (char const *const *)argv,
160                          p->dl->bundle, 0, realpid);
161           execvp(*argv, argv);
162           fprintf(stderr, "execvp failed: %s: %s\r\n", *argv, strerror(errno));
163           _exit(127);
164           break;
165 
166         default:
167           close(fids[1]);
168           p->fd = fids[0];
169           waitpid(pid, &stat, 0);
170           log_Printf(LogDEBUG, "Using descriptor %d for child\n", p->fd);
171           physical_SetupStack(p, execdevice.name, PHYSICAL_FORCE_ASYNC);
172           return &execdevice;
173       }
174     }
175   }
176 
177   return NULL;
178 }
179