/*--------------------------------------------------------------------------*/ /* */ /* */ /* ------------ Bit-Bucket Software, Co. */ /* \ 10001101 / Writers and Distributors of */ /* \ 011110 / Freely Available Software. */ /* \ 1011 / */ /* ------ */ /* */ /* (C) Copyright 1987-96, Bit Bucket Software Co. */ /* */ /* This module was adapted by Bill Andrus */ /* With the usual kibitzing by Vince Perriello */ /* BinkleyTerm Version7 Nodelist processing module */ /* */ /* */ /* For complete details of the licensing restrictions, please refer */ /* to the License agreement, which is published in its entirety in */ /* the MAKEFILE and BT.C, and also contained in the file LICENSE.260. */ /* */ /* USE OF THIS FILE IS SUBJECT TO THE RESTRICTIONS CONTAINED IN THE */ /* BINKLEYTERM LICENSING AGREEMENT. IF YOU DO NOT FIND THE TEXT OF */ /* THIS AGREEMENT IN ANY OF THE AFOREMENTIONED FILES, OR IF YOU DO */ /* NOT HAVE THESE FILES, YOU SHOULD IMMEDIATELY CONTACT BIT BUCKET */ /* SOFTWARE CO. AT ONE OF THE ADDRESSES LISTED BELOW. IN NO EVENT */ /* SHOULD YOU PROCEED TO USE THIS FILE WITHOUT HAVING ACCEPTED THE */ /* TERMS OF THE BINKLEYTERM LICENSING AGREEMENT, OR SUCH OTHER */ /* AGREEMENT AS YOU ARE ABLE TO REACH WITH BIT BUCKET SOFTWARE, CO. */ /* */ /* */ /* You can contact Bit Bucket Software Co. at any one of the following */ /* addresses: */ /* */ /* Bit Bucket Software Co. FidoNet 1:104/501, 1:343/491 */ /* P.O. Box 460398 AlterNet 7:42/1491 */ /* Aurora, CO 80046 BBS-Net 86:2030/1 */ /* Internet f491.n343.z1.fidonet.org */ /* */ /* Please feel free to contact us at any time to share your comments about */ /* our software and/or licensing policies. */ /* */ /*--------------------------------------------------------------------------*/ /* Include this file before any other includes or defines! */ #include "includes.h" /* This table has been modified to minimize searches */ char unwrk[] = " EANROSTILCHBDMUGPKYWFVJXZQ-'0123456789"; static long LOCALFUNC btree (char *, void *, int (LOCALFUNC *) (void *, void *, int)); static int LOCALFUNC get_ver7_info (unsigned long, ADDRP); static struct _ndx far *LOCALFUNC get7node (HFILE, unsigned long, struct _ndx far *); static void LOCALFUNC unpk (char *instr, char *outp, int many); static int LOCALFUNC addr_compare (void *, void *, int); static int LOCALFUNC name_compare (void *, void *, int); extern int get_nodelist_name (ADDRP); extern char *nodelist_base; extern char *nodelist_name; static char index_filename[260]; static int namelen; static struct _ndx far *nodeidx = NULL; /* index file */ static struct _ndx far *noderef = NULL; /* index file */ int ver7find (ADDRP opus_addr, int have_boss_data) { long record; ADDR found_addr; have_boss_data = have_boss_data; newnodedes.NetNumber = newnodedes.NodeNumber = 0; if (!get_nodelist_name (opus_addr)) return 0; index_filename[0] = '\0'; /* "null-terminated string*/ (void) strcpy (index_filename, net_info); /* take nodelist path */ (void) strcat (index_filename, nodelist_base); /* add in the file name*/ (void) strcat (index_filename, ".NDX"); /* add in the file ext */ record = btree (index_filename, (void *) opus_addr, addr_compare); if (record == -1) return (0); else return (get_ver7_info ((unsigned long) record, &found_addr)); } static int LOCALFUNC addr_compare (void *key, void *desired, int len) { int k; k = ((ADDRP) key)->Zone - ((ADDRP) desired)->Zone; if (k) return (k); k = ((ADDRP) key)->Net - ((ADDRP) desired)->Net; if (k) return (k); k = ((ADDRP) key)->Node - ((ADDRP) desired)->Node; if (k) return (k); /* * Node matches. * * The rule for points: * 1) If len == 6, treat key value for Point as Zero. * 2) Return comparison of key Point and desired Point. */ if (len == 6) ((ADDRP) key)->Point = 0; return ((ADDRP) key)->Point - ((ADDRP) desired)->Point; } void opususer (char *name, ADDRP faddr) { char last_name_first[80]; char midname[80]; char *c, *p, *m; long record; faddr->Zone = faddr->Net = faddr->Node = faddr->Point = (unsigned short) -1; faddr->Domain = NULL; c = midname; /* Start of temp name buff */ p = name; /* Point to start of name */ m = NULL; /* Init pointer to space */ *c = *p++; while (*c) /* Go entire length of name */ { if (*c == ' ') /* Look for space */ m = c; /* Save location */ c++; *c = *p++; } if (m != NULL) /* If we have a pointer, */ { *m++ = '\0'; /* Terminate the first half */ (void) strcpy (last_name_first, m); /* Now copy the last name */ (void) strcat (last_name_first, ", "); /* Insert a comma and space */ (void) strcat (last_name_first, midname); /* Finally copy first half */ } else (void) strcpy (last_name_first, midname); /* Use whole name otherwise*/ (void) fancy_str (last_name_first); /* Get caps in where needed */ namelen = (int) strlen (last_name_first); /* Calc length now */ index_filename[0] = '\0'; /* "null-terminated string" */ if (nodelist_base == NULL) get_nodelist_name (&my_addr); /* fill in nodelist.base */ (void) strcpy (index_filename, net_info); /* take nodelist path */ (void) strcat (index_filename, "SYSOP.NDX"); /* add in the file name */ record = btree (index_filename, (void *) last_name_first, name_compare); if (record == -1) return; (void) get_ver7_info ((unsigned long) record, faddr); } static int LOCALFUNC name_compare (void *key, void *desired, int len) { return (strnicmp ((char *) key, (char *) desired, (unsigned int) min (namelen, len))); } /* * General V7 nodelist engine. Used by both the by-node and by-sysop * lookups. * * Thanks to Phil Becker for showing me how nice it looks in assembler. * It helped me see how nice it could be in C. * * (I know, Phil, it's still nicer in assembler!) * */ static long LOCALFUNC btree (char *filename, void *desired, int (LOCALFUNC * compare) (void *key, void *desired, int len)) { int j, k, l; struct _IndxRef far *ip = NULL; struct _LeafRef far *lp = NULL; char aline[160]; char far *tp; char *np; long record, foundrec = -1L; int count; HFILE stream; if ((stream = (HFILE) share_open (filename, O_RDONLY | O_BINARY, DENY_WRITE)) == (HFILE) - 1) return (-1L); /* no file, no work to do */ if (node_index == NULL) node_index = _fmalloc (sizeof (struct _ndx)); if (nodeidx == NULL) nodeidx = _fmalloc (sizeof (struct _ndx)); if (noderef == NULL) noderef = _fmalloc (sizeof (struct _ndx)); if (node_index == NULL) { status_line (msgtxt[M_NODELIST_MEM]); (void) close (stream); return (-1L); } /* Get CtlRec */ if (get7node (stream, 0L, noderef) != noderef) { close (stream); return (-1L); } /* The guts of the matter -- walk from CtlRec to Leaf */ record = noderef->ndx.CtlBlk.CtlRoot; /* * Read the first Index node. */ if (get7node (stream, (unsigned long) (record * noderef->ndx.CtlBlk.CtlBlkSize), nodeidx) != nodeidx) { close (stream); return (-1L); } /* * Follow the node tree until we either match a key right in the index * node, or locate the leaf node which must contain the entry. */ while (nodeidx->ndx.INodeBlk.IndxFirst != -1) { if ((count = nodeidx->ndx.INodeBlk.IndxCnt) == 0) { j = 0; } else for (j = 0; j < count; j++) /* check 20 or less */ { ip = &(nodeidx->ndx.INodeBlk.IndxRef[j]); tp = (char far *) nodeidx + ip->IndxOfs; k = l = ip->IndxLen; for (np = aline; k > 0; k--) *np++ = *tp++; k = (*compare) ((void *) aline, desired, l); if (k > 0) break; if (k == 0) { /* Key matches in the index node. Since we're just doing lookup, we * can assume its pointer is valid. If we were doing updates, that * assumption would not work, because leaf nodes update first. So in * an update environment, the entire code segment relating to k == 0 * should not execute, and we should walk the tree all the way down. */ close (stream); return (nodeidx->ndx.INodeBlk.IndxRef[j].IndxData); } } if (j == 0) record = nodeidx->ndx.INodeBlk.IndxFirst; else record = (nodeidx->ndx.INodeBlk.IndxRef[--j]).IndxPtr; if (get7node (stream, (unsigned long) (record * noderef->ndx.CtlBlk.CtlBlkSize), nodeidx) != nodeidx) { close (stream); return (-1L); } } /* * We can only get here if we've found the leafnode which must * contain our entry. * * Find our guy here or die trying. */ if ((count = nodeidx->ndx.LNodeBlk.IndxCnt) != 0) { /* Search for a higher key */ for (j = 0; j < count; j++) /* check 30 or less */ { lp = &(nodeidx->ndx.LNodeBlk.LeafRef[j]); tp = (char far *) nodeidx + lp->KeyOfs; k = l = lp->KeyLen; for (np = aline; k > 0; k--) *np++ = *tp++; k = (*compare) ((void *) aline, desired, l); if (k > 0) break; if (k == 0) { foundrec = (nodeidx->ndx.LNodeBlk.LeafRef[j]).KeyVal; break; } } } (void) close (stream); return (foundrec); } static int LOCALFUNC get_ver7_info (unsigned long pos, ADDRP faddr) { struct _vers7 vers7; char my_phone[40]; char my_pwd[9]; char aline[160]; char aline2[160]; char *fst; char temp[80]; /* we build filenames here*/ FILE *stream; (void) strcpy (temp, net_info); /* take nodelist path */ (void) strcat (temp, nodelist_base); /* add in the filename*/ (void) strcat (temp, ".DAT"); /* then the extension */ if ((stream = share_fopen (temp, read_binary, DENY_WRITE)) == NULL) { status_line (msgtxt[M_UNABLE_TO_OPEN], temp); return (0); } if (fseek (stream, (long int) pos, SEEK_SET)) /* point at record */ { status_line (msgtxt[M_NODELIST_SEEK_ERR], temp); (void) fclose (stream); return (0); } if (!fread ((char *) &vers7, sizeof (struct _vers7), 1, stream)) { status_line (msgtxt[M_NODELIST_REC_ERR], temp); (void) fclose (stream); return (0); } (void) memset (my_phone, '\0', 40); (void) fread (my_phone, vers7.Phone_len, 1, stream); (void) memset (my_pwd, '\0', 9); (void) fread (my_pwd, vers7.Password_len, 1, stream); (void) memset (aline, '\0', 160); (void) memset (aline2, '\0', 160); if (!fread (aline2, vers7.pack_len, 1, stream)) { status_line (msgtxt[M_NODELIST_REC_ERR], temp); (void) fclose (stream); return (0); } (void) fclose (stream); unpk (aline2, aline, vers7.pack_len); (void) memset (&newnodedes, 0, sizeof (struct _newnode)); newnodedes.NetNumber = vers7.Net; newnodedes.NodeNumber = vers7.Node; newnodedes.Cost = newnodedes.RealCost = vers7.CallCost; (void) memcpy (newnodedes.SystemName, aline, min (33, vers7.Bname_len)); newnodedes.SystemName[min (33, vers7.Bname_len)] = '\0'; (void) fancy_str (newnodedes.SystemName); fst = &aline[0] + vers7.Bname_len + vers7.Sname_len; (void) memcpy (newnodedes.PhoneNumber, my_phone, min (39, vers7.Phone_len)); newnodedes.PhoneNumber[min (39, vers7.Phone_len)] = '\0'; (void) memcpy (newnodedes.MiscInfo, fst, min (29, vers7.Cname_len)); newnodedes.MiscInfo[min (29, vers7.Cname_len)] = '\0'; (void) fancy_str (newnodedes.MiscInfo); (void) memcpy (newnodedes.Password, my_pwd, min (8, vers7.Password_len)); newnodedes.HubNode = vers7.HubNode; newnodedes.BaudRate = vers7.BaudRate; newnodedes.ModemType = vers7.ModemType; newnodedes.NodeFlags = vers7.NodeFlags; found_zone = faddr->Zone = vers7.Zone; found_net = faddr->Net = vers7.Net; faddr->Node = vers7.Node; if (vers7.NodeFlags & B_point) faddr->Point = vers7.HubNode; else faddr->Point = 0; faddr->Domain = NULL; return (1); } static struct _ndx far *LOCALFUNC get7node (HFILE stream, unsigned long pos, struct _ndx far * ndx) { unsigned long got; (void) lseek (stream, (long) pos, SEEK_SET); /* Note, we do not use "got". Some platforms want it to be a long and some want it to be a int. We don't care, so we make it a long (see above) so there's enough room, then use a void * so the compiler won't complain about an argument we don't even want */ if (_dos_read (stream, ndx, (unsigned int) sizeof (struct _ndx), (void *)&got) != 0) { status_line (msgtxt[M_NODELIST_READ_ERR]); (void) close (stream); return (NULL); } return (ndx); } /* ==================================================================== * unpack a dense version of a symbol (base 40 polynomial) * ==================================================================== */ static void LOCALFUNC unpk (char *instr, char *outp, int count) { struct chars { unsigned char c1; unsigned char c2; }; union { unsigned short w1; struct chars d; } u; register short i, j; /* MB int */ char obuf[4]; outp[0] = '\0'; while (count) { u.d.c1 = *instr++; u.d.c2 = *instr++; count -= 2; for (j = 2; j >= 0; j--) { i = u.w1 % 40; u.w1 /= 40; obuf[j] = unwrk[i]; } obuf[3] = '\0'; (void) strcat (outp, obuf); } }