#include <stdlib.h>
#include <stdio.h>
#include <printerdb.h>
#define strdup(x) strcpy(malloc(strlen(x) + 1), x)
extern size_t strlen(const char *);
extern char *index(const char *, int);
extern char *strcpy(char *, const char *);
extern int strcmp(const char *, const char*);
extern void *bcopy(void *, void *, unsigned);
static FILE *pf;
static char *getline(FILE *);
static int emptyfield(char *);
static void
_prdb_free_ent(
prdb_ent *ent
)
{
int i;
for (i = 0; ent->pe_name[i]; i++) {
free(ent->pe_name[i]);
}
free(ent->pe_name);
ent->pe_name = NULL;
for (i = 0; i < ent->pe_nprops; i++) {
free(ent->pe_prop[i].pp_key);
free(ent->pe_prop[i].pp_value);
}
free(ent->pe_prop);
ent->pe_prop = NULL;
}
void
_old_prdb_end(
void
)
{
if (pf != NULL) {
fclose(pf);
pf = NULL;
}
}
void
_old_prdb_set(
void
)
{
if (pf == NULL) {
pf = fopen("/etc/printcap", "r");
}
}
static void
pename_insert(
char ***target,
char *name,
int which
)
{
if (which == 0) {
*target = malloc(sizeof(char *) * 2);
} else {
*target = realloc(*target, sizeof(char *) * (which + 2));
}
(*target)[which] = strdup(name);
(*target)[which + 1] = NULL;
}
static void
peprop_insert(
prdb_property **target,
prdb_property prop,
int which
)
{
if (which == 0) {
*target = malloc(sizeof(prop));
} else {
*target = realloc(*target, (which + 1) * sizeof(prop));
}
(*target)[which] = prop;
}
prdb_ent *
_old_prdb_get(
void
)
{
char *line;
char *p;
char *end;
char *hash;
char *equal;
char *where;
static prdb_ent ent;
prdb_property prop;
int which;
_old_prdb_set();
if (pf == NULL) {
return (NULL);
}
do {
line = getline(pf);
if (line == NULL) {
return (NULL);
}
} while (*line == 0);
where = line;
end = index(where, ':');
if (end != NULL) {
*end++ = 0;
}
which = 0;
if (ent.pe_name != NULL) {
_prdb_free_ent(&ent);
}
for (;;) {
p = index(where, '|');
if (p != NULL && (end == NULL || p < end)) {
*p++ = 0;
pename_insert(&ent.pe_name, where, which++);
where = p;
} else {
pename_insert(&ent.pe_name, where, which);
break;
}
}
where = end;
which = 0;
for (;;) {
end = index(where, ':');
if (end != NULL) {
*end++ = 0;
}
hash = index(where, '#');
equal = index(where, '=');
if (hash != NULL && (end == NULL || hash < end)) {
*hash = 0;
prop.pp_key = strdup(where);
*hash = '#';
prop.pp_value = strdup(hash);
peprop_insert(&ent.pe_prop, prop, which++);
} else if (equal != NULL && (end == NULL ||
equal < end)) {
*equal++ = 0;
prop.pp_key = strdup(where);
prop.pp_value = strdup(equal);
peprop_insert(&ent.pe_prop, prop, which++);
} else if (!emptyfield(where)) {
prop.pp_key = strdup(where);
prop.pp_value = strdup("");
peprop_insert(&ent.pe_prop, prop, which++);
}
where = end;
if (end == NULL) {
break;
}
}
free(line);
ent.pe_nprops = which;
return (&ent);
}
static int
prmatch(
prdb_ent *ent,
char *name
)
{
int i;
for (i = 0; ent->pe_name[i] != NULL; i++) {
if (strcmp(ent->pe_name[i], name) == 0) {
return (1);
}
}
return (0);
}
prdb_ent *
_old_prdb_getbyname(
char *prname
)
{
prdb_ent *ent;
_old_prdb_set();
if (pf == NULL) {
return (NULL);
}
while ((ent = _old_prdb_get())) {
if (prmatch(ent, prname)) {
break;
}
}
_old_prdb_end();
return (ent);
}
static char *
getline(
FILE *f
)
{
char line[BUFSIZ];
char *res = NULL;
int more = 1;
int len;
int inclen;
len = 0;
while (more && fgets(line, sizeof(line), f)) {
inclen = strlen(line);
if (line[inclen - 1] == '\n') {
line[inclen - 1] = 0;
inclen--;
}
if (*line == '#') {
continue;
}
if (res == NULL) {
res = malloc(inclen + 1);
} else {
res = realloc(res, len + inclen + 1);
}
if (line[inclen - 1] == '\\') {
line[inclen - 1] = 0;
inclen--;
} else {
more = 0;
}
bcopy(line, res + len, inclen);
len += inclen;
res[len] = 0;
}
return (res);
}
static int
emptyfield(
char *line
)
{
while (*line) {
if (*line != ' ' && *line != '\t') {
return (0);
}
line++;
}
return (1);
}