When a link is ``!program'', realise when the process we're
authorbrian <brian@openbsd.org>
Sun, 2 Apr 2000 01:36:26 +0000 (01:36 +0000)
committerbrian <brian@openbsd.org>
Sun, 2 Apr 2000 01:36:26 +0000 (01:36 +0000)
exec()ing couldn't be exec'd and fail the device open rather
than thinking the open succeeded but the first read() got zero.

usr.sbin/ppp/ppp/exec.c

index 40c146b..233cea9 100644 (file)
@@ -23,7 +23,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *     $OpenBSD: exec.c,v 1.11 2000/02/27 01:38:25 brian Exp $
+ *     $OpenBSD: exec.c,v 1.12 2000/04/02 01:36:26 brian Exp $
  */
 
 #include <sys/param.h>
@@ -108,7 +108,8 @@ exec_Create(struct physical *p)
       log_Printf(LogPHASE, "Unable to create pipe for line exec: %s\n",
                 strerror(errno));
     else {
-      int stat, argc, i;
+      static int child_status;
+      int stat, argc, i, ret, wret;
       pid_t pid, realpid;
       char *argv[MAXARGS];
 
@@ -122,6 +123,7 @@ exec_Create(struct physical *p)
         case -1:
           log_Printf(LogPHASE, "Unable to create pipe for line exec: %s\n",
                     strerror(errno));
+          close(fids[1]);
           break;
 
         case  0:
@@ -129,15 +131,20 @@ exec_Create(struct physical *p)
           timer_TermService();
           setuid(ID0realuid());
 
-          switch (fork()) {
+          child_status = 0;
+          switch (vfork()) {
             case 0:
               break;
 
             case -1:
+              ret = errno;
               log_Printf(LogPHASE, "Unable to fork to drop parent: %s\n",
                         strerror(errno));
+              _exit(ret);
+              break;
+
             default:
-              _exit(127);
+              _exit(child_status);     /* The error from exec() ! */
           }
 
           log_Printf(LogDEBUG, "Exec'ing ``%s''\n", p->name.base);
@@ -145,7 +152,7 @@ exec_Create(struct physical *p)
           if ((argc = MakeArgs(p->name.base, argv, VECSIZE(argv),
                                PARSE_REDUCE|PARSE_NOHASH)) < 0) {
             log_Printf(LogWARN, "Syntax error in exec command\n");
-            _exit(127);
+            _exit(ESRCH);
           }
 
           command_Expand(argv, argc, (char const *const *)argv,
@@ -158,20 +165,43 @@ exec_Create(struct physical *p)
             fcntl(i, F_SETFD, 1);
 
           execvp(*argv, argv);
-          printf("execvp failed: %s: %s\r\n", *argv, strerror(errno));
-          _exit(127);
+          child_status = errno;                /* Only works for vfork() */
+          printf("execvp failed: %s: %s\r\n", *argv, strerror(child_status));
+          _exit(child_status);
           break;
 
         default:
           close(fids[1]);
+          while ((wret = waitpid(pid, &stat, 0)) == -1 && errno == EINTR)
+            ;
+          if (wret == -1) {
+            log_Printf(LogWARN, "Waiting for child process: %s\n",
+                       strerror(errno));
+            close(fids[0]);
+            break;
+          } else if (WIFSIGNALED(stat)) {
+            log_Printf(LogWARN, "Child process received sig %d !\n",
+                       WTERMSIG(stat));
+            close(fids[0]);
+            break;
+          } else if (WIFSTOPPED(stat)) {
+            log_Printf(LogWARN, "Child process received stop sig %d !\n",
+                       WSTOPSIG(stat));
+            /* I guess that's ok.... */
+          } else if ((ret = WEXITSTATUS(stat))) {
+            log_Printf(LogWARN, "Cannot exec \"%s\": %s\n", p->name.base,
+                       strerror(ret));
+            close(fids[0]);
+            break;
+          }
           p->fd = fids[0];
-          waitpid(pid, &stat, 0);
           log_Printf(LogDEBUG, "Using descriptor %d for child\n", p->fd);
           physical_SetupStack(p, execdevice.name, PHYSICAL_FORCE_ASYNC);
           if (p->cfg.cd.necessity != CD_DEFAULT)
             log_Printf(LogWARN, "Carrier settings ignored\n");
           return &execdevice;
       }
+      close(fids[0]);
     }
   }