home *** CD-ROM | disk | FTP | other *** search
- /*
- feedpipe.c
- Written by D'Arcy J.M. Cain
-
- Feeds command to a named pipe
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <process.h>
- #include <signal.h>
- #include <io.h>
- #include <string.h>
- #include <errno.h>
- #include <malloc.h>
- #include <pwd.h>
- #include <grp.h>
- #include <sys/stat.h>
- #include "feedpipe.h"
-
- /* globals */
- FP_CFG *fp_cfg;
- char *progname;
-
- static char *f_name;
-
- static void cleanup(int sig)
- {
- unlink(f_name);
- exit(sig);
- }
-
- /* function called for each line in configuration file */
- static void feedpipe(FP_CFG fc)
- {
- int child, k, uid, gid;
- FILE *pipe_fp, *fp;
-
- /* fork and check for error */
- if ((child = fork()) == -1)
- {
- fprintf(stderr, "%s: Can't fork (%s)\n", progname, strerror(errno));
- exit(3);
- }
-
- /* if no error and parent process then return immediately */
- if (child)
- return;
-
- /* we are now a new process with a command to run */
- f_name = fc.name;
-
- signal(SIGHUP, cleanup);
- signal(SIGINT, cleanup);
- signal(SIGTERM, cleanup);
-
- /* the child doesn't need this array */
- free(fp_cfg);
-
- /* mode is for permissions only - it's always a pipe */
- fc.mode &= 000777;
- fc.mode |= S_IFIFO;
-
- if (fc.owner == NULL)
- uid = getuid();
- else
- {
- struct passwd *pw;
-
- if ((pw = getpwnam(fc.owner)) == NULL)
- {
- fprintf(stderr, "%s: No such user %s\n", progname, fc.owner);
- exit(4);
- }
-
- uid = pw->pw_uid;
- }
-
- if (fc.group == NULL)
- gid = getgid();
- else
- {
- struct group *gr;
-
- if ((gr = getgrnam(fc.group)) == NULL)
- {
- fprintf(stderr, "%s: No such group %s\n", progname, fc.group);
- exit(5);
- }
-
- gid = gr->gr_gid;
- }
-
- /* this loop may seem a little strange */
- /* each iteration through it is actually a new process */
- for (;;)
- {
- char buf[BUFSIZ];
-
- /* remove any existing file or pipe */
- unlink(fc.name);
-
- /* create the new pipe */
- if (mknod(fc.name, fc.mode, 0))
- {
- fprintf(stderr, "%s: Can't create pipe %s (%s)\n",
- progname, fc.name, strerror(errno));
- exit(6);
- }
-
- if (chown(fc.name, uid, gid))
- {
- fprintf(stderr, "%s: Can't change group and/or owner %s (%s)\n",
- progname, fc.name, strerror(errno));
- exit(7);
- }
-
- /* this open will block until someone reads the other end */
- if ((pipe_fp = fopen(fc.name, "wt")) == NULL)
- {
- fprintf(stderr, "%s: Can't open pipe %s (%s)\n",
- progname, fc.name, strerror(errno));
- exit(8);
- }
-
- /* when we get here someone is reading the pipe we opened */
- /* at this point we fork a new process to create the node */
- /* again and block on opening it - this allows another process */
- /* to open the same pipe and get the full file after a very */
- /* short delay */
-
- /* note that error on fork doesn't stop us immediately */
- if ((child = fork()) != 0)
- {
- /* open the command for reading */
- if ((fp = popen(fc.cmd, "rt")) == NULL)
- {
- fprintf(stderr, "%s: Can't open command %s (%s)\n",
- progname, fc.cmd, strerror(errno));
- exit(9);
- }
-
- /* shovel them bits */
- while ((k = fread(buf, 1, BUFSIZ, fp)) != 0)
- fwrite(buf, 1, k, pipe_fp);
-
- /* cleanup */
- fclose(fp);
- fclose(pipe_fp);
-
- /* now check for failed fork */
- if (child == -1)
- {
- fprintf(stderr, "%s: Can't fork for next %s (%s)\n",
- progname, fc.name, strerror(errno));
- exit(10);
- }
-
- /* exit in any case but with no error */
- exit(0);
- }
-
- /* close the pipe */
- fclose(pipe_fp);
- }
- }
-
- /* start the bubble machine */
- int main(int argc, char **argv)
- {
- FILE *fp;
- int k, nents;
-
- /* set umask so that config file has full control */
- umask(0);
-
- /* get the program name for error messages */
- if ((progname = strrchr(argv[0], '/')) == NULL)
- progname = argv[0];
- else
- progname++;
-
- /* we expect one and only one argument currently */
- if (argc != 2)
- {
- fprintf(stderr, "Usage: %s config_file\n", progname);
- exit(1);
- }
-
- /* give it its own process group */
- setpgrp();
-
- /* open the configuration file */
- if ((fp = fopen(argv[1], "rt")) == NULL)
- {
- fprintf(stderr, "%s: Can't open configuration file (%s)\n",
- progname, strerror(errno));
- exit(2);
- }
-
- /* and read it */
- if (!(nents = readcfg(fp)))
- exit(errno);
-
- /* start a process for each active line */
- for (k = 0; k < nents; k++)
- feedpipe(fp_cfg[k]);
-
- /* free the memory in the parent process and exit */
- free(fp_cfg);
- return(0);
- }
-