home *** CD-ROM | disk | FTP | other *** search
- /*
- * msend.c
- *
- * Copyright (c) 1993 Zik Saleeba <zik@zikzak.apana.org.au>
- * Copyright (c) 1993 Andrew Herbert <andrew@werple.apana.org.au>
- * Copyright (c) 1992 Sun Microsystems, Inc.
- *
- * This is a client implementation of the Message Send protocol
- * defined in RFC1312. This implementation may be freely
- * copied, modified, and redistributed, provided that this
- * comment and the Sun Microsystems copyright are retained.
- * Anyone installing, modifying, or documenting this
- * software is advised to read the section in the RFC which
- * deals with security issues.
- *
- * Author: Geoff.Arnold@east.sun.com
- * Modified by: David Barr <barr@darwin.psu.edu>
- * Modified by: Andrew Herbert <andrew@werple.apana.org.au>
- * Modified by: Zik Saleeba <zik@zikzak.apana.org.au>
- */
-
- /* $Id: msend.c,v 1.2 1997/10/26 08:41:14 lukeh Exp $ */
-
- #include "common.h"
- #include "msend.h"
-
- #ifdef MSEND_APP
- extern void mslog(char *message, ...);
- #define printf mslog
- #endif
-
- char *prog; /* points to program name for messages */
- int debug = 0;
- int verbose = 0;
- char *empty_arg = ""; /* used to encode an empty message part */
-
- int msg_len = 0; /* the cumulative length of the message */
- char *msg; /* message assembly buffer */
-
- #define INTERFACES 32 /* for broadcasting */
- int if_n = 0;
- struct sockaddr_in if_a[INTERFACES];
-
-
- void
- usage()
- {
- fprintf(stderr, "Usage: %s [-t][-d][-v][-rN][-pN] recipient ['message'] - send message\n", prog);
- fprintf(stderr, " or: %s -lM - show the last M messages (default 5)\n", prog);
- fprintf(stderr, " or: %s -c - check for unread messages\n", prog);
- fprintf(stderr, " or: %s -u - show unread messages\n", prog);
- fprintf(stderr, " or: %s -sN - shorten buffer to N messages (default: 20)\n", prog);
- fprintf(stderr, " or: %s -eN - expire old messages for all users (def. 20 msgs)\n", prog);
- fprintf(stderr, " -t - use TCP (stream) connection - ignored for broadcasts\n");
- fprintf(stderr, " -g - use UDP (dataGram) transmission (default)\n");
- fprintf(stderr, " -b - broadcast to hosts on local network\n");
- fprintf(stderr, " -v - verbose mode\n");
- fprintf(stderr, " -rN - UDP retransmissions (default: 4)\n");
- fprintf(stderr, " -pN - use port N (default: 18)\n");
- fprintf(stderr, " -d - turn on debugging (implies -v)\n");
- fprintf(stderr, "\nRecipient may have any of the following forms:\n");
- fprintf(stderr, " user - send to user on the same machine\n");
- fprintf(stderr, " user@host - directed to user at given host\n");
- fprintf(stderr, " user:term@host - user logged in to term on host\n");
- fprintf(stderr, " :term@host - specified terminal on host\n");
- fprintf(stderr, " :all@host - all terminals on given host\n");
- fprintf(stderr, " @host - console at given host\n");
- }
-
-
- void collect_args(options, numargs, argc, argv)
- char *(**options)[];
- int *numargs;
- int argc;
- char *argv[];
- {
- int argcount;
- char *pos;
- char *env_args;
- int argccount;
-
- /* get the environment args */
- env_args = (char *)getenv("MSENDOPTS");
-
- if (env_args != NULL) {
- *numargs = 0;
-
- /* do a quick scan to approximately count the arguments */
- argcount = 1;
- for (pos = env_args; *pos != '\0'; pos++) {
- if (*pos == ' ')
- argcount++;
- }
- *options = (char *(*)[])malloc(sizeof(char *) * (argcount+argc));
-
- /* ok, now do it properly */
-
- /* skip leading spaces */
- pos = env_args;
- while (*pos == ' ')
- pos++;
-
- /* collect each arg */
- while (*pos != '\0') {
- (**options)[(*numargs)++] = pos;
- while (*pos != ' ' && *pos != '\0')
- pos++;
- if (*pos == ' ') {
- *pos++ = '\0';
-
- /* ignore trailing spaces */
- while (*pos == ' ')
- pos++;
- }
- }
- /* add the argv args */
- for (argccount = 0; argccount < argc; argccount++)
- (**options)[(*numargs)++] = argv[argccount];
- }
- else {
- /* just use argv */
- *options = (char *(*)[])argv;
- *numargs = argc;
- }
- }
-
- #ifndef MSEND_APP
- int
- main(argc, argv)
- int argc;
- char *argv[];
- {
- int use_tcp = 0;
- int retries = 4;
- short port = 0;
- int broadcasting = 0;
- int shorten = 20;
- int doshorten = 0;
-
- char *recipient;
- char *user;
- char *term;
- char *host;
- char *msg_text;
-
- struct sockaddr_in sin;
- struct servent *sp;
- struct hostent *hp;
- char local_name[MAXHOSTNAMELEN];
- char *(*options)[];
- int numargs;
- int argcount;
-
-
- prog = *argv++;
- argc--;
- collect_args(&options, &numargs, argc, argv);
-
- /* process options:
- * -d (debug)
- * -t (use TCP)
- * -b (broadcast)
- * -g (dataGram)
- * -rN (set retransmission count)
- * -pN (use port N instead of 18)
- * -lN (review messages)
- * -u (unread messages)
- * -sN (shorten buffer)
- * -eN (expire)
- * -c (check unread)
- */
-
- argcount = 0;
- while(numargs && *(*options)[argcount] == '-') {
- (*options)[argcount]++;
- switch (toupper(*(*options)[argcount])){
- case 'D':
- debug++;
- verbose++;
- break;
- case 'V':
- verbose++;
- break;
- case 'T':
- use_tcp = 1;
- break;
- case 'R':
- (*options)[argcount]++;
- retries = atoi((*options)[argcount]);
- break;
- case 'P':
- (*options)[argcount]++;
- port = atoi((*options)[argcount]);
- break;
- case 'B':
- #ifdef NO_BROADCAST
- fprintf(stderr, "Sorry, broadcast not available on this machine - not broadcasting.\n");
- #else
- broadcasting = 1;
- use_tcp = 0;
- #endif
- break;
- case 'G':
- use_tcp = 0;
- break;
- case 'L':
- (*options)[argcount]++;
- last_message(atoi((*options)[argcount]), shorten);
- exit(0);
- break;
- case 'U':
- unread_message(shorten);
- exit(0);
- break;
- case 'C':
- exit(check_unread());
- break;
- case 'S':
- (*options)[argcount]++;
- shorten = atoi((*options)[argcount]);
- if (shorten <= 0)
- shorten = 20;
- doshorten = 1;
- break;
- case 'E':
- (*options)[argcount]++;
- expire(atoi((*options)[argcount]));
- exit(0);
- break;
- default:
- usage();
- exit(1);
- /*NOTREACHED*/
- }
- argcount++;
- numargs--;
- }
-
- /* shorten if we need to */
- if (doshorten) {
- makeshort(shorten);
- exit(0);
- }
-
- if((numargs < 1) || (numargs > 2)) {
- usage();
- exit(1);
- /*NOTREACHED*/
- }
-
- /*
- * Rip apart the recipient field and set the user, term,
- * and host pointers.
- */
- recipient = (*options)[argcount];
-
- msg_text = numargs == 2 ? (*options)[argcount+1] : NULL;
-
- if(debug) printf("recipient is '%s'\n", recipient);
-
- host = (char *)STRCHR(recipient, '@');
- if(host == NULL)
- host = empty_arg;
- else
- *host++ = '\0';
-
- term = (char *)STRCHR(recipient, ':');
- if(term == NULL)
- term = empty_arg;
- else
- *term++ = '\0';
- if(!strcmp(term, "all")) /* external form is "all" */
- strcpy(term, "*"); /* protocol uses "*" */
-
- user = recipient;
-
- if(debug) printf("user = '%s', term='%s', host = '%s'\n",
- user, term, host);
-
- if (host[0] == '\0') {
- #ifdef USE_SYSINFO
- sysinfo(SI_HOSTNAME, local_name, sizeof(local_name));
- #else /* USE_SYSINFO */
- gethostname(local_name, sizeof(local_name));
- #endif /* USE_SYSINFO */
- host = local_name;
- }
-
- sin.sin_family = AF_INET;
-
- /*
- * compute the port to use: consult /etc/services, but if not
- * found use 18 (from the RFC). the -pN option overrides
- */
-
- if(port == 0) {
- sp = getservbyname("message", (use_tcp ? "tcp" : "udp"));
- if(sp)
- sin.sin_port = sp->s_port;
- else
- sin.sin_port = htons(18); /* from the RFC */
- }
- else
- sin.sin_port = htons(port);
-
-
- if(debug) printf("using port %d\n", htons(sin.sin_port));
-
- /*
- * check to see if we're broadcasting. otherwise build an address for
- * the designated host
- */
-
- if(!broadcasting) {
- hp = gethostbyname(host);
- if(hp == NULL) {
- /* XXX need to add stuff to handle dotted IP addresses */
- fprintf(stderr, "%s: unknown host: %s\n", prog, host);
- exit(2);
- }
- MEMCPY((char *)&sin.sin_addr, (char *)hp->h_addr, hp->h_length);
- }
-
- /*
- * now assemble the message. note that this procedure will only
- * return if the assembly is successful
- */
- assemble_message(user, term, msg_text);
-
- /*
- * if broadcast, invoke broadcast_msg
- */
- if(broadcasting) {
- udp_msg(&sin, retries, 1);
- exit(0);
- /*NOTREACHED*/
- }
-
-
- /*
- * if requested, attempt to send message via TCP
- */
- if(use_tcp)
- tcp_msg(&sin);
- /*
- * If tcp_msg returns, it means that it was unable to bind
- * to the port on the server. In this case, revert to UDP.
- */
- udp_msg(&sin, retries, 0);
- exit(0);
- }
- #endif
-
-
- /*
- * append a string to a message buffer, extra = 1 if we want
- * to add a trailing null-terminator into the message as well.
- * expands the buffer as necessary.
- */
-
- void
- append_buffer(buffer, bufsize, msglen, addstr, extra)
- char **buffer;
- int *bufsize;
- int *msglen;
- char *addstr;
- int extra;
- {
- int addlen;
-
- /* expand the buffer */
- addlen = strlen(addstr) + extra;
- if (*msglen + addlen > *bufsize) {
- /* get more space */
- *bufsize *= 2;
- *buffer = realloc(*buffer, *bufsize);
- if (*buffer == NULL) {
- fprintf(stderr, "Out of memory.\n");
- exit(1);
- }
- }
-
- strcpy(*buffer + *msglen, addstr);
- *msglen += addlen;
- }
-
-
- /*
- * assemble_message assembles a complete message in the buffer
- * msg and stores the length in msg_len. Note that, as defined
- * by the RFC, the message buffer includes embedded nulls.
- */
-
- void
- assemble_message(user, term, msg_text)
- char *user;
- char *term;
- char *msg_text;
- {
- char *r;
- char linebuff[256];
- char *dp;
- int buflen;
- FILE *sigfile;
- char *signature;
- char *homedir;
- struct passwd *pwd;
-
- /* make a buffer */
- buflen = 1024;
- msg = malloc(buflen);
- if (msg == NULL) {
- fprintf(stderr, "Out of memory.\n");
- exit(1);
- }
-
- /* make the message */
- *msg = 'B'; /* per RFC */
- msg_len = 1;
-
- filter(user);
- append_buffer(&msg, &buflen, &msg_len, user, 1);
- filter(term);
- append_buffer(&msg, &buflen, &msg_len, term, 1);
-
- if (msg_text)
- do_line(&msg, &buflen, &msg_len, msg_text);
- else {
- int is_tty = isatty(0);
-
- linebuff[sizeof(linebuff)-1] = '\0';
- if (is_tty) {
- puts("Enter your message (blank line to end):");
- #ifdef USE_READLINE
- while ((r = readline("> ")) != NULL && *r != '\0') {
- add_history(r);
- do_line(&msg, &buflen, &msg_len, r);
- }
- #else
- putchar('>');
- putchar(' ');
- /* eof or empty line terminates */
- while(((r = fgets(linebuff, sizeof(linebuff)-1, stdin)) != NULL) &&
- linebuff[1]) {
- do_line(&msg, &buflen, &msg_len, linebuff);
- putchar('>'); putchar(' ');
- }
- #endif
- if (r == NULL)
- /* we must have finished with ctrl-d */
- putchar('\n'); /* newline for style */
- }
- else
- while(fgets(linebuff, sizeof(linebuff)-1, stdin) != NULL)
- do_line(&msg, &buflen, &msg_len, linebuff);
- }
-
- append_buffer(&msg, &buflen, &msg_len, "", 1);
-
- #ifndef BUGGY_LOGNAME
- dp = (char *)getlogin();
- if (dp == NULL || *dp == '\0')
- #endif
- {
- struct passwd *me;
- me = getpwuid(getuid());
- if (me == NULL) {
- fprintf(stderr, "You don't exist - go away!\n");
- exit(1);
- }
- dp = me->pw_name;
- }
-
- append_buffer(&msg, &buflen, &msg_len, dp, 1);
- if(debug) printf("sender username is '%s'\n", (dp ? dp : empty_arg));
- dp = (char *)ttyname(2); /* check standard error */
- if (dp == NULL) {
- append_buffer(&msg, &buflen, &msg_len, empty_arg, 1);
- } else {
- append_buffer(&msg, &buflen, &msg_len, dp, 1);
- }
- if(debug) printf("sender terminal is '%s'\n", (dp ? dp : empty_arg));
-
- sprintf(linebuff, "%ld", time(NULL));
- append_buffer(&msg, &buflen, &msg_len, linebuff, 1);
- if(debug) printf("cookie is '%s'\n", linebuff);
-
- /*
- * Generate a signature from $HOME/.msgsig
- */
-
- homedir = (char *)getenv("HOME");
- if (homedir == NULL) {
- pwd = (struct passwd *)getpwnam(dp);
- homedir = pwd->pw_dir;
- }
- sprintf(linebuff, "%s/.msgsig", homedir);
- signature = empty_arg;
- sigfile = fopen(linebuff, "r");
- if (sigfile != NULL) {
- linebuff[sizeof(linebuff)-1] = '\0';
- if (fgets(linebuff, sizeof(linebuff)-1, sigfile) != NULL) {
- if (linebuff[strlen(linebuff)-1] == '\n')
- linebuff[strlen(linebuff)-1] = '\0';
- filter(linebuff);
- signature = linebuff;
- }
- fclose(sigfile);
- }
-
- if(debug) printf("signature is '%s'\n", signature);
- append_buffer(&msg, &buflen, &msg_len, signature, 1);
-
- if(debug) printf("total message length is %d\n", msg_len);
- }
-
- void
- do_line(buffer, bufsize, msglen, linebuff)
- char **buffer;
- int *bufsize;
- int *msglen;
- char *linebuff;
- {
- int addlen;
-
- filter(linebuff);
- addlen = strlen(linebuff);
- if (addlen > 0 && linebuff[addlen-1] == '\n')
- linebuff[addlen-1] = '\0'; /* minus the terminating LF */
- append_buffer(buffer, bufsize, msglen, linebuff, 0);
- append_buffer(buffer, bufsize, msglen, "\r\n", 0);
- }
-
- /*
- * tcp_msg(sp)
- * sp points at a sockaddr_in which contains the
- * port to be used.
- *
- * Send the assembled message using TCP. If the attempt is
- * successful, the program exits with a status of 0. If a client-
- * side error occurs (e.g. unable to open a socket) the program
- * exits with a positive non-zero status. If it proves impossible
- * to connect to the server, an error message is displayed and
- * the procedure returns. This allows the caller to retry using
- * UDP.
- */
-
- void
- tcp_msg (sp)
- struct sockaddr_in *sp;
- {
- int s;
- struct sockaddr_in sin;
- char rcvbuf[256];
- int rval;
-
- if(debug) printf("invoked tcp_msg()\n");
-
- if((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
- fprintf(stderr, "%s: unable to open socket.\n", prog);
- perror("Reason");
- exit(3);
- }
-
- sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = htonl(INADDR_ANY);
- sin.sin_port = htons(0);
-
- if(BIND(s, (struct sockaddr *)&sin, sizeof sin) < 0) {
- fprintf(stderr, "%s: unable to set local socket address.\n", prog);
- perror("Reason");
- exit(3);
- }
-
- if(connect(s, (struct sockaddr *)sp, sizeof (*sp)) < 0) {
- fprintf(stderr, "%s: unable to connect to TCP server.\n",
- prog);
- perror("Reason");
- return;
- /*NOTREACHED*/
- }
-
- if(verbose)
- printf("sending message...\n");
- if(write(s, msg, msg_len) < 0) {
- fprintf(stderr, "%s: unable to send message.\n", prog);
- perror("Reason");
- if (close(s))
- perror("close");
- exit(3);
- }
- /*
- * wait for reply
- */
- rval = read(s, rcvbuf, sizeof rcvbuf);
- if (rval < 1) {
- fprintf(stderr, "%s: no reply received.\n", prog);
- perror("Reason");
- if (close(s))
- perror("close");
- exit(3);
- }
- rcvbuf[(rval < sizeof(rcvbuf)) ? rval : sizeof(rcvbuf)-1] = 0;
- if (debug) printf("reply:'%s'\n", rcvbuf);
- if (rcvbuf[0] == '+') {
- if (verbose) printf("message delivered to recipient (%s)\n",
- rcvbuf+1);
- exit(0);
- /*NOTREACHED*/
- }
- else if (rcvbuf[0] == '-') {
- printf("Message wasn't delivered - %s.\n", rcvbuf+1);
- exit(1);
- /*NOTREACHED*/
- }
- else {
- printf("Message wasn't delivered.\n");
- exit(2);
- /*NOTREACHED*/
- }
- }
-
- /*
- * udp_msg(sp, r)
- * sp points at a sockaddr_in which contains the
- * port to be used.
- * r is the retry count to be used.
- * broad is set if it's to be broadcast
- *
- * Send the assembled message to a specific destination using UDP.
- * This procedure will never return - it always exits with an
- * appropriate status code.
- */
-
- void
- udp_msg(sp, r, broad)
- struct sockaddr_in *sp;
- int r;
- int broad;
- {
- int s;
- int delivered = 0;
- struct sockaddr_in sin;
- fd_set ready;
- struct timeval to;
- int rval;
- int toutwait;
- int i;
-
- if(debug) printf("invoked udp_msg(...,%d)\n", r);
-
- if((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
- fprintf(stderr, "%s: unable to open socket.\n", prog);
- perror("Reason");
- exit(3);
- }
-
- #ifndef NO_BROADCAST
- if (broad) {
- i = 1;
- if(setsockopt(s, SOL_SOCKET, SO_BROADCAST, &i, sizeof i) < 0) {
- fprintf(stderr, "%s: unable to configure socket for broadcast.\n", prog);
- perror("Reason");
- exit(3);
- }
-
- find_broadcast_addresses(s);
- }
- #endif
-
- sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = htonl(INADDR_ANY);
- sin.sin_port = htons(0);
-
- if(bind(s, (struct sockaddr *)&sin, sizeof sin) < 0) {
- fprintf(stderr, "%s: unable to set local socket address.\n", prog);
- perror("Reason");
- exit(3);
- }
-
- /*
- * the timeout wait starts at three seconds and backs off
- * by two seconds each time we retry
- */
- toutwait = 3;
-
- /* send the message */
- while(r--) {
- if(verbose)
- printf("sending message...\n");
- if (broad) {
- #ifndef NO_BROADCAST
- for (i = 0; i < if_n; i++){
- if_a[i].sin_port = sp->sin_port;
- if(verbose) printf("sending message to %s\n",
- inet_ntoa(if_a[i].sin_addr));
- if(sendto(s, msg, msg_len, 0, (struct sockaddr *)&(if_a[i]),
- sizeof if_a[i]) < 0) {
- fprintf(stderr, "%s: unable to send message.\n", prog);
- perror("Reason");
- exit(3);
- }
- }
- #endif
- }
- else {
- if(sendto(s, msg, msg_len, 0, (struct sockaddr *)sp, sizeof(*sp)) < 0) {
- fprintf(stderr, "%s: unable to send message.\n", prog);
- perror("Reason");
- exit(3);
- }
- }
- if(r) {
- /*
- * wait for reply or timeout
- */
- to.tv_sec = toutwait;
- to.tv_usec = 0;
- FD_ZERO(&ready);
- FD_SET(s, &ready);
- rval = select(20, &ready, (fd_set *)0, (fd_set *)0, &to);
- if(rval < 0)
- fprintf(stderr, "%s: interrupt\n", prog);
- if(rval == 1) {
- delivered = 1;
- udp_decode_ack(s);
- break;
- }
- /*
- * falling through, must be interrupt or timeout
- */
- toutwait += 2;
- }
- }
- if (!delivered)
- printf("Message unacknowledged - may not have been received.\n");
- if(debug) printf("closing and exiting\n");
- close(s);
- exit(0);
- /*NOTREACHED*/
- }
-
-
- #ifndef NO_BROADCAST
- /*
- * find_broadcast_addresses
- *
- * This procedure is used by broadcast_msg to determine all of the
- * network interfaces configred on the local system, so that the
- * message can be broadcast over each of them. This logic is derived
- * from the SunOS documentation, and has also been tested on SVR4:
- * anyone porting this program to significantly different systems
- * should check this area carefully.
- *
- * The procedure uses the SIOCGIFCONF ioctl to retrieve the
- * interfaces. For each one, it retrieves the flags via SIOCGIFFLAGS.
- * For a point-to-point interface, the peer address is fetched using
- * SIOCGIFDSTADDR. For a broadcast inteface, the broadcast address
- * is obtained using SIOCGIFBRDADDR. The addresses are accumulated
- * in the array if_a, and if_n holds the count of addresses found.
- */
-
- void
- find_broadcast_addresses(s)
- int s;
- {
- struct ifconf ifc;
- struct ifreq *ifr;
- char buf[4096], *cp, *cplim;
- int n;
-
- if_n = 0;
-
- ifc.ifc_len = sizeof buf;
- ifc.ifc_buf = buf;
-
- if(ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) {
- fprintf(stderr, "%s: SIOCGIFCONF failed.\n", prog);
- perror("Reason");
- exit(3);
- }
- ifr = ifc.ifc_req;
- n = ifc.ifc_len/sizeof(struct ifreq);
- if(debug)
- printf("checking %d interfaces returned by SIOCGIFCONF...\n",
- n);
-
- #ifdef RTM_ADD
- #define max(a, b) (a > b ? a : b)
- #define size(p) max((p).sa_len, sizeof(p))
- #else
- #define size(p) (sizeof (p))
- #endif
-
- cplim = buf + ifc.ifc_len; /*skip over if's with big ifr_addr's */
- for (cp = buf; cp < cplim;
- cp += sizeof (ifr->ifr_name) + size(ifr->ifr_addr)) {
- ifr = (struct ifreq *)cp;
- if(ifr->ifr_addr.sa_family != AF_INET) {
- continue;
- }
- if(ioctl(s, SIOCGIFFLAGS, (char *)ifr) < 0) {
- perror("SIOCGIFFLAGS");
- continue;
- }
- if((ifr->ifr_flags & IFF_UP) == 0 ||
- (ifr->ifr_flags & IFF_LOOPBACK) ||
- (ifr->ifr_flags & (IFF_BROADCAST|IFF_POINTOPOINT)) == 0)
- continue;
- if(ifr->ifr_flags & IFF_POINTOPOINT) {
- if(ioctl(s, SIOCGIFDSTADDR, (char *)ifr) < 0) {
- perror("SIOCGIFDSTADDR");
- continue;
- }
- MEMCPY((char *)&if_a[if_n++], (char *)&ifr->ifr_dstaddr,
- sizeof ifr->ifr_dstaddr);
- } else if(ifr->ifr_flags & IFF_BROADCAST) {
- if(ioctl(s, SIOCGIFBRDADDR, (char *)ifr) < 0) {
- perror("SIOCGIFBRDADDR");
- continue;
- }
- MEMCPY((char *)&if_a[if_n++], (char *)&ifr->ifr_broadaddr,
- sizeof ifr->ifr_broadaddr);
- }
- }
-
- if(debug)
- printf("found %d interfaces\n", if_n);
- if(if_n == 0) {
- fprintf(stderr, "%s: no applicable network interfaces\n", prog);
- exit(3);
- /*NOTREACHED*/
- }
- }
- #endif /* NO_BROADCAST */
-
-
- /* read & decode the server's acknowledgement */
- void
- udp_decode_ack(s)
- int s;
- {
- struct sockaddr_in from;
- int fromlen, rval;
- char rcvbuf[256];
-
- fromlen = sizeof(fromlen);
- rval = recvfrom(s, rcvbuf, sizeof rcvbuf, 0,
- (struct sockaddr *)&from, &fromlen);
-
- if (rval < 0) {
- perror("recvfrom");
- return;
- }
- rcvbuf[(rval < sizeof(rcvbuf)) ? rval : sizeof(rcvbuf)-1] = 0;
-
- if (rcvbuf[0] == '+') {
- if (verbose)
- printf("message delivered to recipient (%s)\n",
- rcvbuf+1);
- }
- else if (rcvbuf[0] == '-')
- printf("Message wasn't delivered - %s.\n", rcvbuf+1);
- else
- printf("Unknown message acknowledgement (%s)\n", rcvbuf);
- }
-
-
- /*
- * As noted in the RFC, it is important to filter out control
- * chracters and suchlike, since there may exist terminals
- * which will behave in bizarre and security-violating ways
- * if presented with certain control code sequences. The
- * server will also be filtering messages, but it is incumbent
- * upon a well-written client implementation to send only "clean"
- * messages. After all, there may exist servers which will reject
- * any message which does not filter cleanly.
- *
- * It is an open question as to how the filtering should be done.
- * One approach might be to squeeze out any invalid characters
- * silently. This would make debugging difficult. This implementation
- * replaces all non-printable characters with '?' characters.
- */
-
- void
- filter(text)
- char *text;
- {
- while (*text) {
- if(!isprint(*text) && !isspace(*text))
- *text = '?';
- text++;
- }
- }
-