home *** CD-ROM | disk | FTP | other *** search
- /* 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[];
-
- #ifdef NOHERROR
- int h_errno;
- 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 */
- };
-
- #else
- extern int h_errno;
- extern char *h_errlist;
- #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';
- }
-