static char rcsid[] = "@(#)$Id: reghelper.c,v 1.8 2006/04/09 07:37:30 hurtta Exp $";

/******************************************************************************
 *  The Elm (ME+) Mail System  -  $Revision: 1.8 $   $State: Exp $
 *
 *  Author: Kari Hurtta <hurtta+elm@posti.FMI.FI> (was hurtta+elm@ozone.FMI.FI)
 *****************************************************************************/

#include "defs_major.h"
#include "patchlevel.h"

#include "reghelper.h"

/*  Protocol in PIPE:  
 *
 *        file descriptor given on $ELM_INSTALLER
 *        installer root given on  $ELM_ROOT
 *
 *         filenames are relative to $ELM_ROOT
 * 
 *
 * -- copy file
 *
 * 'F' user group mode filename '\n'
 *
 * -- create directory
 *
 * 'M' user group mode filename '\n'
 *
 * --  execute
 * {n}  user group mode filename '\n'
 * {n}  user group mode filename'\n'
 *
 * 'E' filename  {n} xx yy {n} '\n'
 *
 * -- config file touched on replay time
 *
 * 'C' user group mode filename'\n'
 *
 * -- remove files
 *
 * 'R' file file file '\n'
 *
 * -- link file
 *
 * 'L' file file '\n'
 *
 */

#include <errno.h>
#ifndef ANSI_C
extern int errno;
#endif

void reghelper_init()
{
    char * register_pipe   = getenv("ELM_INSTALLER");
    char * installer_root  = getenv("ELM_ROOT");
    int fd;
    struct stat X;
  
    if (installer_root && 0 != strcmp(installer_root,"/")) {
      	fprintf(stderr,
		"%s does not support $ELM_ROOT=%s\n",
		program_name,installer_root);
	exit(1);
    }

    if (!register_pipe) {
      register_fd = -1;
      return;
    }

    fd = atoi(register_pipe);	
    
    if (fd < 1) {
	fprintf(stderr,"%s: $ELM_INSTALLER=%s invalid\n",
		program_name,register_pipe);
	
	exit (1);   /* FAILURE */
	
    } 
    
    if (fstat(fd,&X) < 0) {
	fprintf(stderr,"%s: $ELM_INSTALLER=%s invalid\n",
		program_name,register_pipe);
	
	exit (1);   /* FAILURE */
    }


    register_fd = fd;
    register_module = getenv("ELM_MODULE");
}

void log_config(file)
     char *file;
{
    /* Skip '/' on front ... */
    while ('/' == file[0])
	file++;

    if (register_fd != -1)
        log_it("C",file,"-","-",0, register_module);
}

void log_it(letter,target_r,user,group,mode,   module)
     char * letter;
     char * target_r;
     char * user; 
     char * group; 
     int mode;
     char * module;
{
    int l_letter = strlen(letter);
    int l_target = strlen(target_r);
    int l_user   = strlen(user);
    int l_group  = strlen(group);
    int l_module = module ? strlen(module) : 0;

    char buffer[ MAX_PIPE_LOG];
    char *ptr;
    char mode_s[6];

    int L = 17 + l_letter + l_target + l_user + l_group + l_module;

    sprintf(mode_s,"%05o",mode);

    if (L >  MAX_PIPE_LOG-2) {
	fprintf(stderr,"%s: Can't register file, string too long: %d\n",
		program_name,L);
	exit(1);
    } 

    ptr = buffer;

    if (module) {
	add_to_buffer(buffer, sizeof buffer,&ptr,"m",1);
	add_to_buffer(buffer, sizeof buffer,&ptr,module,l_module);
    }

    add_to_buffer(buffer, sizeof buffer,&ptr,letter,l_letter);
    add_to_buffer(buffer, sizeof buffer,&ptr,user,l_user);
    add_to_buffer(buffer, sizeof buffer,&ptr,group,l_group);
    add_to_buffer(buffer, sizeof buffer,&ptr,mode_s,5);
    add_to_buffer(buffer, sizeof buffer,&ptr,target_r,l_target);

    *ptr++ = '\n';   /* Terminating NL on line */

    L = ptr - buffer;

    if (L >  MAX_PIPE_LOG-2) {
	fprintf(stderr,"%s: Can't register file, string too long: %d\n",
		program_name,L);
	exit(1);
    } 
    
    write_once(register_fd,buffer,L);

}

void write_once(fd,buffer,L)
     int fd; 
     char *buffer; 
     int L;
{
    int n;

    /* We have better to able write whole string at ONCE,
       or otherwise two different writes from different processes
       are mixed on pipe ... (ie. if paraller make)
    */

 again:
    n = write(fd,buffer,L);

    if (n < 0) {

	if (EINTR == errno)
	    goto again;

	fprintf(stderr,"%s: Can't register file or command, write to fd %d failed\n",
		program_name,fd);
	exit(1);
    
    }

    if (n != L) {
	fprintf(stderr,"%s: Can't register file or command, incomplete write to fd %d : %d bytes written (expected %d)\n",
		program_name,fd, n, L);
	exit(1);    
    }

}

void add_to_buffer(buffer,blen,ptr,str,s_len) 
     char *buffer;
     size_t blen;
     char **ptr;
     char *str; 
     int s_len;
{
    char *p = *ptr;
    char *s = str;
    int abt = 0;

    if (p < buffer || p >= buffer +blen) {
	fprintf(stderr,"%s: out of range!!\n",program_name);
	exit(1);
    }

    for (p = *ptr, s = str; 
	 p < buffer + blen && s < str + s_len;
	 p++, s++) {
	*p = *s;
    }

    if (*s != '\0') {
	fprintf(stderr,
		"%s: incorrect s_len=%d (or out of buffer), str=%s!!\n",
		program_name, s_len,str);
	abt = 1;
    }

    if (p ==  buffer +blen) {
	fprintf(stderr,
		"%s: out of buffer\n",
		program_name);

	abt = 1;
    }

    if (abt)
	exit(abt);

    *p++ = '\0';

    *ptr = p;
}

/*
 * Local Variables:
 *  mode:c
 *  c-basic-offset:4
 *  buffer-file-coding-system: iso-8859-1
 * End:
 */


syntax highlighted by Code2HTML, v. 0.9.1