/* zsend direct send Copyright (c) 1991 Jim Zelenka */
/* portions from ZWRITE Copyright MIT */

#include <sysdep.h>
#include <zephyr/zephyr.h>
#include <pwd.h>

#define NAME "zsend"

extern unsigned short port;
int msgsize;
int (*auth)();
void un_tabify();

#ifndef TABSTOP
#define	TABSTOP	8			/* #chars between tabstops */
#endif /* ! TABSTOP */

#define SIGNEDFORMAT "Class $class, Instance $instance:\nTo: @bold($recipient)\n@bold($1) <$sender>\n\n$2"
#define UNSIGNEDFORMAT "Class $class, Instance $instance:\nTo: @bold($recipient)\n$message"

void
zsend(recipient, body, opcode, class, instance)
char *recipient, *body, *opcode, *class, *instance;
{
  ZNotice_t notice;
  char *temp;
  int size, retval;
  char signature[1024], *message;
  register char *cp = signature;
  register struct passwd *pwd;
  register char *cp2, *pp;
  
  if ((retval = ZInitialize()) != ZERR_NONE) {
    com_err(NAME, retval, "while initializing");
    exit(1);
  } 

  memset((char *) &notice, 0, sizeof(notice));

  auth = ZAUTH;
  temp = ZGetVariable("zwrite-signature");
  if (temp) {
    strcpy(signature, temp);
  } 
  if (!signature) {
    pwd = getpwuid(getuid());
    if (pwd) {
      cp2 = pwd->pw_gecos;
      for (; *cp2 && *cp2 != ',' ; cp2++) {
	if (*cp2 == '&') {
	  pp = pwd->pw_name;
	  *cp++ = islower(*pp) ? toupper(*pp) : *pp;
	  pp++;
	  while (*pp)
	    *cp++ = *pp++;
	}
	else
	  *cp++ = *cp2;
      }
    }
  }
  ZClosePort();
  port = 0;
  if ((retval = ZOpenPort(&port)) != ZERR_NONE) {
    com_err(NAME, retval, "opening port");
    exit(1);
  }
  notice.z_kind = ACKED;
  notice.z_port = port;
  notice.z_class = class;
  notice.z_class_inst = instance;
  notice.z_sender = 0;
  notice.z_opcode = opcode;
  notice.z_recipient = recipient;
  if (signature)
    notice.z_default_format = SIGNEDFORMAT;
  else
    notice.z_default_format = UNSIGNEDFORMAT;
  
  message = NULL;
  msgsize = 0;
  if (signature) {
    message = (char *) malloc((unsigned)(strlen(signature)+2));
    strcpy(message, signature);
    msgsize = strlen(message);
    message[msgsize++] = '\0';
  } 
  else {
    message = (char *) malloc(1);
    message[msgsize++] = '\0';
  }
  
  size = msgsize + strlen(body);
  size++;
  message = (char *) realloc(message, (unsigned) size);
  strcpy(message+msgsize, body);
  msgsize += strlen(body);
  message[msgsize] = '\n';
  msgsize++;
  message[msgsize] = '\0';
  un_tabify(&message, &msgsize);
  notice.z_message = message;
  notice.z_message_len = size;

#ifdef DEBUG
  show("Recipient", notice.z_recipient);
  show("Opcode", notice.z_opcode);
  show("Instance", notice.z_class_inst);
  show("Class", notice.z_class);
#endif

  send_off(&notice, 1);
}

void
show(name, what)
char *name, *what;
{
  printf("%s\n===\n", name);
  printf("\"%s\"\n\n", what);
}

void
un_tabify(bufp, sizep)
char **bufp;
register int *sizep;
{
    register char *cp, *cp2;
    char *cp3;
    register int i;
    register int column;		/* column of next character */
    register int size = *sizep;

    for (cp = *bufp, i = 0; size; size--, cp++)
	if (*cp == '\t')
	    i++;			/* count tabs in buffer */

    if (!i)
	return;				/* no tabs == no work */

    /* To avoid allocation churning, allocate enough extra space to convert
       every tab into TABSTOP spaces */
    /* only add (TABSTOP-1)x because we re-use the cell holding the
       tab itself */
    cp = (char *) malloc((unsigned)(*sizep + (i * (TABSTOP-1))));
    if (!cp)				/* XXX */
	return;				/* punt expanding if memory fails */
    cp3 = cp;
    /* Copy buffer, converting tabs to spaces as we go */
    for (cp2 = *bufp, column = 1, size = *sizep; size; cp2++, size--) {
	switch (*cp2) {
	case '\n':
	case '\0':
	    /* newline or null: reset column */
	    column = 1;
	    *cp++ = *cp2;		/* copy the newline */
	    break;
	default:
	    /* copy the character */
	    *cp = *cp2;
	    cp++;
	    column++;
	    break;
	case '\t':
	    /* it's a tab, compute how many spaces to expand into. */
	    i = TABSTOP - ((column - 1) % TABSTOP);
	    for (; i > 0; i--) {
		*cp++ = ' ';		/* fill in the spaces */
		column++;
		(*sizep)++;		/* increment the size */
	    }
	    (*sizep)--;			/* remove one (we replaced the tab) */
	    break;
	}
    }
    free(*bufp);			/* free the old buf */
    *bufp = cp3;
    return;
}

send_off(notice, real)
ZNotice_t *notice;
int real;
{
  int retval;

  if ((retval = ZSendNotice(notice,auth)) != ZERR_NONE) {
    com_err(NAME,retval,"while sending notice");
  }
}













