home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume26 / feedpipe / part01 / feedpipe.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-14  |  4.2 KB  |  213 lines

  1. /*
  2. feedpipe.c
  3. Written by D'Arcy J.M. Cain
  4.  
  5. Feeds command to a named pipe
  6. */
  7.  
  8. #include    <stdio.h>
  9. #include    <stdlib.h>
  10. #include    <process.h>
  11. #include    <signal.h>
  12. #include    <io.h>
  13. #include    <string.h>
  14. #include    <errno.h>
  15. #include    <malloc.h>
  16. #include    <pwd.h>
  17. #include    <grp.h>
  18. #include    <sys/stat.h>
  19. #include    "feedpipe.h"
  20.  
  21. /* globals */
  22. FP_CFG    *fp_cfg;
  23. char    *progname;
  24.  
  25. static char    *f_name;
  26.  
  27. static void    cleanup(int sig)
  28. {
  29.     unlink(f_name);
  30.     exit(sig);
  31. }
  32.  
  33. /* function called for each line in configuration file */
  34. static void    feedpipe(FP_CFG fc)
  35. {
  36.     int        child, k, uid, gid;
  37.     FILE    *pipe_fp, *fp;
  38.  
  39.     /* fork and check for error */
  40.     if ((child = fork()) == -1)
  41.     {
  42.         fprintf(stderr, "%s: Can't fork (%s)\n", progname, strerror(errno));
  43.         exit(3);
  44.     }
  45.  
  46.     /* if no error and parent process then return immediately */
  47.     if (child)
  48.         return;
  49.  
  50.     /* we are now a new process with a command to run */
  51.     f_name = fc.name;
  52.  
  53.     signal(SIGHUP, cleanup);
  54.     signal(SIGINT, cleanup);
  55.     signal(SIGTERM, cleanup);
  56.  
  57.     /* the child doesn't need this array */
  58.     free(fp_cfg);
  59.  
  60.     /* mode is for permissions only - it's always a pipe */
  61.     fc.mode &= 000777;
  62.     fc.mode |= S_IFIFO;
  63.  
  64.     if (fc.owner == NULL)
  65.         uid = getuid();
  66.     else
  67.     {
  68.         struct passwd    *pw;
  69.  
  70.         if ((pw = getpwnam(fc.owner)) == NULL)
  71.         {
  72.             fprintf(stderr, "%s: No such user %s\n", progname, fc.owner);
  73.             exit(4);
  74.         }
  75.  
  76.         uid = pw->pw_uid;
  77.     }
  78.  
  79.     if (fc.group == NULL)
  80.         gid = getgid();
  81.     else
  82.     {
  83.         struct group    *gr;
  84.  
  85.         if ((gr = getgrnam(fc.group)) == NULL)
  86.         {
  87.             fprintf(stderr, "%s: No such group %s\n", progname, fc.group);
  88.             exit(5);
  89.         }
  90.  
  91.         gid = gr->gr_gid;
  92.     }
  93.  
  94.     /* this loop may seem a little strange */
  95.     /* each iteration through it is actually a new process */
  96.     for (;;)
  97.     {
  98.         char    buf[BUFSIZ];
  99.  
  100.         /* remove any existing file or pipe */
  101.         unlink(fc.name);
  102.  
  103.         /* create the new pipe */
  104.         if (mknod(fc.name, fc.mode, 0))
  105.         {
  106.             fprintf(stderr, "%s: Can't create pipe %s (%s)\n",
  107.                                 progname, fc.name, strerror(errno));
  108.             exit(6);
  109.         }
  110.  
  111.         if (chown(fc.name, uid, gid))
  112.         {
  113.             fprintf(stderr, "%s: Can't change group and/or owner %s (%s)\n",
  114.                                 progname, fc.name, strerror(errno));
  115.             exit(7);
  116.         }
  117.  
  118.         /* this open will block until someone reads the other end */
  119.         if ((pipe_fp = fopen(fc.name, "wt")) == NULL)
  120.         {
  121.             fprintf(stderr, "%s: Can't open pipe %s (%s)\n",
  122.                                 progname, fc.name, strerror(errno));
  123.             exit(8);
  124.         }
  125.  
  126.         /* when we get here someone is reading the pipe we opened */
  127.         /* at this point we fork a new process to create the node */
  128.         /* again and block on opening it - this allows another process */
  129.         /* to open the same pipe and get the full file after a very */
  130.         /* short delay */
  131.  
  132.         /* note that error on fork doesn't stop us immediately */
  133.         if ((child = fork()) != 0)
  134.         {
  135.             /* open the command for reading */
  136.             if ((fp = popen(fc.cmd, "rt")) == NULL)
  137.             {
  138.                 fprintf(stderr, "%s: Can't open command %s (%s)\n",
  139.                                     progname, fc.cmd, strerror(errno));
  140.                 exit(9);
  141.             }
  142.  
  143.             /* shovel them bits */
  144.             while ((k = fread(buf, 1, BUFSIZ, fp)) != 0)
  145.                 fwrite(buf, 1, k, pipe_fp);
  146.  
  147.             /* cleanup */
  148.             fclose(fp);
  149.             fclose(pipe_fp);
  150.  
  151.             /* now check for failed fork */
  152.             if (child == -1)
  153.             {
  154.                 fprintf(stderr, "%s: Can't fork for next %s (%s)\n",
  155.                                     progname, fc.name, strerror(errno));
  156.                 exit(10);
  157.             }
  158.  
  159.             /* exit in any case but with no error */
  160.             exit(0);
  161.         }
  162.  
  163.         /* close the pipe */
  164.         fclose(pipe_fp);
  165.     }
  166. }
  167.  
  168. /* start the bubble machine */
  169. int        main(int argc, char **argv)
  170. {
  171.     FILE    *fp;
  172.     int        k, nents;
  173.  
  174.     /* set umask so that config file has full control */
  175.     umask(0);
  176.  
  177.     /* get the program name for error messages */
  178.     if ((progname = strrchr(argv[0], '/')) == NULL)
  179.         progname = argv[0];
  180.     else
  181.         progname++;
  182.  
  183.     /* we expect one and only one argument currently */
  184.     if (argc != 2)
  185.     {
  186.         fprintf(stderr, "Usage: %s config_file\n", progname);
  187.         exit(1);
  188.     }
  189.  
  190.     /* give it its own process group */
  191.     setpgrp();
  192.  
  193.     /* open the configuration file */
  194.     if ((fp = fopen(argv[1], "rt")) == NULL)
  195.     {
  196.         fprintf(stderr, "%s: Can't open configuration file (%s)\n",
  197.                         progname, strerror(errno));
  198.         exit(2);
  199.     }
  200.  
  201.     /* and read it */
  202.     if (!(nents = readcfg(fp)))
  203.         exit(errno);
  204.  
  205.     /* start a process for each active line */
  206.     for (k = 0; k < nents; k++)
  207.         feedpipe(fp_cfg[k]);
  208.  
  209.     /* free the memory in the parent process and exit */
  210.     free(fp_cfg);
  211.     return(0);
  212. }
  213.