home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume30 / log_tcp / part02 / shell_cmd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-20  |  2.5 KB  |  106 lines

  1.  /*
  2.   * shell_cmd() takes a shell command template and performs %a (host
  3.   * address), %c (client info), %h (host name or address), %d (daemon name),
  4.   * %p (process id) and %u (user name) substitutions. The result is executed
  5.   * by a /bin/sh child process, with standard input, standard output and
  6.   * standard error connected to /dev/null.
  7.   * 
  8.   * Diagnostics are reported through syslog(3).
  9.   * 
  10.   * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
  11.   */
  12.  
  13. #ifndef lint
  14. static char sccsid[] = "@(#) shell_cmd.c 1.2 92/06/11 22:21:28";
  15. #endif
  16.  
  17. /* System libraries. */
  18.  
  19. #include <sys/types.h>
  20. #include <sys/param.h>
  21. #include <stdio.h>
  22. #include <syslog.h>
  23.  
  24. extern char *strncpy();
  25. extern void closelog();
  26. extern void exit();
  27.  
  28. /* Local stuff. */
  29.  
  30. #include "log_tcp.h"
  31.  
  32. /* Forward declarations. */
  33.  
  34. static void do_child();
  35.  
  36. /* shell_cmd - expand %<char> sequences and execute shell command */
  37.  
  38. void    shell_cmd(string, daemon, client)
  39. char   *string;
  40. char   *daemon;
  41. struct from_host *client;
  42. {
  43.     char    cmd[BUFSIZ];
  44.     int     child_pid;
  45.     int     wait_pid;
  46.     int     daemon_pid = getpid();
  47.  
  48.     /*
  49.      * Most of the work is done within the child process, to minimize the
  50.      * risk of damage to the parent.
  51.      */
  52.  
  53.     switch (child_pid = fork()) {
  54.     case -1:                    /* error */
  55.     syslog(LOG_ERR, "fork: %m");
  56.     break;
  57.     case 00:                    /* child */
  58.     percent_x(cmd, sizeof(cmd), string, daemon, client, daemon_pid);
  59.     do_child(daemon, cmd);
  60.     /* NOTREACHED */
  61.     default:                    /* parent */
  62.     while ((wait_pid = wait((int *) 0)) != -1 && wait_pid != child_pid)
  63.          /* void */ ;
  64.     }
  65. }
  66.  
  67. /* do_child - exec command with { stdin, stdout, stderr } to /dev/null */
  68.  
  69. static void do_child(myname, command)
  70. char   *myname;
  71. char   *command;
  72. {
  73.     char   *error = 0;
  74.     int     tmp_fd;
  75.  
  76.     /*
  77.      * Close a bunch of file descriptors. The Ultrix inetd only passes stdin,
  78.      * but other inetd implementations set up stdout as well. Ignore errors.
  79.      */
  80.  
  81.     closelog();
  82.     for (tmp_fd = 0; tmp_fd < 10; tmp_fd++)
  83.     (void) close(tmp_fd);
  84.  
  85.     /* Set up new stdin, stdout, stderr, and exec the shell command. */
  86.  
  87.     if (open("/dev/null", 2) != 0) {
  88.     error = "open /dev/null: %m";
  89.     } else if (dup(0) != 1 || dup(0) != 2) {
  90.     error = "dup: %m";
  91.     } else {
  92.     (void) execl("/bin/sh", "sh", "-c", command, (char *) 0);
  93.     error = "execl /bin/sh: %m";
  94.     }
  95.  
  96.     /* We can reach the following code only if there was an error. */
  97.  
  98. #ifdef LOG_MAIL
  99.     (void) openlog(myname, LOG_PID, FACILITY);
  100. #else
  101.     (void) openlog(myname, LOG_PID);
  102. #endif
  103.     syslog(LOG_ERR, error);
  104.     exit(0);
  105. }
  106.