home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
AmigActive 15
/
AACD15.ISO
/
AACD
/
Online
/
SpeakFreely
/
src
/
lwl.c
< prev
next >
Wrap
C/C++ Source or Header
|
2000-09-30
|
12KB
|
468 lines
/*
Speak Freely for Unix
Look Who's Listening Client
*/
#include "speakfree.h"
#include "version.h"
static int sock; /* Our socket */
static char *prog; /* Program name */
static struct sockaddr_in lookhost; /* Look who's listening host, if any */
static int lwlport = Internet_Port + 2; /* Look Who's Listening port */
static int debugging = FALSE; /* Debug mode enabled */
static int showmessage = FALSE; /* Show server message */
struct lwl {
struct lwl *next; /* Next connection */
long ltime; /* Time of last update */
unsigned long ssrc; /* Session source descriptor */
long naddr; /* Internet address */
short port; /* Port address */
char *cname; /* Canonical name */
char *name; /* User name */
char *email; /* Electronic mail address */
char *phone; /* Telephone number */
char *loc; /* Geographic location */
char *tool; /* Application name */
};
/* PROG_NAME -- Extract program name from argv[0]. */
static char *prog_name(arg)
char *arg;
{
char *cp = strrchr(arg, '/');
return (cp != NULL) ? cp + 1 : arg;
}
/* USAGE -- Print how-to-call information. */
static void usage()
{
V fprintf(stderr, "%s -- Speak Freely: Look Who's Listening Lookup.\n", prog);
V fprintf(stderr, " %s.\n", Relno);
V fprintf(stderr, "\n");
V fprintf(stderr, "Usage: %s [options]\n", prog);
V fprintf(stderr, "Options:\n");
V fprintf(stderr, " -C Output sfmike connection address(es)\n");
V fprintf(stderr, " -D Debugging output on stderr\n");
V fprintf(stderr, " -Hhost:port Query designated host\n");
V fprintf(stderr, " -L List table of matches\n");
V fprintf(stderr, " -M Show server message\n");
V fprintf(stderr, " -U Print this message\n");
V fprintf(stderr, "\n");
V fprintf(stderr, "by John Walker\n");
V fprintf(stderr, " http://www.fourmilab.ch/\n");
}
/* DUPSDESITEM -- Make a copy of an SDES item and advance the pointer
past it. */
static char *dupSdesItem(cp)
char **cp;
{
char *ip = *cp, *bp;
int l = ip[1] & 0xFF;
bp = malloc(l + 1);
if (bp != NULL) {
bcopy(ip + 2, bp, l);
bp[l] = 0;
}
*cp = ip + l + 2;
return bp;
}
/* DESTROYLWL -- Release storage associated with an LWL list item. */
static void destroyLwl(lw)
struct lwl *lw;
{
if (lw->cname != NULL) {
free(lw->cname);
}
if (lw->name != NULL) {
free(lw->name);
}
if (lw->email != NULL) {
free(lw->email);
}
if (lw->phone != NULL) {
free(lw->phone);
}
if (lw->loc != NULL) {
free(lw->loc);
}
if (lw->tool != NULL) {
free(lw->tool);
}
free(lw);
}
/* DUMPLWL -- Dump an LWL on the specified stream. */
static void dumpLwl(fo, lw)
FILE *fo;
struct lwl *lw;
{
struct sockaddr_in s;
s.sin_addr.s_addr = lw->naddr;
fprintf(fo, "SSRC = %X IP = %s Port %d %s", lw->ssrc, inet_ntoa(s.sin_addr),
lw->port, ctime(&(lw->ltime)));
if (lw->cname != NULL) {
fprintf(fo, " CNAME = %s\n", lw->cname);
}
if (lw->name != NULL) {
fprintf(fo, " NAME = %s\n", lw->name);
}
if (lw->email != NULL) {
fprintf(fo, " EMAIL = %s\n", lw->email);
}
if (lw->phone != NULL) {
fprintf(fo, " PHONE = %s\n", lw->phone);
}
if (lw->loc != NULL) {
fprintf(fo, " LOC = %s\n", lw->loc);
}
if (lw->tool != NULL) {
fprintf(fo, " TOOL = %s\n", lw->tool);
}
}
/* Main program. */
main(argc, argv)
int argc;
char *argv[];
{
int i, argie, length, nret = 0, connex = FALSE,
listing = FALSE, deefault = TRUE;
struct sockaddr_in name;
char *hostspec = NULL, *cp;
/* Process command line options. */
prog = prog_name(argv[0]);
for (argie = 1; argie < argc; argie++) {
char *op, opt;
op = argv[argie];
if (*op == '-') {
opt = *(++op);
if (islower(opt)) {
opt = toupper(opt);
}
switch (opt) {
case 'C': /* -C -- Output connect addresses */
connex = TRUE;
deefault = FALSE;
break;
case 'D': /* -D -- Debug output to stderr */
debugging = TRUE;
break;
case 'H': /* -Hhost:port -- Host/port to query */
hostspec = op + 1;
break;
case 'L': /* -L -- List table of finds */
listing = TRUE;
deefault = FALSE;
break;
case 'M': /* -M -- Show server message */
showmessage = TRUE;
break;
case 'U': /* -U -- Print usage information */
case '?': /* -? -- Print usage information */
usage();
return 0;
}
} else {
break;
}
}
/* Try to locate host to contact for information. */
if ((cp = hostspec) == NULL) {
cp = getenv("SPEAKFREE_LWL_ASK");
if (cp == NULL || strlen(cp) == 0) {
char *np;
cp = getenv("SPEAKFREE_LWL_TELL");
if (cp == NULL) {
fprintf(stderr, "%s: no host specified.\n", prog);
fprintf(stderr, "%s: use -Hhost:port option or SPEAKFREE_LWL_ASK\n", prog);
fprintf(stderr, "%s: or SPEAKFREE_LWL_TELL environment variables.\n", prog);
return 2;
}
/* Multiple hosts may have been specified on the
SPEAKFREE_LWL_TELL statement. If so, query only the
first. */
if ((np = strchr(cp, ',')) != NULL) {
*np = 0;
}
}
}
if (cp != NULL) {
struct hostent *h;
char *ep;
if ((ep = strchr(cp, ':')) != NULL) {
*ep = 0;
lwlport = atoi(ep + 1);
}
h = gethostbyname(cp);
if (h != NULL) {
bcopy((char *) (h->h_addr), (char *) &lookhost.sin_addr.s_addr,
sizeof lookhost.sin_addr.s_addr);
lookhost.sin_family = AF_INET;
lookhost.sin_port = htons(lwlport);
} else {
fprintf(stderr, "%s: server %s is unknown.\n", prog, cp);
return 2;
}
}
/* Now loop through the command line arguments and pose
each as a query to the server, then print whatever
reply we get. */
for (; showmessage || (argie < argc); argie++) {
char p[1500];
rtcp_t *rp = (rtcp_t *) p;
static char query[] = "SFlq";
int l;
char *cp;
/* Create the socket */
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
perror("opening stream socket");
return 1;
}
if (connect(sock, (struct sockaddr *) &lookhost, sizeof lookhost) < 0) {
perror("connecting stream socket");
return 1;
}
/* Find assigned port value and print it. */
length = sizeof(name);
if (getsockname(sock, (struct sockaddr *) &name, &length) < 0) {
perror("getting socket name");
return 1;
}
#ifdef SHOW_SOCKET
fprintf(stderr, "%s: socket port #%d\n", prog, ntohs(name.sin_port));
#endif
#ifdef RationalWorld
rp->common.version = RTP_VERSION;
rp->common.p = 0;
rp->common.count = 1;
rp->common.pt = RTCP_APP;
#else
*((short *) rp) = htons((RTP_VERSION << 14) | RTCP_APP | (1 << 8));
#endif
rp->r.sdes.src = 0;
if (showmessage) {
argie--;
bcopy("SFms", p + 8, 4);
rp->common.length = htons(2);
if (send(sock, p, 12, 0) < 0) {
perror("sending server message request");
}
} else {
bcopy(query, p + 8, 4);
strcpy(p + 12, argv[argie]);
cp = p + 13 + strlen(p + 12);
while ((cp - p) & 3) {
*cp++ = 0;
}
rp->common.length = htons(((cp - p) / 4) - 1);
if (send(sock, p, cp - p, 0) < 0) {
perror("sending look who's listening query message");
}
}
if ((l = recv(sock, p, sizeof p, 0)) > 0) {
if (showmessage) {
showmessage = FALSE;
fwrite(p + 12, l - 13, 1, stdout);
} else {
int sdes_count;
#ifdef RationalWorld
sdes_count = rp->common.count;
#else
sdes_count = (((unsigned char *) rp)[0]) & 0x1F;
#endif
cp = (char *) &(rp->r.sdes.src);
while (sdes_count-- > 0) {
struct lwl *lw;
lw = (struct lwl *) malloc(sizeof(struct lwl));
if (lw != NULL) {
int parsing = TRUE;
struct sockaddr_in u;
char s[40];
bzero((char *) lw, sizeof(struct lwl));
bcopy(cp, (char *) &(lw->ssrc), 4);
cp += 4;
while (parsing) {
switch ((*cp) & 0xFF) {
case RTCP_SDES_CNAME:
lw->cname = dupSdesItem(&cp);
break;
case RTCP_SDES_NAME:
lw->name = dupSdesItem(&cp);
break;
case RTCP_SDES_EMAIL:
lw->email = dupSdesItem(&cp);
break;
case RTCP_SDES_PHONE:
lw->phone = dupSdesItem(&cp);
break;
case RTCP_SDES_LOC:
lw->loc = dupSdesItem(&cp);
break;
case RTCP_SDES_TOOL:
lw->tool = dupSdesItem(&cp);
break;
case RTCP_SDES_PRIV:
{
char *zp = dupSdesItem(&cp);
if (zp != NULL) {
if (zp[0] == 1 &&
zp[1] == 'P') {
lw->port = atoi(zp + 2);
} else if (zp[0] == 1 &&
zp[1] == 'I') {
lw->naddr = inet_addr(zp + 2);
} else if (zp[0] == 1 &&
zp[1] == 'T') {
lw->ltime = atol(zp + 2);
}
free(zp);
}
}
break;
case RTCP_SDES_END:
cp++;
while ((cp - p) & 3) {
cp++;
}
parsing = FALSE;
break;
default:
{
char *zp = dupSdesItem(&cp);
if (zp != NULL) {
free(zp);
}
}
break;
}
}
if (debugging) {
dumpLwl(stderr, lw);
}
u.sin_addr.s_addr = lw->naddr;
/* Default output listing: short address/cname (name) list. */
if (deefault) {
char ipport[40], deef[256];
sprintf(ipport, "%s:%d", inet_ntoa(u.sin_addr), lw->port);
sprintf(deef, "%-24s %s", ipport, lw->cname);
if (lw->name) {
sprintf(deef + strlen(deef), " (%s)", lw->name);
}
printf("%s\n", deef);
}
/* Output connect IP:port arguments if requested. */
if (connex) {
printf("%s-p%s:%d", nret > 0 ? " " : "",
inet_ntoa(u.sin_addr), lw->port);
}
/* Produce long tabular listing of results. */
if (listing) {
char ipport[40];
struct tm *lt;
lt = localtime(&lw->ltime);
sprintf(ipport, "%s:%d", inet_ntoa(u.sin_addr), lw->port);
printf("\n%-24s %-48s %02d:%02d\n", ipport, lw->cname,
lt->tm_hour, lt->tm_min);
if (lw->name != NULL) {
printf("%25s%s\n", "", lw->name);
}
if (lw->loc != NULL) {
printf("%25s%s\n", "", lw->loc);
}
if (lw->phone != NULL) {
printf("%25sPhone: %s\n", "", lw->phone);
}
if (lw->email != NULL) {
printf("%25sE-mail: %s\n", "", lw->email);
}
}
nret++;
destroyLwl(lw);
}
}
}
}
if (l <= 0) {
perror("reading reply from socket");
return 2;
}
close(sock);
}
if (connex) {
if (nret > 0) {
printf("\n");
} else {
fprintf(stderr, "No users found.\n");
return 2;
}
}
return 0;
}