problems compiling plan under libc6
I really don't program in C, so I have no idea if this is something easy
to figure out or needs a great amount of reworking. Anyway, given that
debian will require all packages to be compiled with libc6 in the near
future, I thought I would see if this is fixable. The error message from
gcc is:
gcc -s -D_POSIX_SOURCE -DNOLOCK -DLINUX -DRABBITS -c file_r.c
file_r.c: In function `read_mainlist':
file_r.c:132: `S_IFDIR' undeclared (first use this function)
file_r.c:132: (Each undeclared identifier is reported only once
file_r.c:132: for each function it appears in.)
make[1]: *** [file_r.o] Error 1
make[1]: Leaving directory `/home/telmerco/debian/plan-1.6.1/src'
make: *** [linux] Error 2
The lines around line 132 in file_r.c are
if (!stat(user[u].path, &sbuf) && (sbuf.st_mode & S_IFDIR))
sprintf(path, "%s/%s", user[u].path, DB_FILE);
and the entire file_r.c is attached. The error message seems to be saying
that the code is trying to do a bitwise AND with something that is
undefined. However, I have no idea why this would work with libc5 and not
libc6:)
I really don't know what other information to add except for some lib and
gcc versions (below). Any help is gratefully appreciated. Cheers, Colin.
ii libc6 2.0.4-1 The GNU C library version 2
ii libc6-dev 2.0.4-1 The GNU C library version 2
ii libc6-doc 2.0.4-1 The GNU C library version 2
ii gcc 2.7.2.2-5 The GNU C compiler
ii bash 2.0-3 The GNU Bourne Again SHell
--
Colin R. Telmer, Institute of Intergovernmental Relations
School of Policy Studies, Queen's University
Kingston, Ontario, Canada, K7L-3N6
(613)545-6000x4219 telmerco@qed.econ.queensu.ca
PGP Public Key at <URL:http://terrapin.econ.queensu.ca>
/*
* read the master list from the ~/.dayplan file. This file is also
* linked into the daemon program (file_w.c is not).
*
* read_mainlist() Read all files into mainlist.
*/
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#ifdef MIPS
#include <sys/types.h>
#include <sys/fcntl.h>
#else
#include <stdlib.h>
#endif
#ifdef _APOLLO_SOURCE
#include <sys/types.h>
#include <sys/fcntl.h>
#endif
#ifdef ULTRIX
#include <sys/types.h>
#endif
#include <sys/stat.h>
#include <pwd.h>
#include <time.h>
#include <errno.h>
#include <Xm/Xm.h>
#include "config.h"
#include "proto.h"
#include "version.h"
#ifdef PLANGROK
#include "grok.h"
#include "form.h"
#endif
#define NDAYS 28 /* must agree with cal.h */
#ifdef MIPS
extern char *getenv();
extern char *malloc();
#endif
static int readfile();
static void make_default_user();
static void convert_dbase();
extern char *progname; /* argv[0] */
extern struct plist *mainlist; /* all schedule entries */
extern struct config config; /* global configuration data */
struct user *user; /* user list for week view */
static int maxusers; /* max # of users in u list */
int nusers; /* # of users in user list */
char Print_Spooler[100]; /* print spooling command */
/*
* read the main list. First, read the main ~/.dayplan file, which also
* provides the configuration data, including the user list. Next, read
* the private dayplan file and all user dayplan files. Return a text
* buffer with error messages; if msg is 0 print themn to stderr. This
* file can't use create_error_popup because it is used by the daemon too.
*
* Depending on the mode, server connections are established after the
* config part of the .dayplan file (including the user list and server
* mode) was read in. The actual appointment data is then read from the
* files or the servers.
*/
BOOL read_mainlist()
{
struct stat sbuf; /* check for directories */
char msgbuf[4096]; /* default message buffer */
char *msg, *p; /* where messages are stored */
char path[1024]; /* user file name to read */
int u; /* user counter */
int error;
msg = msgbuf;
*msg = 0;
destroy_list(&mainlist); /* delete appt list */
create_list(&mainlist);
if (user) { /* delete user list */
for (u=0; u < nusers; u++) {
if (user[u].name)
free((char *)user[u].name);
if (user[u].path)
free((char *)user[u].path);
if (user[u].server)
free((char *)user[u].server);
}
free((char *)user);
user = 0;
}
nusers = maxusers = 0;
/* main data */
if (error = readfile(&mainlist, DB_PUB_PATH, 0, TRUE))
sprintf(msg+strlen(msg),
"Failed to read master file %s, error %d\n",
DB_PUB_PATH, error);
else if (!access(DB_PUB_PATH, F_OK) && access(DB_PUB_PATH, W_OK))
sprintf(msg+strlen(msg),
"Warning: own config and data file %s is not writable\n",
DB_PUB_PATH);
/* private data */
if (error = readfile(&mainlist, DB_PRIV_PATH, 0, FALSE))
sprintf(msg+strlen(msg),
"Failed to read private file %s, error %d\n",
DB_PRIV_PATH, error);
else if (!access(DB_PRIV_PATH, F_OK) && access(DB_PRIV_PATH, W_OK))
sprintf(msg+strlen(msg),
"Warning: own private data file %s is not writable\n",
DB_PRIV_PATH);
make_default_user(resolve_tilde(DB_PUB_PATH)); /* network connection*/
if (p = attach_to_network())
strcat(msg, p);
read_from_server(&mainlist, 0, 0);
/* user data */
for (u=1; u < nusers; u++) { /* skip 0, 0 is own */
if (user[u].fromserver) {
read_from_server(&mainlist, u, 0);
continue;
}
if (!user[u].path || !user[u].name) {
sprintf(msg+strlen(msg),
"file of user #%d not read, no name or path\n",
u);
continue;
}
if (!stat(user[u].path, &sbuf) && (sbuf.st_mode & S_IFDIR))
sprintf(path, "%s/%s", user[u].path, DB_FILE);
else
strcpy(path, user[u].path);
user[u].readonly = !access(path, F_OK) && !!access(path, W_OK);
user[u].modified = FALSE;
user[u].time = get_time();
if (config.owner_only && !stat(path, &sbuf)
&& sbuf.st_uid != getuid())
user[u].readonly = TRUE;
if ((error = readfile(&mainlist, path, u, FALSE)) &&
error != ENOENT)
sprintf(msg+strlen(msg),
"Failed to read file %s of user %s, error %d\n",
user[u].path, user[u].name, error);
}
rebuild_repeat_chain(mainlist);
if (*msg)
create_error_popup(0, 0,
"Error while reading files:\n%s", msg);
mainlist->modified = FALSE;
return(!*msg);
}
/*
* read a list from a file. If <list> points to a non-null pointer, the
* list in the file is merged into the list. As with add_entry(), <list>
* is a pointer to a pointer to the list because the list might grow and
* must be re-allocated. If the file is empty, no new list is allocated,
* and <list> continues to point to a null pointer.
*
* If it turns out that appointment data is to be read from servers instead
* of files after a 'n' (networking) line was read, reading is aborted when
* the first appointment definition is found (line beginning with a digit):
* network mode...
* 1: always read from file
* 2: only read own: from .dayplan (conf) or .dayplan.priv (!conf&&!name)
* 3: never read from any file
*
* Always read config information if conf==TRUE, it never comes from a server.
* Returns nonzero if the file could not be read.
*/
static int readfile(list, path, u, conf)
struct plist **list; /* list to add to */
char *path; /* file to read list from */
int u; /* user number, 0=own */
BOOL conf; /* if TRUE, config stuff too */
{
register struct config *c = &config;
FILE *fp; /* open file */
BOOL writable; /* can we lock the file? */
char line[1024]; /* line buffer */
int lineno = 0; /* first line == "grok"? */
path = resolve_tilde(path);
writable = !access(path, W_OK);
if (!(fp = fopen(path, writable ? "r+" : "r")))
return(errno);
if (conf) /* defaults for 't' line */
guess_tzone();
if (writable)
lockfile(fp, TRUE);
for (;;) {
if (!fgets(line, 1024, fp))
break;
if (!lineno++ && !strncmp(line, "grok", 4)) {
#ifndef PLANGROK
create_error_popup(0, 0,
"%s is a\ngrok database, not supported", path);
#else
extern FORM *form_create();
struct user *up = &user[u];
if (!u)
create_error_popup(0, 0, "The first file in the file list\n(%s)\nmust not be a grok database!\nTrying to continue, you may lose data.", path);
form_delete(up->form);
dbase_delete(up->dbase);
up->grok = TRUE;
up->readonly = TRUE;
up->form = form_create();
up->dbase = dbase_create();
if (read_form(up->form, path)) {
char *p = up->form->dbase?up->form->dbase:path;
read_dbase(up->dbase, up->form, p);
convert_dbase(list, up, p);
}
#endif
break;
}
if (!conf && strchr("OotelaPpmUu", *line))
continue;
if (*line >= '0' && *line <= '9' && user
&& user[u].fromserver)
break;
parse_file_line(list, path, user ? user[u].name:0, conf, line);
}
if (writable)
lockfile(fp, FALSE);
fclose(fp);
return(0);
}
/*
* parse a line read from a file or from a server. An entry consists of one
* or more lines and calls to this routine; remember the entry currently
* being read and keep adding to it until a new entry starts. If the line
* begins with '@', it's the first appt line from the network with '@fid rid'
* prepended to the usual numerical date/time string.
*/
void parse_file_line(list, path, name, conf, line)
struct plist **list; /* list to add to */
char *path; /* file/server to read from */
char *name; /* user name, 0=not yet known*/
BOOL conf; /* if TRUE, config stuff too */
char *line; /* line to be parsed */
{
register struct config *c = &config;
int fid, rid; /* network file ID and row ID*/
char *instring; /* string at line[2] or [3] */
register char *p, *q; /* line scan pointer */
static struct entry entry; /* temp entry before adding */
static struct entry *ep = 0; /* list entry being read */
int n, m; /* tmp entry # of ep in list */
struct tm tm; /* m/d/y h:m:s to time conv */
int tmp[9]; /* temps for sscanf */
int acol; /* more temps for sscanf */
char sflag, pflag, nflag;
char nmflag, nyflag, nwflag, noflag, ndflag;
char **string; /* string to add to */
int len; /* new length of string */
char buf1[256], buf2[1024], buf3[1024];
if (*line == '@') {
sscanf(line+1, "%d %d", &fid, &rid);
while (*++line != ' ');
while (*++line == ' ');
while (*++line != ' ');
while (*++line == ' ');
delete_entry_by_id(*list, fid, rid);
} else
fid = rid = 0;
instring = line+2;
*buf1 = *buf2 = *buf3 = 0;
switch(*line) {
case '\n':
case '#':
return;
case 'V':
line[strlen(line)-1] = 0;
sprintf(buf1, "plan %s", VERSION);
if (strcmp(line, buf1))
fprintf(stderr,
"%s: WARNING: file %s is version %s, program version is %s\n",
progname, path, line, buf1);
break;
case 'o':
c->week_ndays = 7;
c->sunday_first = line[2] != '-';
c->ampm = line[3] != '-';
c->mmddyy = line[4] != '-';
c->autodel = line[5] != '-';
c->julian = line[6] != '-';
c->gpsweek = line[7] == 'g';
c->weeknum = line[7] != '-';
c->nopast = line[8] != '-';
c->bigwarning = line[9] != '-';
c->weekwarn = line[10] != '-';
c->weekuser = line[11] != '-';
c->week_bignotime = line[12] != '-';
c->fullweek = line[13] != '-';
c->colorcode_m = line[14] != '-';
c->ownonly = line[15] != '-';
sscanf(line+16, "%d %d %d %d %d %d",
(int *)&c->early_time,
(int *)&c->late_time,
(int *)&c->wintimeout,
(int *)&c->week_minhour,
(int *)&c->week_maxhour,
(int *)&c->week_ndays);
if (c->week_minhour >= c->week_maxhour) {
c->week_minhour = 8;
c->week_maxhour = 20;
}
if (c->week_ndays < 1)
c->week_ndays = 7;
if (c->week_ndays > NDAYS)
c->week_ndays = NDAYS;
break;
case 'O':
c->share_mainwin = line[2] != '-';
c->resize_mainwin = line[3] != '-';
break;
case 't':
sscanf(line+2, "%d %d %d %d %d",
(int *)&c->adjust_time,
(int *)&c->raw_tzone,
(int *)&c->dst_flag,
(int *)&c->dst_begin,
(int *)&c->dst_end);
set_tzone();
break;
case 'e':
c->ewarn_window = line[2] != '-';
c->ewarn_mail = line[3] != '-';
c->ewarn_exec = line[4] != '-';
line[strlen(line)-1] = 0;
if (c->ewarn_prog)
free(c->ewarn_prog);
c->ewarn_prog = 0;
if (line[5] && line[6])
c->ewarn_prog = mystrdup(line+6);
break;
case 'l':
c->lwarn_window = line[2] != '-';
c->lwarn_mail = line[3] != '-';
c->lwarn_exec = line[4] != '-';
line[strlen(line)-1] = 0;
if (c->lwarn_prog)
free(c->lwarn_prog);
c->lwarn_prog = 0;
if (line[5] && line[6])
c->lwarn_prog = mystrdup(line+6);
break;
case 'a':
c->alarm_window = line[2] != '-';
c->alarm_mail = line[3] != '-';
c->alarm_exec = line[4] != '-';
line[strlen(line)-1] = 0;
if (c->alarm_prog)
free(c->alarm_prog);
c->alarm_prog = 0;
if (line[5] && line[6])
c->alarm_prog = mystrdup(line+6);
break;
case 'y':
c->yov_single = line[2] != '-';
for (p=line+2; *p && *p != ' '; p++);
sscanf(p, "%d %d %d", &c->yov_nmonths,
&c->yov_display,
&c->yov_user);
break;
case 'P':
c->pr_omit_appts = line[2] != '-';
c->pr_omit_priv = line[3] != '-';
c->pr_omit_others = line[4] != '-';
c->pr_mode = atoi(line+13);
break;
case 'p':
strncpy(Print_Spooler, (const char *)line + 2,
sizeof(Print_Spooler));
Print_Spooler[sizeof(Print_Spooler)-1] = 0;
Print_Spooler[strlen(Print_Spooler)-1] = 0;
break;
case 'm':
line[strlen(line)-1] = 0;
if (line[1] && line[2])
c->mailer = mystrdup(line+2);
break;
case 'U':
make_default_user(path);
break;
case 'u':
if (nusers >= maxusers) {
n = nusers + 10;
user = user ? realloc(user, n * sizeof(struct user))
: malloc(n * sizeof(struct user));
if (!user)
fatal("no memory");
memset(user+maxusers, 0,
(n-maxusers) * sizeof(struct user));
maxusers = n;
}
sscanf(line+2, "%s %s %d %d %d %d %d %d %s %d\n", buf1, buf2,
&user[nusers].suspend_w,
&user[nusers].color,
&user[nusers].suspend_m,
&user[nusers].alarm,
&user[nusers].suspend_o,
&user[nusers].fromserver, buf3,
&user[nusers].suspend_d);
if (!*buf3 && gethostname(buf3, sizeof(buf3)))
strcpy(buf3, "localhost");
m = 0;
do for (n=nusers-1; n >= 0; n--)
if (!strcmp(user[n].name, buf1)) {
strcat(buf1, "x");
break;
}
while (n >= 0 && m++ < nusers);
user[nusers].name = mystrdup(buf1);
user[nusers].path = mystrdup(buf2);
user[nusers].server = mystrdup(buf3);
user[nusers].file_id = -1;
nusers++;
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
make_default_user(path);
clone_entry(&entry, (struct entry *)0);
sflag = pflag = nflag =
nmflag = nyflag = nwflag = noflag = ndflag = 0;
acol = 0;
sscanf(line,
"%d/%d/%d %d:%d:%d %d:%d:%d %d:%d:%d %d:%d:%d %c%c%c%c%c%c%c%c-- %d",
&tm.tm_mon, &tm.tm_mday, &tm.tm_year,
&tm.tm_hour, &tm.tm_min, &tm.tm_sec,
tmp+0, tmp+1, tmp+2,
tmp+3, tmp+4, tmp+5,
tmp+6, tmp+7, tmp+8,
&sflag, &pflag, &nflag,
&nmflag, &nyflag, &nwflag, &noflag, &ndflag, &acol);
tm.tm_mon--;
if (tm.tm_year < 70)
tm.tm_year += 100;
if (tm.tm_year > 1900)
tm.tm_year -= 1900;
if (entry.notime = tm.tm_hour > 23)
tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
entry.time = tm_to_time(&tm);
entry.length = tmp[0]*3600 + tmp[1]*60 + tmp[2];
entry.early_warn = tmp[3]*3600 + tmp[4]*60 + tmp[5];
entry.late_warn = tmp[6]*3600 + tmp[7]*60 + tmp[8];
entry.suspended = sflag == 'S';
entry.private = pflag == 'P';
entry.noalarm = nflag == 'N';
entry.hide_in_m = nmflag == 'M';
entry.hide_in_y = nyflag == 'Y';
entry.hide_in_w = nwflag == 'W';
entry.hide_in_o = noflag == 'O';
entry.hide_in_d = ndflag == 'D';
entry.acolor = acol;
entry.user = name ? mystrdup(name) : 0;
entry.file = fid;
entry.id = rid;
n = add_entry(list, &entry); /* sets <list> */
ep = &(*list)->entry[n];
break;
case 'R':
sscanf(line+2, "%d %d %d %d %d",
(int *)&ep->rep_every,
(int *)&ep->rep_last,
(int *)&ep->rep_weekdays,
(int *)&ep->rep_days,
(int *)&ep->rep_yearly);
if (ep->time && ep->rep_last && ep->time > ep->rep_last)
ep->rep_last = 0;
break;
case 'E':
for (n=0; n < NEXC; n++)
if (!ep->except[n])
break;
if (n < NEXC) {
sscanf(line+2, "%d/%d/%d",
&tm.tm_mon, &tm.tm_mday, &tm.tm_year);
tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
tm.tm_mon--;
if (tm.tm_year < 70)
tm.tm_year += 100;
if (tm.tm_year > 1900)
tm.tm_year -= 1900;
ep->except[n] = tm_to_time(&tm);
} else
fprintf(stderr,
"too many exception dates for appt");
break;
case 'N':
string = &ep->note;
ep->hide_in_w |= line[2] == '-';
if (line[2] == '-' || line[2] == '=') {
ep->hide_in_m = ep->hide_in_y = TRUE;
instring++;
}
goto add;
case 'M':
string = &ep->message;
goto add;
case 'S':
string = &ep->script;
add: len = *string ? strlen(*string) : 0;
len += strlen(instring) + 2;
if (!(p = malloc(len))) {
fprintf(stderr, "%s: no memory", progname);
exit(1);
}
if (*string) {
strcpy(p, *string);
strcat(p, instring);
free(*string);
} else
strcpy(p, instring);
*string = p;
break;
default:
fprintf(stderr, "%s: %s: illegal line:\n%s",
progname, path, line);
}
}
/*
* When a 'U', 'u', or begin-appointment line is found, user[0] (own) must
* exist. If not, this routine makes one, and also ensures that <user> is
* not a null pointer because everybody relies on that.
*/
static void make_default_user(path)
char *path; /* file path for own .dayplan */
{
struct passwd *pw;
char host[1024], *name;
if (user && nusers && user[0].name)
return;
pw = getpwuid(getuid());
name = pw ? pw->pw_name : getenv("LOGNAME");
if (!name)
name = "unknown";
if (!user) {
maxusers = 10;
if (!(user = malloc(maxusers * sizeof(struct user))))
fatal("no memory");
memset(user, 0, maxusers * sizeof(struct user));
}
if (gethostname(host, sizeof(host)))
strcpy(host, "localhost");
user[0].name = mystrdup(name);
user[0].path = mystrdup(path);
user[0].server = mystrdup(host);
user[0].alarm = TRUE;
user[0].file_id = -1;
nusers = 1;
}
/*
* convert a grok database to a list of appointment entries
*/
#ifdef PLANGROK
static void convert_dbase(list, up, db)
struct plist **list; /* list to add to */
register struct user *up; /* user with form/dbase */
char *db; /* db name for error messages*/
{
struct entry *elist; /* temporary list of entries */
register struct entry *ep; /* list entry being read */
ITEM *item; /* current field description */
ROW *row; /* curr database row */
register char *data; /* curr database contents */
int en, ei; /* # of entries; curr entry */
int fn, fi; /* # of fields; curr field */
BOOL tagged=FALSE; /* dbase has plan interface? */
BOOL have_d, have_n; /* dbase has date & note? */
int def_d, def_n; /* default date & note fields*/
int n;
if ((en = up->dbase->nrows) < 1 || (fn = up->form->nitems) < 1)
return;
if (!(elist = (struct entry *)malloc(en * sizeof(struct entry))))
fatal("no memory for appointment list");
for (ep=elist, ei=0; ei < en; ei++, ep++) {
clone_entry(ep, (struct entry *)0);
ep->grok_row = ei;
}
have_d = have_n = FALSE; /* have date & note? */
def_d = def_n = -1;
for (fi=fn-1; fi >= 0; fi--) {
item = up->form->items[fi];
tagged |= item->plan_if != 0;
have_d |= item->plan_if == 't';
have_n |= item->plan_if == 'n';
if (item->type == IT_TIME &&
(item->timefmt == T_DATE || item->timefmt == T_DATETIME))
def_d = fi;
if (item->type == IT_INPUT || item->type == IT_NOTE)
def_n = fi;
}
if (!have_d && def_d < 0) {
create_error_popup(0, 0, "xmbase-grok database %s\ncannot be read because the calendar\ninterface is %s, and there are no\ndate fields to automatically generate one.", db, tagged ? "incomplete" : "missing");
return;
}
if (!have_d)
up->form->items[def_d]->plan_if = 't';
if (!have_n)
up->form->items[def_n]->plan_if = 'n';
for (fi=0; fi < fn; fi++) { /* ok, convert dbase */
item = up->form->items[fi];
for (ep=elist, ei=0; ei < en; ei++, ep++) {
row = up->dbase->row[ei];
if (row->ncolumns <= item->column)
continue;
if (!(data = row->data[item->column]))
continue;
switch(item->plan_if) {
case 't': if (item->timefmt == T_DATE) {
ep->notime = TRUE;
ep->time = atoi(data);
} else if (item->timefmt == T_DATETIME)
ep->time = atoi(data);
break;
case 'l': ep->length = atoi(data); break;
case 'w': ep->early_warn = atoi(data); break;
case 'W': ep->late_warn = atoi(data); break;
case 'r': ep->rep_every = atoi(data)*86400; break;
case 'e': ep->rep_last = atoi(data); break;
case 'c': ep->acolor = atoi(data) & 7; break;
case 'n': ep->note = mystrdup(data); break;
case 'm': ep->message = mystrdup(data); break;
case 's': ep->script = mystrdup(data); break;
case 'S': ep->suspended = !!atoi(data); break;
case 'T': ep->notime = !!atoi(data); break;
case 'A': ep->noalarm = !!atoi(data); break;
}
}
}
for (ep=elist, n=ei=0; ei < en; ei++, ep++) /* sanity checks */
if (ep->time) {
n++;
if (ep->rep_last) {
if (!ep->rep_every)
ep->rep_every = 86400;
if (ep->rep_last < ep->time)
ep->rep_last = ep->time;
}
ep->user = mystrdup(up->name);
add_entry(list, ep);
} else
destroy_entry(ep);
if (!n)
create_error_popup(0, 0, "%d of %d appointments from grok database\n%s discarded\nbecause of invalid date/time.", en-n, en, db);
free((void *)elist);
}
#endif
Reply to: