Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #162313

How can a daemon process open() the stdout of someone who signals it?

From John Forkosh <forkosh@panix.com>
Newsgroups comp.lang.c
Subject How can a daemon process open() the stdout of someone who signals it?
Date 2021-08-11 13:53 +0000
Organization PANIX Public Access Internet and UNIX, NYC
Message-ID <sf0kp8$ki0$1@reader1.panix.com> (permalink)

Show all headers | View raw


Specifically, below's the little test program I wrote.
It works fine, but isn't programmed to do exactly what I want
because I can't figure out how to program that.

It runs as a daemon, just sitting on a pause() until
it catches a signal, via  killall -SIGINT testdaemon
and then it just writes a dummy line with date/time and
#running processes to a log file. Just a "Hello, World" test.

But what I want is to write some stuff to the stdout
of the process that sent the signal to testdaemon.
Note that the testhandler() function has an
if(0)fprintf(stdout,etc).  So my question is,
what do I do to open()/fopen()/whatever the user's
(whoever sent testdaemon the sigint) stdout?
And then close it after the test handler completes,
just before the daemon goes back to pause().

So, for definiteness, here's the little testdaemon code,

/* ---
 * usage:  nohup ./testdaemon
 *   then:  killall -SIGINT testdaemon
 * -------------------------------------- */
/* --- standard headers --- */
#include <stdio.h>
#include <stdlib.h>
/* --- required for daemonize() --- */
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
/* --- required for signals --- */
#include <signal.h>
/* --- additional data --- */
#if !defined(LOGFILE)
  #define LOGFILE "/home/username/testdaemon.log"
#endif

/* --- entry point --- */
void testhand ( int signal ) {  /* test handler for all signals */
  if(0) fprintf(stdout,"testhand> trapped signal#%d\n",signal);
  switch(signal) {
    default: break;
    case SIGINT:
      system("echo `date` ... ps ax = `ps ax|wc` >> " LOGFILE);
      break;
    } /* --- end-of-switch(signal) --- */
  return;
  } /* --- end-of-function testhand() --- */

/* --- entry point --- */
int  main ( int argc, char *argv[] ) {
  /* --- allocations and declarations --- */
  int   signal=SIGINT, sethandler();    /* signal to send daemon */
  void  (*handler)() = testhand;        /* set up test handler */
  int   sleepsecs = 9;                  /* log info every sleepsecs seconds */
  int   daemonize(), isdaemon=daemonize(); /* run process as daemon */
  if ( isdaemon )                       /* running as daemon */
    if ( sethandler(signal,handler) == 0 ) /* established handler */
      while ( 1 ) pause();              /* killall -SIGINT testdaemon */
  exit ( 0 );
  } /* --- end-of-function main() --- */

And, if you're interested, or want to use them,
here are the more general daemonize() and sethandler() functions

/*===========================================================================
 * Function:    sethandler ( signal, handler )
 * Purpose:     Set handler() function for signal.
 * --------------------------------------------------------------------------
 * Arguments:   signal (I)      int containing signal (e.g., SIGALRM)
 *                              to be trapped by handler.
 *              handler (I)     function pointer to handler function.
 * --------------------------------------------------------------------------
 * Returns:     (int)           sigaction() return value.
 * --------------------------------------------------------------------------
 * Notes:     o
 *=========================================================================*/
/* --- entry point --- */
int sethandler ( int signal, void (*handler)() ) {
  /* --- allocations and declarations --- */
  struct sigaction newaction;           /* new action for signal */
  int   action = (-1);                  /* sigaction() return value */
  /* --- establish signal handler by calling sigaction() --- */
  newaction.sa_handler = handler;       /* set handler address */
  newaction.sa_flags = SA_RESTART;      /* resume after running handler */
  sigemptyset(&newaction.sa_mask);      /* no additional signals blocked */
  action = sigaction(signal, &newaction, NULL); /* 0=success, -1=failure */
  return(action);                       /* back to caller with result */
  } /* --- end-of-function sethandler() --- */

/* ==========================================================================
 * Function:    int daemonize ( void )
 * Purpose:     runs process as daemon
 * --------------------------------------------------------------------------
 * Arguments:   -none
 * --------------------------------------------------------------------------
 * Returns:     ( int )         1=success, 0=failure
 * --------------------------------------------------------------------------
 * Notes:     o
 * ======================================================================= */
/* --- entry point --- */
int daemonize ( void ) {
  /* --- allocations and declarations --- */
  int     status = 0;                   /* init to signal failure */
  pid_t   pid, sid;                     /* process, session id */
  /* --- fork off the parent process --- */
  if ( (pid = fork()) < 0 ) goto end_of_job; /* failed to fork */
  if ( pid > 0 ) exit(EXIT_SUCCESS);    /* exit parent process */
  /* --- change the file mode mask --- */
  umask(0);
  /* --- create a new sid for the child process --- */
  if ( (sid = setsid()) < 0 ) goto end_of_job;
  /* --- change the current working directory --- */
  if ( chdir("/") < 0 ) goto end_of_job;
  /* --- close out the standard file descriptors --- */
  close(STDIN_FILENO);
  close(STDOUT_FILENO);
  close(STDERR_FILENO);
  /* --- back to caller as daemon --- */
  status = 1;                           /* signal success to caller */
  end_of_job:
    return status;
  } /* --- end-of-function daemonize() --- */

-- 
John Forkosh  ( mailto:  j@f.com  where j=john and f=forkosh )

Back to comp.lang.c | Previous | NextNext in thread | Find similar | Unroll thread


Thread

How can a daemon process open() the stdout of someone who signals it? John Forkosh <forkosh@panix.com> - 2021-08-11 13:53 +0000
  Re: How can a daemon process open() the stdout of someone who signals it? Lew Pitcher <lew.pitcher@digitalfreehold.ca> - 2021-08-11 15:41 +0000
    Re: How can a daemon process open() the stdout of someone who signals it? John Forkosh <forkosh@panix.com> - 2021-08-12 03:11 +0000
    Re: How can a daemon process open() the stdout of someone who signals it? Vir Campestris <vir.campestris@invalid.invalid> - 2021-08-13 21:30 +0100
      Re: How can a daemon process open() the stdout of someone who signals it? Lew Pitcher <lew.pitcher@digitalfreehold.ca> - 2021-08-14 14:25 +0000
  Re: How can a daemon process open() the stdout of someone who signals it? Kaz Kylheku <563-365-8930@kylheku.com> - 2021-08-11 18:10 +0000
    Re: How can a daemon process open() the stdout of someone who signals it? John Forkosh <forkosh@panix.com> - 2021-08-12 03:17 +0000

csiph-web