/*
* USERLIST.C
*
* Written by Paul Edwards and modified by Bill Bond.
* Modified to make it do a binary search by Bill Bond.
* Modfied by Tobias Ernst (based on code by Kim Lykkegaard) to support
* multiple results for a single lookup.
* Released to the public domain.
*
* Look up user name in a Fido userlist.
*
* Note: The Fido userlist consists of fixed length records sorted
* alphabetically. A record is in the format:
*
* Bloggs, Joe 3:666/666
*/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include "addr.h"
#include "nedit.h"
#include "winsys.h"
#include "keys.h"
#include "menu.h"
#include "msged.h"
#include "memextra.h"
#include "strextra.h"
#include "nshow.h"
#include "userlist.h"
#include "screen.h"
#include "mctype.h"
#define SELBOX_WRTOVER 7
#if defined(MSDOS) && (!defined(__FLAT__))
#define LOOKUPMAX 200 /* prevent memory exhaustage */
#else
#define LOOKUPMAX 200000L
#endif
#define LOOKUPSTEP 50
static long filelen(FILE * fp)
{
long ret;
ret = fseek(fp, 0, SEEK_END);
if (ret != 0L)
{
return (0L);
}
ret = ftell(fp);
if (ret < 0)
{
ret = 0;
}
return ret;
}
ADDRESS lookup(char *name, char *fn)
{
FILE *fp;
ADDRESS tmpAddr;
char buf[200];
char revName[200];
char **nodeinfo = NULL;
int lenRev, result, fureclen = 1, done = 0;
int i, j, k;
long found = 0, lookupmax = 0L;
long low, mid, high;
char *p;
tmpAddr = CurArea.addr;
if (tmpAddr.domain != NULL)
{
tmpAddr.domain = xstrdup(tmpAddr.domain);
}
tmpAddr.notfound = 1;
fp = fopen(fn, "r");
if (fp == NULL)
{
return (tmpAddr);
}
makeReverse(revName, name);
strlwr(revName);
lenRev = strlen(revName);
if (fgets(buf, sizeof buf, fp) != NULL)
{
fureclen = strlen(buf);
#ifndef UNIX
fureclen++; /* take the \r character into account */
/* i++; */
#endif
}
high = filelen(fp) / fureclen;
low = 0;
while (low <= high && !done)
{
mid = low + (high - low) / 2;
fseek(fp, (long)mid * fureclen, SEEK_SET);
if (fgets(buf, sizeof buf, fp) != NULL)
{
strlwr(buf);
result = strncmp(buf, revName, lenRev);
if (result > 0)
{
high = mid - 1;
}
else if (result < 0)
{
low = mid + 1;
}
else
{
if (!OpenMsgWnd(50, 6, " Scanning Fido User List ",
NULL, 0, 0))
{
return tmpAddr;
}
SendMsgWnd("Press Esc to stop", 1);
/* seek backwards to find the first match */
while (result == 0)
{
mid=mid-10;
if (mid<0)
{
fseek(fp, 0L, SEEK_SET);
mid = 0;
break;
}
fseek(fp, (long)mid * fureclen, SEEK_SET);
fgets(buf, sizeof buf, fp);
strlwr(buf);
result = strncmp(buf, revName, lenRev);
if (KeyHit() && GetKey() == Key_Esc)
{
CloseMsgWnd();
return tmpAddr;
}
}
/* we seeked backwards too far, now find the first match. */
while (result != 0)
{
fgets(buf, sizeof buf, fp);
strlwr(buf);
result = strncmp(buf, revName, lenRev);
if (KeyHit() && GetKey() == Key_Esc)
{
CloseMsgWnd();
return tmpAddr;
}
}
/* Now we have found the first match. Implement a lookup
window */
while (result == 0)
{
/* kill trailing LFs and CRs */
if (buf[strlen(buf)-1]=='\n')
{
buf[strlen(buf)-1]='\0';
}
if (buf[strlen(buf)-1]=='\r')
{
buf[strlen(buf)-1]='\0';
}
/* uppercase the first letters of the name */
buf[0] = toupper(buf[0]);
for(i = 1; *buf && i < strlen(buf) - 1; i++)
{
if ((buf[i] == ' ') && (buf[i+1] != ' '))
{
buf[i + 1] = toupper(buf[i + 1]);
}
}
if (found + 1 >= lookupmax)
{
if (lookupmax + LOOKUPSTEP > LOOKUPMAX)
{
break;
}
if (lookupmax == 0)
{
lookupmax = LOOKUPSTEP;
nodeinfo = xmalloc(sizeof(char *) * lookupmax);
}
else
{
lookupmax += LOOKUPSTEP;
nodeinfo = xrealloc(nodeinfo,
sizeof(char *) * lookupmax);
}
}
nodeinfo[found++] = xstrdup(buf);
if (fgets(buf, sizeof buf, fp) == NULL)
{
break;
}
strlwr(buf);
result = strncmp(buf, revName, lenRev);
if (KeyHit() && GetKey() == Key_Esc)
{
CloseMsgWnd();
return tmpAddr;
}
}
nodeinfo[found++] = NULL;
CloseMsgWnd();
result = DoMenu(8, 7, 8+61,
(5 + found > maxy - 4) ? maxy - 4 : 5 + found,
nodeinfo, 0,
SELBOX_WRTOVER, " Nodelist Lookup ");
if (result == (unsigned long) - 1)
{
fclose(fp);
return tmpAddr;
}
strcpy(buf, nodeinfo[result]);
/* Use the name as it was found in the userlist */
i = strlen(buf) - 1;
while (i > 0 && m_isspace(buf[i]))
{
i--;
}
while (i > 0 && !m_isspace(buf[i]))
{
i--;
}
while (i > 0 && m_isspace(buf[i]))
{
i--;
}
j = i;
while (i > 0 && buf[i] != ',')
{
i--;
}
if (buf[i] == ',')
{
if (buf[i + 1] == ' ')
{
i++;
}
if (j - i + 1 > 0)
{
memmove(name, buf + i + 1, j - i);
}
k = i;
if (buf[i] == ' ')
{
i--;
}
if (i > 0)
{
name[j - k] = ' ';
memmove(name + j - k + 1, buf, k);
name[j] = '\0';
}
}
else
{
if (j != 0)
{
memcpy(name, buf, j + 1);
name[j+2] = '\0';
}
else
{
name[0] = '\0';
}
}
for(i = 0; i < found; i++)
{
if (nodeinfo[i] == NULL)
{
break;
}
xfree(nodeinfo[i]);
}
p = buf + strlen(buf) - 1;
while ((p >= buf) && (m_isspace(*p)))
{
*p = '\0';
p--;
}
while ((p >= buf) && (!m_isspace(*p)))
{
p--;
}
if ((p >= buf) && (m_isspace(*p)))
{
p++;
}
if (tmpAddr.domain != NULL)
{
xfree(tmpAddr.domain);
}
fclose(fp);
return parsenode(p);
}
}
else
{
done = 0; /* force end of loop */
}
}
fclose(fp);
return tmpAddr;
}
void makeReverse(char *revName, char *name)
{
char *lastSpace;
int len;
lastSpace = strrchr(name, ' ');
if (lastSpace == NULL)
{
strcpy(revName, name);
return;
}
len = strlen(lastSpace + 1);
memcpy(revName, lastSpace + 1, len);
memcpy(revName + len, ", ", 2);
memcpy(revName + len + 2, name, (size_t) (lastSpace - name));
*(revName + len + 2 + (size_t) (lastSpace - name)) = '\0';
}
syntax highlighted by Code2HTML, v. 0.9.1