ftp.nice.ch/pub/next/unix/admin/msend.1.0.N.bs.tar.gz#/msend/sendrecv.c

This is sendrecv.c in view mode; [Download] [Up]

/* sendrecv.c:
 *
 * these routines send messages and receive replies
 *
 * (c) Copyright 1988, 1989, 1990 Jim Frost.  All Rights Reserved.  Please see
 * the accompanying file "Copyright" for more information.
 */

#include "Copyright"
#include "config.h"
#include "msend.h"

extern int  errno;
extern char *sys_errlist[];


char	*h_errlist[] = {
  "Error 0",
  "Unknown host",			/* 1 HOST_NOT_FOUND */
  "Host name lookup failure",		/* 2 TRY_AGAIN */
  "Unknown server error",		/* 3 NO_RECOVERY */
  "No address associated with name",	/* 4 NO_ADDRESS */
};

#ifndef NOHERROR
extern int h_errno;
#else
int h_errno;
#endif

static char *wrerr= "communications error with socket";

/* send a message to another server and get a reply
 */

void sendmessage(si,ri,mode)
struct simsg *si; /* message to send */
struct rimsg *ri; /* reply we'll get */
int    mode;      /* communications mode */
{ int     a;
  int     uid;
  static  int     s= -1;
  struct  sheader sh;
  struct  rheader rh;
  u_short fwdcount;
  u_short mmode;

  /* check to see if we have too many forwards
   */

  if (si->fwdcount > MAXFORWARD) {
    ri->h.errno= RE_FWDLOOP;
    strcpy(ri->msg,"Forwarding loop (too many forwards)");
    return;
  }

  /* look for illegal characters in the string.  this stops people
   * from sending nasty codes with this
   */

  for (a= 0; a < strlen(si->msg); a++)
    if ((si->msg[a] < ' ') && (si->msg[a] != '\t') && (si->msg[a] != '\n') &&
        (si->msg[a] != 010)) {
      ri->h.errno= RE_NOTFATAL;
      strcpy(ri->msg,"Control characters are not allowed in messages (message not sent)");
      ri->h.msglen= strlen(ri->msg);
      return;
    }

  /* s is -1 if we're not already connected
   */

  if (s == -1) {

    /* if possible, become root for duration of hopen() call so we can
     * deal with low port numbers
     */

    if (getuid() == ROOTUID) {
      uid= geteuid();
      seteuid(ROOTUID);
    }

    /* return immediate error if we can't connect
     */

    if ((s= hopen(si->tohost)) < 0) {
      if (getuid() == ROOTUID)
        seteuid(uid);
      if (h_errno == 0) { 
	sprintf(ri->msg,"%s: %s",si->tohost,sys_errlist[errno]);
	ri->h.msglen= strlen(sys_errlist[errno]);
      } else { 
	sprintf(ri->msg,"%s: %s",si->tohost,h_errlist[h_errno]);
	ri->h.msglen= strlen(h_errlist[h_errno]);
      }
      ri->h.errno= RE_SYSERR;
      return;
    }
    if (getuid() == ROOTUID)
      seteuid(uid); /* become our old selves again */
  }

  /* format request and send it across
   */

  fwdcount= htons(si->fwdcount);
  mmode= htons((u_short)mode);
  sh.taddrlen= htons((u_short)strlen(si->taddr));
  sh.tttylen= htons((u_short)strlen(si->ttty));
  sh.msglen= htons((u_short)strlen(si->msg));

  if (hwrite(s,(char *)&sh,sizeof(struct sheader)) < 0) {
    hclose(s);
    s= -1;
    blderr(ri,RE_SYSERR,wrerr);
    return;
  }
  if (hwrite(s,(char *)&fwdcount,sizeof(u_short)) < 0) {
    hclose(s);
    s= -1;
    blderr(ri,RE_SYSERR,wrerr);
    return;
  }
  if (hwrite(s,(char *)&mmode,sizeof(u_short)) < 0) {
    hclose(s);
    s= -1;
    blderr(ri,RE_SYSERR,wrerr);
    return;
  }
  if (hwrite(s,(char *)si->taddr,strlen(si->taddr)) < 0) {
    hclose(s);
    s= -1;
    blderr(ri,RE_SYSERR,wrerr);
    return;
  }
  if (hwrite(s,(char *)si->ttty,strlen(si->ttty)) < 0) {
    hclose(s);
    s= -1;
    blderr(ri,RE_SYSERR,wrerr);
    return;
  }
  if (hwrite(s,(char *)si->msg,strlen(si->msg)) < 0) {
    hclose(s);
    s= -1;
    blderr(ri,RE_SYSERR,wrerr);
    return;
  }

  /* Get the returned structure
   */

  hread(s,(char *)&rh,sizeof(struct rheader));
  ri->h.errno= ntohs(rh.errno);
  ri->h.msglen= ntohs(rh.msglen);
  hread(s,(char *)ri->msg,ri->h.msglen);
  ri->msg[ri->h.msglen]= '\0';
  if ((mode & SM_CLOSE) || (ri->h.errno != RE_OK)) {
    hclose(s);
    s= -1;
  }
}

/* sendreply() and recvmessage() are used only in the daemon
 */

/* send reply back to whomever called us.  automatically close connection
 * if we were supposed to.
 */

void sendreply(s,ri,mode)
int s;
struct rimsg *ri;
int mode;
{ struct rheader rh;

  rh.errno= htons(ri->h.errno);
  rh.msglen= htons((u_short)strlen(ri->msg));
  hwrite(s,(char *)&rh,sizeof(struct rheader));
  hwrite(s,(char *)ri->msg,strlen(ri->msg));
  if ((mode & SM_CLOSE) || (ri->h.errno != RE_OK))
    hclose(s);
}

/* this gets a message from the socket.
 */

void recvmessage(s,si)
int s;
struct simsg *si;
{ struct sheader sh;
  int    r;

  /* pull the message out of the connection and into a structure
   */

  switch (hread(s,(char *)&sh,sizeof(struct sheader))) {
  case -1:
    error("error reading message header"); /* oh well */
  case 0:
    hclose(s);
    exit(0);
  default:
    break;
  }

  /* adjust integer format
   */

  sh.taddrlen= ntohs(sh.taddrlen);
  sh.tttylen= ntohs(sh.tttylen);
  sh.msglen= ntohs(sh.msglen);

  /* read the data section
   */

  r= hread(s,(char *)&si->fwdcount,sizeof(u_short));
  r|= hread(s,(char *)&si->mode,sizeof(u_short));
  r|= hread(s,(char *)si->taddr,sh.taddrlen);
  r|= hread(s,(char *)si->ttty,sh.tttylen);
  r|= hread(s,(char *)si->msg,sh.msglen);

  if (r < 0) {
    error("packet read error");
    hclose(s);
    exit(1);
  }

  si->fwdcount= ntohs(si->fwdcount);
  si->mode= ntohs(si->mode);
  si->taddr[sh.taddrlen]= '\0';
  si->ttty[sh.tttylen]= '\0';
  si->msg[sh.msglen]= '\0';
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.