/*****************************************************************************
Simple line printer daemon

ATTENTION: NO SECURITY FEATURES IMPLEMENTED


  ©1994 by Juergen Schubert
*****************************************************************************/


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <clib/netlib_protos.h>
#include <sys/syslog.h>



/*********** Acknowledgement *****************************************/
char	*sp = "";
#define ack()	write(sock, sp, 1);



#define BUFSIZE 512


#define true 1
#define false 0

const char *ver="$VER: LPD 0.1 (11.09.94)";



int
main(int argc, char **argv)
{
  char buffer[BUFSIZE];
  char device[BUFSIZE];
  char from[BUFSIZE];
  char *cp;
  long size, i;
  int log=false;
  int outhandle;

  unsigned int amt, j;

  int sock = init_inet_daemon();

  if ( argc > 1 )
     log = true;

  openlog("lpd", LOG_PID, LOG_LPR);

  ack();


  /******************* Read output device name ***********************/
  cp = buffer;
  do
  {
     if ((size = read(sock, cp, 1)) != 1)
     {
        if (size < 0)
          return 10;
     }
  } while (*cp++ != '\n');
  *--cp = '\0';
  cp = buffer;

  ack();


  if ( cp[0] != '\2' )
  {
     syslog ( LOG_ERR, "Request not supported : %d", cp[0] );
     write ( sock, &cp[0], 1 );
     return 5;
  }

  strcpy ( device, &cp[1] );

  if ( !strcmp ( device, "lpr" ))  /* Remote host tries to print to default printer */
    strcpy ( device, "par:" );     /* Default printing to par: */

  if ( log )
     syslog ( LOG_INFO, "Remote host tries to print to %s", device );



  /******************* Read size and sending host  **********************/
  cp = buffer;
  do
  {
     if ((size = read(sock, cp, 1)) != 1)
     {
        if (size < 0)
          return 10;
     }
  } while (*cp++ != '\n');
  *--cp = '\0';
  cp = buffer;

  ack();

  switch (*cp++)
  {
     /* \1 = Cleanup not possible */

     case '\2':	/* read cf file */
     case '\3': /* read df file */
        size = 0;
        while (*cp >= '0' && *cp <= '9')
           size = size * 10 + (*cp++ - '0');
        if (*cp++ != ' ')
           break;

        strcpy(from, cp + 6);
        break;

     default:
        syslog ( LOG_ERR, "Cleanup not supported" );
        return 5;
  }

  if ( log )
     syslog ( LOG_INFO, "Host %s is printing %ld bytes.", from, size );


  /****************** Get the job ************************************/

  outhandle = open ( device, O_APPEND|O_CREAT|O_WRONLY, S_IREAD|S_IWRITE );
  if ( !outhandle )
  {
     write ( sock, &cp[0], 1 );
     syslog ( LOG_ERR, "Can't get an output handle for %s", device );
     return 10;
  }

  for (i = 0; i < size; i += BUFSIZ)
  {
     amt = BUFSIZ;
     cp = buffer;
     if (i + amt > size)
        amt = size - i;
     do
     {
        j = read(sock, cp, amt);
        if (j <= 0)
        {
           syslog (LOG_ERR,"Lost connection");
           break;
        }
        amt -= j;
        cp += j;
     } while (amt > 0);

     amt = BUFSIZ;
     cp = buffer;
     if (i + amt > size)
        amt = size - i;

     write ( outhandle, cp, amt );
  }

  ack();
  ack();
  close ( outhandle );

  if ( log )
     syslog ( LOG_INFO, "Printing successfully finished" );


  close ( sock );
  exit ( 0 );
}
