static void OpenPurgeFile(char const *fname, char const *mode) { DynamicBuffer fname_buf; if (PurgeFP != NULL && PurgeFP != stdout) { fclose(PurgeFP); } PurgeFP = NULL; /* Do not open a purge file if we're below purge include depth */ if (IStackPtr-2 >= PurgeIncludeDepth) { PurgeFP = NULL; return; } DBufInit(&fname_buf); if (DBufPuts(&fname_buf, fname) != OK) return; if (DBufPuts(&fname_buf, ".purged") != OK) return; PurgeFP = fopen(DBufValue(&fname_buf), mode); if (!PurgeFP) { fprintf(ErrFp, "Cannot open `%s' for writing: %s\n", DBufValue(&fname_buf), strerror(errno)); } DBufFree(&fname_buf); }
/********************************************************************** %FUNCTION: DBufGets %ARGUMENTS: dbuf -- pointer to a dynamic buffer fp -- file to read from %RETURNS: OK or E_NO_MEM %DESCRIPTION: Reads an entire line from a file and appends to dbuf. Does not include trailing newline. **********************************************************************/ int DBufGets(DynamicBuffer *dbuf, FILE *fp) { char tmp[256]; /* Safe to hard-code */ int busy = 1; int l; DBufFree(dbuf); /* Try reading the first few bytes right into the buffer -- we can usually save some unnecessary copying */ *(dbuf->buffer) = 0; fgets(dbuf->buffer, dbuf->allocatedLen, fp); if (!*(dbuf->buffer)) return OK; dbuf->len = strlen(dbuf->buffer); l = dbuf->len - 1; if (dbuf->buffer[l] == '\n') { dbuf->buffer[l] = 0; dbuf->len = l; return OK; } while(busy) { *tmp = 0; fgets(tmp, 256, fp); if (!*tmp) return OK; l = strlen(tmp) - 1; if (tmp[l] == '\n') { tmp[l] = 0; busy = 0; } if (DBufPuts(dbuf, tmp) != OK) return E_NO_MEM; } return OK; }
static int SetupGlobChain(char const *dirname, IncludeStruct *i) { DynamicBuffer pattern; char *dir; size_t l; int r; glob_t glob_buf; DirectoryFilenameChain *dc = CachedDirectoryChains; i->chain = NULL; if (!*dirname) return E_CANT_OPEN; dir = StrDup(dirname); if (!dir) return E_NO_MEM; /* Strip trailing slashes off directory */ l = strlen(dir); while(l) { if (*(dir+l-1) == '/') { l--; *(dir+l) = 0; } else { break; } } /* Repair root directory :-) */ if (!l) { *dir = '/'; } /* Check the cache */ while(dc) { if (!strcmp(dc->dirname, dir)) { if (DebugFlag & DB_TRACE_FILES) { fprintf(ErrFp, "Found cached directory listing for `%s'\n", dir); } free(dir); i->chain = dc->chain; return OK; } dc = dc->next; } if (DebugFlag & DB_TRACE_FILES) { fprintf(ErrFp, "Scanning directory `%s' for *.rem files\n", dir); } if (ShouldCache) { dc = malloc(sizeof(DirectoryFilenameChain)); if (dc) { dc->dirname = StrDup(dir); if (!dc->dirname) { free(dc); dc = NULL; } } if (dc) { if (DebugFlag & DB_TRACE_FILES) { fprintf(ErrFp, "Caching directory `%s' listing\n", dir); } dc->chain = NULL; dc->next = CachedDirectoryChains; CachedDirectoryChains = dc; } } DBufInit(&pattern); DBufPuts(&pattern, dir); DBufPuts(&pattern, "/*.rem"); free(dir); r = glob(DBufValue(&pattern), 0, NULL, &glob_buf); DBufFree(&pattern); if (r == GLOB_NOMATCH) { globfree(&glob_buf); return OK; } if (r != 0) { globfree(&glob_buf); return -1; } /* Add the files to the chain backwards to preserve sort order */ for (r=glob_buf.gl_pathc-1; r>=0; r--) { FilenameChain *ch = malloc(sizeof(FilenameChain)); if (!ch) { globfree(&glob_buf); FreeChain(i->chain); i->chain = NULL; return E_NO_MEM; } /* TODO: stat the file and only add if it's a plain file and readable by us */ ch->filename = StrDup(glob_buf.gl_pathv[r]); if (!ch->filename) { globfree(&glob_buf); FreeChain(i->chain); i->chain = NULL; free(ch); return E_NO_MEM; } ch->next = i->chain; i->chain = ch; } if (dc) { dc->chain = i->chain; } globfree(&glob_buf); return OK; }
static int ReadLineFromFile(void) { int l; char copy_buffer[4096]; size_t n; DynamicBuffer buf; DBufInit(&buf); DBufFree(&LineBuffer); while(fp) { if (DBufGets(&buf, fp) != OK) { DBufFree(&LineBuffer); return E_NO_MEM; } LineNo++; if (ferror(fp)) { DBufFree(&buf); DBufFree(&LineBuffer); return E_IO_ERR; } if (feof(fp)) { FCLOSE(fp); if ((DBufLen(&buf) == 0) && (DBufLen(&LineBuffer) == 0) && PurgeMode) { if (PurgeFP != NULL && PurgeFP != stdout) fclose(PurgeFP); PurgeFP = NULL; } } l = DBufLen(&buf); if (l && (DBufValue(&buf)[l-1] == '\\')) { if (PurgeMode) { if (DBufPuts(&LineBuffer, DBufValue(&buf)) != OK) { DBufFree(&buf); DBufFree(&LineBuffer); return E_NO_MEM; } if (DBufPutc(&LineBuffer, '\n') != OK) { DBufFree(&buf); DBufFree(&LineBuffer); return E_NO_MEM; } } else { DBufValue(&buf)[l-1] = '\n'; if (DBufPuts(&LineBuffer, DBufValue(&buf)) != OK) { DBufFree(&buf); DBufFree(&LineBuffer); return E_NO_MEM; } } continue; } if (DBufPuts(&LineBuffer, DBufValue(&buf)) != OK) { DBufFree(&buf); DBufFree(&LineBuffer); return E_NO_MEM; } DBufFree(&buf); /* If the line is: __EOF__ treat it as end-of-file */ CurLine = DBufValue(&LineBuffer); if (!strcmp(CurLine, "__EOF__")) { if (PurgeMode && PurgeFP) { PurgeEchoLine("%s\n", "__EOF__"); while ((n = fread(copy_buffer, 1, sizeof(copy_buffer), fp)) != 0) { fwrite(copy_buffer, 1, n, PurgeFP); } if (PurgeFP != stdout) fclose(PurgeFP); PurgeFP = NULL; } FCLOSE(fp); DBufFree(&LineBuffer); CurLine = DBufValue(&LineBuffer); } FreshLine = 1; if (DebugFlag & DB_ECHO_LINE) OutputLine(ErrFp); return OK; } CurLine = DBufValue(&LineBuffer); return OK; }
static int DoCalRem(ParsePtr p, int col) { int oldLen; Trigger trig; TimeTrig tim; Value v; int r, err; int jul; CalEntry *CurCol = CalColumn[col]; CalEntry *e; char const *s, *s2; DynamicBuffer buf, obuf, pre_buf; Token tok; int is_color, col_r, col_g, col_b; is_color = 0; DBufInit(&buf); DBufInit(&pre_buf); /* Parse the trigger date and time */ if ( (r=ParseRem(p, &trig, &tim, 1)) ) { FreeTrig(&trig); return r; } /* Don't include timed reminders in calendar if -a option supplied. */ if (DontIssueAts && tim.ttime != NO_TIME) { FreeTrig(&trig); return OK; } if (trig.typ == NO_TYPE) { FreeTrig(&trig); return E_EOLN; } if (trig.typ == SAT_TYPE) { r=DoSatRemind(&trig, &tim, p); if (r) { FreeTrig(&trig); if (r == E_EXPIRED) return OK; return r; } if (!LastTrigValid) { FreeTrig(&trig); return OK; } r=ParseToken(p, &buf); if (r) { FreeTrig(&trig); return r; } FindToken(DBufValue(&buf), &tok); DBufFree(&buf); if (tok.type == T_Empty || tok.type == T_Comment) { FreeTrig(&trig); return OK; } if (tok.type != T_RemType || tok.val == SAT_TYPE) { FreeTrig(&trig); return E_PARSE_ERR; } if (tok.val == PASSTHRU_TYPE) { r=ParseToken(p, &buf); if (r) return r; if (!DBufLen(&buf)) { DBufFree(&buf); FreeTrig(&trig); return E_EOLN; } StrnCpy(trig.passthru, DBufValue(&buf), PASSTHRU_LEN); DBufFree(&buf); } trig.typ = tok.val; jul = LastTriggerDate; if (!LastTrigValid) { FreeTrig(&trig); return OK; } } else { /* Calculate the trigger date */ jul = ComputeTrigger(trig.scanfrom, &trig, &r, 1); if (r) { FreeTrig(&trig); return r; } } /* Convert PS and PSF to PASSTHRU */ if (trig.typ == PS_TYPE) { strcpy(trig.passthru, "PostScript"); trig.typ = PASSTHRU_TYPE; } else if (trig.typ == PSF_TYPE) { strcpy(trig.passthru, "PSFile"); trig.typ = PASSTHRU_TYPE; } if (trig.typ == PASSTHRU_TYPE) { if (!PsCal && strcmp(trig.passthru, "COLOR") && strcmp(trig.passthru, "COLOUR")) { FreeTrig(&trig); return OK; } if (!strcmp(trig.passthru, "COLOR") || !strcmp(trig.passthru, "COLOUR")) { is_color = 1; /* Strip off the three color numbers */ DBufFree(&buf); r=ParseToken(p, &buf); DBufPuts(&pre_buf, DBufValue(&buf)); DBufPutc(&pre_buf, ' '); DBufFree(&buf); if (r) { FreeTrig(&trig); return r; } r=ParseToken(p, &buf); DBufPuts(&pre_buf, DBufValue(&buf)); DBufPutc(&pre_buf, ' '); DBufFree(&buf); if (r) { FreeTrig(&trig); return r; } r=ParseToken(p, &buf); DBufPuts(&pre_buf, DBufValue(&buf)); DBufPutc(&pre_buf, ' '); DBufFree(&buf); if (r) { FreeTrig(&trig); return r; } (void) sscanf(DBufValue(&pre_buf), "%d %d %d", &col_r, &col_g, &col_b); if (col_r < 0) col_r = 0; else if (col_r > 255) col_r = 255; if (col_g < 0) col_g = 0; else if (col_g > 255) col_g = 255; if (col_b < 0) col_b = 0; else if (col_b > 255) col_b = 255; if (!PsCal && !DoSimpleCalendar) { DBufFree(&pre_buf); } } } /* If trigger date == today, add it to the current entry */ DBufInit(&obuf); if ((jul == JulianToday) || (DoSimpleCalDelta && ShouldTriggerReminder(&trig, &tim, jul, &err))) { NumTriggered++; if (DoSimpleCalendar || tim.ttime != NO_TIME) { /* Suppress time if it's not today or if it's a non-COLOR special */ if (jul != JulianToday || (trig.typ == PASSTHRU_TYPE && strcmp(trig.passthru, "COLOUR") && strcmp(trig.passthru, "COLOR"))) { if (DBufPuts(&obuf, SimpleTime(NO_TIME)) != OK) { DBufFree(&obuf); DBufFree(&pre_buf); FreeTrig(&trig); return E_NO_MEM; } } else { if (DBufPuts(&obuf, CalendarTime(tim.ttime, tim.duration)) != OK) { DBufFree(&obuf); DBufFree(&pre_buf); FreeTrig(&trig); return E_NO_MEM; } } } if (trig.typ != PASSTHRU_TYPE && UserFuncExists("calprefix")==1) { char evalBuf[64]; sprintf(evalBuf, "calprefix(%d)", trig.priority); s2 = evalBuf; r = EvalExpr(&s2, &v, NULL); if (!r) { if (!DoCoerce(STR_TYPE, &v)) { if (DBufPuts(&obuf, v.v.str) != OK) { DestroyValue(v); DBufFree(&obuf); DBufFree(&pre_buf); FreeTrig(&trig); return E_NO_MEM; } } DestroyValue(v); } } oldLen = DBufLen(&obuf); /* In -sa mode, run in ADVANCE mode if we're triggering * before the actual date */ if (jul != JulianToday) { r = DoSubst(p, &obuf, &trig, &tim, jul, ADVANCE_MODE); } else { r = DoSubst(p, &obuf, &trig, &tim, jul, CAL_MODE); } if (r) { DBufFree(&pre_buf); DBufFree(&obuf); FreeTrig(&trig); return r; } if (DBufLen(&obuf) <= oldLen) { DBufFree(&obuf); DBufFree(&pre_buf); FreeTrig(&trig); return OK; } if (trig.typ != PASSTHRU_TYPE && UserFuncExists("calsuffix")==1) { char evalBuf[64]; sprintf(evalBuf, "calsuffix(%d)", trig.priority); s2 = evalBuf; r = EvalExpr(&s2, &v, NULL); if (!r) { if (!DoCoerce(STR_TYPE, &v)) { if (DBufPuts(&obuf, v.v.str) != OK) { DestroyValue(v); DBufFree(&obuf); DBufFree(&pre_buf); FreeTrig(&trig); return E_NO_MEM; } } DestroyValue(v); } } s = DBufValue(&obuf); if (!DoSimpleCalendar) while (isempty(*s)) s++; DBufPuts(&pre_buf, s); s = DBufValue(&pre_buf); e = NEW(CalEntry); if (!e) { DBufFree(&obuf); DBufFree(&pre_buf); FreeTrig(&trig); return E_NO_MEM; } #ifdef REM_USE_WCHAR e->wc_pos = NULL; e->wc_text = NULL; #endif e->is_color = is_color; e->r = col_r; e->g = col_g; e->b = col_b; e->text = StrDup(s); DBufFree(&obuf); DBufFree(&pre_buf); if (!e->text) { free(e); FreeTrig(&trig); return E_NO_MEM; } make_wchar_versions(e); DBufInit(&(e->tags)); DBufPuts(&(e->tags), DBufValue(&(trig.tags))); if (SynthesizeTags) { AppendTag(&(e->tags), SynthesizeTag()); } /* Don't need tags any more */ FreeTrig(&trig); e->duration = tim.duration; e->priority = trig.priority; e->filename = StrDup(FileName); if(!e->filename) { free(e); return E_NO_MEM; } e->lineno = LineNo; if (trig.typ == PASSTHRU_TYPE) { StrnCpy(e->passthru, trig.passthru, PASSTHRU_LEN); } else { e->passthru[0] = 0; } e->pos = e->text; if (jul == JulianToday) { e->time = tim.ttime; } else { e->time = NO_TIME; } e->next = CurCol; CalColumn[col] = e; SortCol(&CalColumn[col]); } return OK; }
static int ReadLineFromFile(void) { int l; DynamicBuffer buf; DBufInit(&buf); DBufFree(&LineBuffer); while(fp) { if (DBufGets(&buf, fp) != OK) { DBufFree(&LineBuffer); return E_NO_MEM; } LineNo++; if (ferror(fp)) { DBufFree(&buf); DBufFree(&LineBuffer); return E_IO_ERR; } if (feof(fp)) { FCLOSE(fp); if ((DBufLen(&buf) == 0) && (DBufLen(&LineBuffer) == 0) && PurgeMode) { if (PurgeFP != NULL && PurgeFP != stdout) fclose(PurgeFP); PurgeFP = NULL; } } l = DBufLen(&buf); if (l && (DBufValue(&buf)[l-1] == '\\')) { if (PurgeMode) { if (DBufPuts(&LineBuffer, DBufValue(&buf)) != OK) { DBufFree(&buf); DBufFree(&LineBuffer); return E_NO_MEM; } if (DBufPutc(&LineBuffer, '\n') != OK) { DBufFree(&buf); DBufFree(&LineBuffer); return E_NO_MEM; } } else { DBufValue(&buf)[l-1] = '\n'; if (DBufPuts(&LineBuffer, DBufValue(&buf)) != OK) { DBufFree(&buf); DBufFree(&LineBuffer); return E_NO_MEM; } } continue; } if (DBufPuts(&LineBuffer, DBufValue(&buf)) != OK) { DBufFree(&buf); DBufFree(&LineBuffer); return E_NO_MEM; } FreshLine = 1; CurLine = DBufValue(&LineBuffer); if (DebugFlag & DB_ECHO_LINE) OutputLine(ErrFp); return OK; } CurLine = DBufValue(&LineBuffer); return OK; }