#include <stdio.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <ctype.h>
#include <sys/types.h>
#include <libintl.h>
#include "pkglib.h"
#include "pkgstrct.h"
#include "pkglocale.h"
#include "pkglibmsgs.h"
static int getend(char **cp);
static int getstr(char **cp, int n, char *str, int separator[]);
int getnumvfp(char **cp, int base, long *d, long bad);
int getlnumvfp(char **cp, int base, fsblkcnt_t *d, long bad);
static char lpath[PATH_MAX];
static char mylocal[PATH_MAX];
static int decisionTableInit = 0;
static int ISWORDSEP[UCHAR_MAX+1];
static int ISPKGNAMESEP[UCHAR_MAX+1];
#define COPYPATH(DEST, SRC, LEN) \
{ \
\
if ((LEN) > sizeof ((DEST))) { \
(LEN) = sizeof ((DEST))-1; \
} \
\
(void) memcpy((DEST), (SRC), (LEN)); \
(DEST)[(LEN)] = '\0'; \
}
int
srchcfile(struct cfent *ept, char *path, PKGserver server)
{
char *cpath_start = NULL;
char classname[CLSSIZ+1];
char pkgname[PKGSIZ+1];
int anypath = 0;
int c;
int cpath_len = 0;
struct pinfo *lastpinfo;
struct pinfo *pinfo;
char *p;
char *curbuf;
int linelen;
setErrstr(NULL);
lpath[0] = '\0';
lpath[sizeof (lpath)-1] = '\0';
(void) strlcpy(ept->ainfo.group, BADGROUP, sizeof (ept->ainfo.group));
(void) strlcpy(ept->ainfo.owner, BADOWNER, sizeof (ept->ainfo.owner));
(void) strlcpy(ept->pkg_class, BADCLASS, sizeof (ept->pkg_class));
ept->ainfo.local = (char *)NULL;
ept->ainfo.mode = BADMODE;
ept->cinfo.cksum = BADCONT;
ept->cinfo.modtime = BADCONT;
ept->cinfo.size = (fsblkcnt_t)BADCONT;
ept->ftype = BADFTYPE;
ept->npkgs = 0;
ept->path = (char *)NULL;
ept->pinfo = (struct pinfo *)NULL;
ept->pkg_class_idx = -1;
ept->volno = 0;
if (decisionTableInit == 0) {
bzero(ISWORDSEP, sizeof (ISWORDSEP));
ISWORDSEP[' '] = 1;
ISWORDSEP['\t'] = 1;
ISWORDSEP['\n'] = 1;
ISWORDSEP['\0'] = 1;
bzero(ISPKGNAMESEP, sizeof (ISPKGNAMESEP));
ISPKGNAMESEP[' '] = 1;
ISPKGNAMESEP['\t'] = 1;
ISPKGNAMESEP['\n'] = 1;
ISPKGNAMESEP[':'] = 1;
ISPKGNAMESEP['\\'] = 1;
ISPKGNAMESEP['\0'] = 1;
decisionTableInit = 1;
}
if ((path != NULL) && (*path == '\0')) {
path = NULL;
}
if ((path != NULL) && (path[0] != '/')) {
if (strcmp(path, "*") != 0) {
setErrstr(pkg_gt(ERR_ILLEGAL_SEARCH_PATH));
return (-1);
}
anypath = 1;
}
if (anypath == 0 && path == NULL)
return (0);
if (anypath == 0)
curbuf = pkggetentry_named(server, path, &linelen, &cpath_len);
else
curbuf = pkggetentry(server, &linelen, &cpath_len);
if (curbuf == NULL)
return (0);
cpath_start = curbuf;
p = cpath_start + cpath_len;
ept->path = lpath;
COPYPATH(lpath, cpath_start, cpath_len);
c = *p++;
if (c == '=') {
if (getstr(&p, PATH_MAX, mylocal, ISWORDSEP)) {
setErrstr(ERR_CANNOT_READ_LL_PATH);
return (-1);
}
ept->ainfo.local = mylocal;
}
while (isspace((c = *p++)))
;
switch (c) {
case '?': case 'f': case 'v': case 'e': case 'l':
case 's': case 'p': case 'c': case 'b': case 'd':
case 'x':
ept->ftype = (char)c;
if (getstr(&p, CLSSIZ, ept->pkg_class, ISWORDSEP)) {
setErrstr(ERR_CANNOT_READ_CLASS_TOKEN);
return (-1);
}
break;
case '\0':
setErrstr(ERR_INCOMPLETE_ENTRY);
return (-1);
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
setErrstr(ERR_VOLUMENO_UNEXPECTED);
return (-1);
case 'i':
setErrstr(ERR_FTYPE_I_UNEXPECTED);
return (-1);
default:
setErrstr(ERR_UNKNOWN_FTYPE);
return (-1);
}
if (((ept->ftype == 's') || (ept->ftype == 'l')) &&
(ept->ainfo.local == NULL)) {
setErrstr(ERR_NO_LINK_SOURCE_SPECIFIED);
return (-1);
}
if (((ept->ftype == 'c') || (ept->ftype == 'b'))) {
ept->ainfo.major = BADMAJOR;
ept->ainfo.minor = BADMINOR;
if (getnumvfp(&p, 10, (long *)&ept->ainfo.major, BADMAJOR) ||
getnumvfp(&p, 10, (long *)&ept->ainfo.minor, BADMINOR)) {
setErrstr(pkg_gt(ERR_CANNOT_READ_MM_NUMS));
return (-1);
}
}
if ((ept->ftype == 'd') || (ept->ftype == 'x') || (ept->ftype == 'c') ||
(ept->ftype == 'b') || (ept->ftype == 'p') ||
(ept->ftype == 'f') || (ept->ftype == 'v') ||
(ept->ftype == 'e')) {
if (getnumvfp(&p, 8, (long *)&ept->ainfo.mode, BADMODE) ||
getstr(&p, sizeof (ept->ainfo.owner), ept->ainfo.owner,
ISWORDSEP) ||
getstr(&p, sizeof (ept->ainfo.group), ept->ainfo.group,
ISWORDSEP)) {
setErrstr(ERR_CANNOT_READ_MOG);
return (-1);
}
}
if ((ept->ftype == 'i') || (ept->ftype == 'f') ||
(ept->ftype == 'v') || (ept->ftype == 'e')) {
if (getlnumvfp(&p, 10, (fsblkcnt_t *)&ept->cinfo.size,
BADCONT) ||
getnumvfp(&p, 10, (long *)&ept->cinfo.cksum, BADCONT) ||
getnumvfp(&p, 10, (long *)&ept->cinfo.modtime, BADCONT)) {
setErrstr(ERR_CANNOT_READ_CONTENT_INFO);
return (-1);
}
}
if (ept->ftype == 'i') {
return (1);
}
lastpinfo = (struct pinfo *)NULL;
while ((c = getstr(&p, sizeof (pkgname), pkgname, ISPKGNAMESEP)) <= 0) {
if (c < 0) {
setErrstr(ERR_PACKAGE_NAME_TOO_LONG);
return (-1);
}
pinfo = (struct pinfo *)calloc(1, sizeof (struct pinfo));
if (!pinfo) {
setErrstr(ERR_NO_MEMORY);
return (-1);
}
if (!lastpinfo) {
ept->pinfo = pinfo;
} else {
lastpinfo->next = pinfo;
}
lastpinfo = pinfo;
if ((pkgname[0] == '-') || (pkgname[0] == '+') ||
(pkgname[0] == '*') || (pkgname[0] == '~') ||
(pkgname[0] == '!') || (pkgname[0] == '%')) {
pinfo->status = pkgname[0];
(void) strlcpy(pinfo->pkg, pkgname+1,
sizeof (pinfo->pkg));
} else {
(void) strlcpy(pinfo->pkg, pkgname,
sizeof (pinfo->pkg));
}
c = *p++;
if (c == '\\') {
pinfo->editflag++;
c = *p++;
}
if (c == ':') {
(void) getstr(&p, sizeof (classname), classname,
ISWORDSEP);
(void) strlcpy(pinfo->aclass, classname,
sizeof (pinfo->aclass));
c = *p++;
}
ept->npkgs++;
if ((c == '\n') || (c == '\0')) {
break;
}
if (!isspace(c)) {
setErrstr(ERR_BAD_ENTRY_END);
return (-1);
}
}
if ((c != '\n') && (c != '\0')) {
if (getend(&p) && ept->pinfo) {
setErrstr(ERR_EXTRA_TOKENS);
return (-1);
}
}
return (1);
}
static int
getstr(char **cp, int n, char *str, int separator[])
{
int c;
char *p = *cp;
char *p1;
size_t len;
if (*p == '\0') {
return (1);
}
while (((c = *p) != '\0') && (isspace(*p++)))
;
if ((c == '\0') || (c == '\n')) {
p--;
*cp = p;
return (1);
}
p--;
p1 = p;
while (separator[(int)(*(unsigned char *)p1)] == 0) {
p1++;
}
len = (ptrdiff_t)p1 - (ptrdiff_t)p;
if (len < n) {
(void) memcpy(str, p, len);
str[len] = '\0';
p += len;
*cp = p;
return (0);
}
(void) memcpy(str, p, n-1);
str[n-1] = '\0';
p += n;
*cp = p;
return (-1);
}
static int
getend(char **cp)
{
int n;
char *p = *cp;
n = 0;
if (*p == '\0') {
return (0);
}
while ((*p != '\0') && (*p != '\n')) {
if (n == 0) {
if (!isspace(*p)) {
n++;
}
}
p++;
}
*cp = ++p;
return (n);
}