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 [EMAIL PROTECTED] 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