exec.c revision 47461
146686Sbrian/*-
246686Sbrian * Copyright (c) 1999 Brian Somers <brian@Awfulhak.org>
346686Sbrian * All rights reserved.
446686Sbrian *
546686Sbrian * Redistribution and use in source and binary forms, with or without
646686Sbrian * modification, are permitted provided that the following conditions
746686Sbrian * are met:
846686Sbrian * 1. Redistributions of source code must retain the above copyright
946686Sbrian *    notice, this list of conditions and the following disclaimer.
1046686Sbrian * 2. Redistributions in binary form must reproduce the above copyright
1146686Sbrian *    notice, this list of conditions and the following disclaimer in the
1246686Sbrian *    documentation and/or other materials provided with the distribution.
1346686Sbrian *
1446686Sbrian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1546686Sbrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1646686Sbrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1746686Sbrian * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1846686Sbrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1946686Sbrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2046686Sbrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2146686Sbrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2246686Sbrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2346686Sbrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2446686Sbrian * SUCH DAMAGE.
2546686Sbrian *
2647461Sbrian *	$Id: exec.c,v 1.2 1999/05/12 09:48:49 brian Exp $
2746686Sbrian */
2846686Sbrian
2946686Sbrian#include <sys/param.h>
3046686Sbrian#include <sys/socket.h>
3146686Sbrian#include <netinet/in.h>
3246686Sbrian#include <arpa/inet.h>
3346686Sbrian#include <netdb.h>
3446686Sbrian#include <netinet/in_systm.h>
3546686Sbrian#include <netinet/ip.h>
3646686Sbrian#include <sys/un.h>
3746686Sbrian
3846686Sbrian#include <errno.h>
3946686Sbrian#include <fcntl.h>
4046686Sbrian#include <stdio.h>
4146686Sbrian#include <stdlib.h>
4246686Sbrian#include <string.h>
4346686Sbrian#include <sys/wait.h>
4446686Sbrian#include <termios.h>
4546686Sbrian#include <unistd.h>
4646686Sbrian
4746686Sbrian#include "layer.h"
4846686Sbrian#include "defs.h"
4946686Sbrian#include "mbuf.h"
5046686Sbrian#include "log.h"
5146686Sbrian#include "sync.h"
5246686Sbrian#include "timer.h"
5346686Sbrian#include "lqr.h"
5446686Sbrian#include "hdlc.h"
5546686Sbrian#include "throughput.h"
5646686Sbrian#include "fsm.h"
5746686Sbrian#include "lcp.h"
5846686Sbrian#include "ccp.h"
5946686Sbrian#include "link.h"
6046686Sbrian#include "async.h"
6146686Sbrian#include "slcompress.h"
6246686Sbrian#include "iplist.h"
6346686Sbrian#include "ipcp.h"
6446686Sbrian#include "filter.h"
6546686Sbrian#include "descriptor.h"
6646686Sbrian#include "physical.h"
6746686Sbrian#include "mp.h"
6846686Sbrian#ifndef NORADIUS
6946686Sbrian#include "radius.h"
7046686Sbrian#endif
7146686Sbrian#include "chat.h"
7246686Sbrian#include "command.h"
7346686Sbrian#include "bundle.h"
7446686Sbrian#include "prompt.h"
7546686Sbrian#include "auth.h"
7646686Sbrian#include "chap.h"
7746686Sbrian#include "cbcp.h"
7846686Sbrian#include "datalink.h"
7946686Sbrian#include "exec.h"
8046686Sbrian
8147061Sbrianstatic struct device execdevice = {
8247061Sbrian  EXEC_DEVICE,
8347061Sbrian  "exec",
8447061Sbrian  NULL,
8547061Sbrian  NULL,
8647061Sbrian  NULL,
8747061Sbrian  NULL,
8847061Sbrian  NULL,
8947061Sbrian  NULL,
9047061Sbrian  NULL,
9147061Sbrian  NULL,
9247061Sbrian  NULL,
9347061Sbrian  NULL
9447061Sbrian};
9547061Sbrian
9647061Sbrianstruct device *
9747061Sbrianexec_iov2device(int type, struct physical *p, struct iovec *iov,
9847061Sbrian                int *niov, int maxiov)
9946686Sbrian{
10047461Sbrian  if (type == EXEC_DEVICE) {
10147461Sbrian    physical_SetupStack(p, execdevice.name, PHYSICAL_FORCE_ASYNC);
10247061Sbrian    return &execdevice;
10347461Sbrian  }
10447061Sbrian
10547061Sbrian  return NULL;
10647061Sbrian}
10747061Sbrian
10847061Sbrianstruct device *
10947061Sbrianexec_Create(struct physical *p)
11047061Sbrian{
11147061Sbrian  if (p->fd < 0 && *p->name.full == '!') {
11246686Sbrian    int fids[2];
11346686Sbrian
11446686Sbrian    if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, fids) < 0)
11546686Sbrian      log_Printf(LogPHASE, "Unable to create pipe for line exec: %s\n",
11646686Sbrian	         strerror(errno));
11746686Sbrian    else {
11846686Sbrian      int stat, argc;
11946686Sbrian      pid_t pid;
12046686Sbrian      char *argv[MAXARGS];
12146686Sbrian
12246686Sbrian      stat = fcntl(fids[0], F_GETFL, 0);
12346686Sbrian      if (stat > 0) {
12446686Sbrian        stat |= O_NONBLOCK;
12546686Sbrian        fcntl(fids[0], F_SETFL, stat);
12646686Sbrian      }
12746686Sbrian      switch ((pid = fork())) {
12846686Sbrian        case -1:
12946686Sbrian          log_Printf(LogPHASE, "Unable to create pipe for line exec: %s\n",
13046686Sbrian	             strerror(errno));
13146686Sbrian          break;
13246686Sbrian
13346686Sbrian        case  0:
13446686Sbrian          close(fids[0]);
13546686Sbrian          timer_TermService();
13646686Sbrian          setuid(geteuid());
13746686Sbrian
13846686Sbrian          switch (fork()) {
13946686Sbrian            case 0:
14046686Sbrian              break;
14146686Sbrian
14246686Sbrian            case -1:
14346686Sbrian              log_Printf(LogPHASE, "Unable to fork to drop parent: %s\n",
14446686Sbrian	                 strerror(errno));
14546686Sbrian            default:
14646686Sbrian              _exit(127);
14746686Sbrian          }
14846686Sbrian
14946686Sbrian          fids[1] = fcntl(fids[1], F_DUPFD, 3);
15046686Sbrian          dup2(fids[1], STDIN_FILENO);
15146686Sbrian          dup2(fids[1], STDOUT_FILENO);
15246686Sbrian          dup2(fids[1], STDERR_FILENO);
15346686Sbrian
15446686Sbrian          argc = MakeArgs(p->name.base, argv, VECSIZE(argv));
15546686Sbrian          command_Expand(argv, argc, (char const *const *)argv,
15646686Sbrian                         p->dl->bundle, 0);
15746686Sbrian          execvp(*argv, argv);
15846686Sbrian          fprintf(stderr, "execvp failed: %s: %s\r\n", *argv, strerror(errno));
15946686Sbrian          _exit(127);
16046686Sbrian          break;
16146686Sbrian
16246686Sbrian        default:
16346686Sbrian          close(fids[1]);
16446686Sbrian          p->fd = fids[0];
16546686Sbrian          waitpid(pid, &stat, 0);
16646686Sbrian          log_Printf(LogDEBUG, "Using descriptor %d for child\n", p->fd);
16747461Sbrian          physical_SetupStack(p, execdevice.name, PHYSICAL_FORCE_ASYNC);
16847061Sbrian          return &execdevice;
16946686Sbrian      }
17046686Sbrian    }
17146686Sbrian  }
17246686Sbrian
17347061Sbrian  return NULL;
17446686Sbrian}
175