freebsd-dev/lib/libmytinfo/findterm.c
Andrey A. Chernov aaf9cb20c9 Fix longstanding bug with buffer pointer goes beyoud buffer start
Cause initscr (ncurses) fail in some cases
1997-08-13 01:21:36 +00:00

287 lines
4.6 KiB
C

/* findterm.c
*
* By Ross Ridge
* Public Domain
* 92/02/01 07:29:56
*
*/
#include "defs.h"
#include <ctype.h>
#include <fcntl.h>
#ifdef USE_STDDEF
#include <sys/types.h>
#endif
#include <sys/stat.h>
#ifdef __FreeBSD__
#include <unistd.h>
#endif
#ifdef USE_SCCS_IDS
static const char SCCSid[] = "@(#) mytinfo findterm.c 3.2 92/02/01 public domain, By Ross Ridge";
#endif
static int linecnt;
static int
getln(f, buf, len)
FILE *f;
register char *buf;
int len; {
register int c, i = 0;
while((c = getc(f)) == '#') {
linecnt++;
while((c = getc(f)) != '\n')
if (c == EOF)
return -1;
}
while(c != '\n') {
if (c == EOF)
return -1;
if (i < len) {
i++;
*buf++ = c;
}
c = getc(f);
}
while(i > 0 && isspace(*(buf-1))) {
buf--;
i--;
}
*buf = '\0';
return i;
}
static int
_findterm2(name, file, buf)
char *name, *buf;
char *file; {
char line[MAX_LINE];
FILE *f;
register char *sp, *dp;
int c;
int l;
int cont;
int fd;
struct stat st;
linecnt = 0;
#ifdef DEBUG
printf("open: %s\n", file);
#endif
fd = open(file, O_RDONLY);
if (fd == -1)
return -1;
if (fstat(fd, &st) == -1) {
close(fd);
return -1;
}
if ((st.st_mode & 0170000) == 0040000) {
sprintf(buf, "%s/%c/%s", file, name[0], name);
close(fd);
fd = open(buf, O_RDONLY);
if (fd == -1)
return -1;
if (read(fd, buf, MAX_BUF) < 12
|| buf[0] != 032 || buf[1] != 1) {
close(fd);
return -1;
}
close(fd);
return 3;
}
f = fdopen(fd, "r");
if (f == NULL) {
close(fd);
return -1;
}
while ((l = getln(f, buf, MAX_LINE)) != -1) {
linecnt++;
if (!isspace(buf[0]) && l != 0) {
sp = buf + l - 1;
cont = 0;
switch(*sp) {
case '\\':
cont = 1;
*sp = '\0';
/* FALLTHROUGH */
case ':':
sp = buf;
dp = line;
while (*sp != ':') {
if (*sp == '\0' && cont &&
(l = getln(f, buf, MAX_LINE))
!= -1) {
linecnt++;
sp = buf;
if (l > 0 && buf[l-1] == '\\')
cont = 1;
else
cont = 0;
continue;
}
if (*sp == '\0') {
#ifdef DEBUG
printf("bad line (%d)\n",
linecnt);
fclose(f);
return -2;
#else
goto err;
#endif
}
*dp++ = *sp++;
}
*dp = '\0';
if (!_tmatch(line, name))
break;
if (!cont) {
fclose(f);
return 1;
}
l = strlen(buf);
dp = buf + l;
while((c = getc(f)) != EOF && l < MAX_BUF) {
if (c == '\n')
break;
if (c == '\\') {
c = getc(f);
if (c == EOF)
break;
if (c == '\n') {
c = getc(f);
if (c == EOF)
break;
if (c == '#') {
while((c = getc(f)) != EOF && c != '\n');
if (c == EOF)
break;
continue;
}
*dp++ = c;
continue;
}
*dp++ = '\\';
*dp++ = c;
continue;
}
*dp++ = c;
}
*dp = '\0';
fclose(f);
return 1;
case ',':
sp = buf;
dp = line;
while(*sp != ',')
*dp++ = *sp++;
*dp = '\0';
if (!_tmatch(line, name))
break;
dp = buf + l;
while ((c = getc(f)) != EOF && l < MAX_BUF) {
if (c == '\n') {
c = getc(f);
if (isspace(c))
continue;
if (c == '\n') {
ungetc(c, f);
continue;
}
if (c == '#') {
while((c = getc(f)) != EOF)
if (c == '\n')
break;
if (c == EOF)
break;
ungetc(c, f);
continue;
}
break;
}
*dp++ = c;
l++;
}
*dp = '\0';
fclose(f);
return 2;
default:
err:
#ifdef DEBUG
printf("strange line (%d)\n", linecnt);
#endif
break;
}
}
}
fclose(f);
return 0;
}
int
_findterm(name, path, buf)
char *name;
struct term_path *path;
char *buf; {
register char *s, *d;
int r = 0;
while(path->file != NULL) {
switch(path->type) {
case 0:
r = _findterm2(name, path->file, buf);
break;
case 1:
if (path->file[0] == '/') {
r = _findterm2(name, path->file, buf);
} else {
s = path->file;
d = buf;
while(*s != '\0' && *s != ':')
*d++ = *s++;
*d = '\0';
if (_tmatch(buf, name)) {
while(*s != '\0')
*d++ = *s++;
return 1;
}
r = 0;
}
break;
case 2:
if (path->file[0] == '/') {
r = _findterm2(name, path->file, buf);
} else {
s = path->file;
d = buf;
while(*s != '\0' && *s != ',')
*d++ = *s++;
*d = '\0';
if (_tmatch(buf, name)) {
while(*s != '\0')
*d++ = *s++;
return 2;
}
r = 0;
}
break;
default:
r = 0;
break;
}
if (r == 1 || r == 2 || r == 3) {
#ifdef DEBUG
printf("found in %s\n", path->file);
#endif
break;
}
path++;
}
return r;
}