⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 expire.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
	*size = (int)(((long)Sb.st_size >> 10) + (((long)Sb.st_size >> 9) & 1));    if (EXPverbose > 1)	(void)printf("\tunlink %s\n", p);    EXPunlinked++;    if (EXPtracing) {	(void)printf("%s\n", p);	return;    }    if (EXPunlinkfile) {	(void)fprintf(EXPunlinkfile, "%s\n", p);	if (!ferror(EXPunlinkfile))	    return;	(void)fprintf(stderr, "Can't write to -z file, %s\n",		strerror(errno));	(void)fprintf(stderr, "(Will ignore it for rest of run.)\n");	(void)fclose(EXPunlinkfile);	EXPunlinkfile = NULL;    }    if (unlink(p) < 0 && errno != ENOENT)	(void)fprintf(stderr, "Can't unlink %s, %s\n", p, strerror(errno));}/***  Do the work of expiring one line.*/STATIC BOOLEXPdoline(out, line, length, arts)    FILE		*out;    char		*line;    int			length;    char		**arts;{    static char		IGNORING[] = "Ignoring bad line, \"%.20s...\"\n";    static long		Offset;    static BUFFER	New;    register char	*p;    register char	*q;    register char	*first;    register int	i;    int			count;    char		*fields[4];    time_t		Arrived;    time_t		Expires;    time_t		Posted;    time_t		when;    long		where;    long		size;    datum		key;    datum		value;    char 		date[20];    /* Split up the major fields. */    i = EXPsplit(line, HIS_FIELDSEP, fields, SIZEOF(fields));    if (i != 2 && i != 3) {	(void)fprintf(stderr, IGNORING, line);	return TRUE;    }    /* Split up the time field, robustly. */    if ((p = strchr(fields[1], HIS_SUBFIELDSEP)) == NULL) {	/* One sub-field:  when the article arrived. */	Arrived = atol(fields[1]);	Expires = 0;	Posted = Arrived;    }    else {	*p = '\0';	Arrived = atol(fields[1]);	*p++ = HIS_SUBFIELDSEP;	if ((q = strchr(p, HIS_SUBFIELDSEP)) == NULL) {	    /* Two sub-fields:  arrival and expiration. */	    Expires = EQ(p, HIS_NOEXP) ? 0 : atol(p);	    Posted = Arrived;	}	else {	    /* All three sub-fields:  arrival, expiration, posted. */	    *q = '\0';	    Expires = EQ(p, HIS_NOEXP) ? 0 : atol(p);	    *q++ = HIS_SUBFIELDSEP;	    Posted = atol(q);	}    }    if (i == 2) {	/* History line for already-expired article. */	if (Arrived < EXPremember) {	    if (EXPverbose > 3)		(void)printf("forget: %s\n", line);	    EXPhistdrop++;	    return TRUE;	}	/* Not time to forget about this one yet. */	if (out) {	    where = Offset;	    (void)fprintf(out, "%s%c%s\n", fields[0], HIS_FIELDSEP, fields[1]);	    Offset += strlen(fields[0]) + 1 + strlen(fields[1]) + 1;	    if (EXPverbose > 3)		(void)printf("remember: %s\n", line);	    EXPhistremember++;	}    }    else {	/* Active article -- split up the file entries. */	count = EXPsplit(fields[2], ' ', arts, nGroups);	if (count == -1) {	    (void)fprintf(stderr, IGNORING, line);	    return TRUE;	}	EXPprocessed++;	when = EXPusepost ? Posted : Arrived;	/* Get space to hold the remaining file name entries. */	if (New.Data == NULL) {	    New.Size = length;	    New.Data = NEW(char, New.Size);	}	else if (New.Size < length) {	    New.Size = length;	    RENEW(New.Data, char, New.Size);	}	/* The "first" variable tells us if we haven't saved the first	 * article yet.  This only matters if we're doing link-saving. */	first = EXPlinks && count > 1 ? arts[0] : (char *)NULL;	/* Loop over all file entries, see if we should keep each one. */	for (size = -1, q = New.Data, i = 0; i < count; i++) {	    p = arts[i];	    if (*p == '\0')		/* Shouldn't happen. */		continue;	    if (EXPkeepit(p, when, Expires)) {		if (EXPverbose > 1)		    (void)printf("keep %s\n", p);		if (first != NULL) {		    /* Keeping one and haven't kept the first; so save it. */		    if (i > 0)			q += strlen(strcpy(q, first));		    first = NULL;		}		if (q > New.Data)		    *q++ = ' ';		q += strlen(strcpy(q, p));		continue;	    }	    /* Don't delete the file if preserving symbolic links to it. */	    if (EXPlinks && i == 0 && count > 1)		continue;	    EXPremove(arts[i], &size);	}	/* If saving links and didn't have to save the leader, delete it. */	if (EXPlinks && first != NULL)	    EXPremove(first, &size);	if (q == New.Data) {	    if (EXPsizing && size > 0)		EXPsaved += size;	    if (EXPremember > 0 && out != NULL) {		where = Offset;		(void)sprintf(date, "%ld", (long)Arrived);		(void)fprintf(out, "%s%c%s%c%s\n",			fields[0], HIS_FIELDSEP,			date, HIS_SUBFIELDSEP, HIS_NOEXP);		Offset += strlen(fields[0]) + 1			+ strlen(date) + 1 + STRLEN(HIS_NOEXP) + 1;	        if (EXPverbose > 3)		    (void)printf("remember history: %s%c%s%c%s\n",			    fields[0], HIS_FIELDSEP,			    date, HIS_SUBFIELDSEP, HIS_NOEXP);		EXPallgone++;	    }	}	else if (out) {	    where = Offset;	    (void)fprintf(out, "%s%c%s%c%s\n",		    fields[0], HIS_FIELDSEP, fields[1], HIS_FIELDSEP,		    New.Data);	    Offset += strlen(fields[0]) + 1 + strlen(fields[1]) + 1		    + strlen(New.Data) + 1;	    if (EXPverbose > 3)		(void)printf("remember article: %s%c%s%c%s\n",			fields[0], HIS_FIELDSEP, fields[1], HIS_FIELDSEP,			New.Data);	    EXPstillhere++;	}    }    if (out == NULL)	return TRUE;    if (ferror(out)) {	(void)fprintf(stderr, "Can't write new history, %s\n",		strerror(errno));	return FALSE;    }    /* Set up the DBZ data.  We don't have to sanitize the Message-ID     * since it had to have been clean to get in there. */    key.dptr = fields[0];    key.dsize = strlen(key.dptr) + 1;    value.dptr = (char *)&where;    value.dsize = sizeof where;    if (EXPverbose > 4)	(void)printf("\tdbz %s@%ld\n", key.dptr, where);    if (dbzstore(key, value) < 0) {	(void)fprintf(stderr, "Can't store key, %s\n", strerror(errno));	return FALSE;    }    return TRUE;}/***  Clean up link with the server and exit.*/STATIC NORETURNCleanupAndExit(Server, Paused, x)    BOOL	Server;    BOOL	Paused;    int		x;{    FILE	*F;    if (Server)	(void)ICCreserve("");    if (Paused && ICCgo(EXPreason) != 0) {	(void)fprintf(stderr, "Can't unpause server, %s\n",		strerror(errno));	x = 1;    }    if (Server && ICCclose() < 0) {	(void)fprintf(stderr, "Can't close communication link, %s\n",		strerror(errno));	x = 1;    }    if (EXPunlinkfile && fclose(EXPunlinkfile) == EOF) {	(void)fprintf(stderr, "Can't close -z file, %s\n", strerror(errno));	x = 1;    }    /* Report stats. */    if (EXPverbose) {	(void)printf("Article lines processed %8ld\n", EXPprocessed);	(void)printf("Articles retained       %8ld\n", EXPstillhere);	(void)printf("Entries expired         %8ld\n", EXPallgone);	(void)printf("Files unlinked          %8ld\n", EXPunlinked);	(void)printf("Old entries dropped     %8ld\n", EXPhistdrop);	(void)printf("Old entries retained    %8ld\n", EXPhistremember);    }    /* Append statistics to a summary file */    if (EXPgraph) {	F = EXPfopen(FALSE, EXPgraph, "a");	(void)fprintf(F, "%ld %ld %ld %ld %ld %ld %ld\n",		(long)Now, EXPprocessed, EXPstillhere, EXPallgone,		EXPunlinked, EXPhistdrop, EXPhistremember);	(void)fclose(F);    }    exit(x);}/***  Print a usage message and exit.*/STATIC NORETURNUsage(){    (void)fprintf(stderr, "Usage: expire [flags] [expire.ctl]\n");    exit(1);}intmain(ac, av)    int			ac;    char		*av[];{    static char		CANTCD[] = "Can't cd to %s, %s\n";    register int	i;    register int	line;    register char	*p;    register QIOSTATE	*qp;    FILE		*F;    char		*active;    char		**arts;    STRING		History;    STRING		HistoryText;    STRING		HistoryPath;    STRING		HistoryDB;    char		*Historydir;    char		*Historypag;    char		*NHistory;    char		*NHistorydir;    char		*NHistorypag;    char		buff[SMBUF];    register FILE	*out;    BOOL		Server;    BOOL		Paused;    BOOL		Bad;    BOOL		IgnoreOld;    BOOL		Writing;    BOOL		UnlinkFile;    time_t		TimeWarp;    /* Set defaults. */    Server = TRUE;    IgnoreOld = FALSE;    History = "history";    HistoryText = _PATH_HISTORY;    HistoryPath = NULL;    Writing = TRUE;    TimeWarp = 0;    UnlinkFile = FALSE;    (void)umask(NEWSUMASK);    /* Parse JCL. */    while ((i = getopt(ac, av, "f:h:d:g:ilnpqr:stv:w:xz:")) != EOF)	switch (i) {	default:	    Usage();	    /* NOTREACHED */	case 'd':	    HistoryPath = optarg;	    break;	case 'f':	    History = optarg;	    break;	case 'g':	    EXPgraph = optarg;	    break;	case 'h':	    HistoryText = optarg;	    break;	case 'i':	    IgnoreOld = TRUE;	    break;	case 'l':	    EXPlinks = TRUE;	    break;	case 'n':	    Server = FALSE;	    break;	case 'p':	    EXPusepost = TRUE;	    break;	case 'q':	    EXPquiet = TRUE;	    break;	case 'r':	    EXPreason = optarg;	    break;	case 's':	    EXPsizing = TRUE;	    break;	case 't':	    EXPtracing = TRUE;	    break;	case 'v':	    EXPverbose = atoi(optarg);	    break;	case 'w':	    TimeWarp = (time_t)(atof(optarg) * 86400.);	    break;	case 'x':	    Writing = FALSE;	    break;	case 'z':	    EXPunlinkfile = EXPfopen(TRUE, optarg, "a");	    UnlinkFile = TRUE;	    break;	}    ac -= optind;    av += optind;    if (ac != 0 && ac != 1)	Usage();    /* Get active file, parse it. */    if ((active = ReadInFile(ACTIVE, (struct stat *)NULL)) == NULL) {	(void)fprintf(stderr, "Can't read %s, %s\n",		ACTIVE, strerror(errno));	exit(1);    }    BuildGroups(active);    (void)time(&Now);    Now += TimeWarp;    /* Parse the control file. */    if (av[0])	F = EQ(av[0], "-") ? stdin : EXPfopen(FALSE, av[0], "r");    else	F = EXPfopen(FALSE, _PATH_EXPIRECTL, "r");    if (!EXPreadfile(F)) {	(void)fclose(F);	(void)fprintf(stderr, "Format error in control file\n");	exit(1);    }    (void)fclose(F);    /* Set up the link, reserve the lock. */    if (EXPreason == NULL) {	(void)sprintf(buff, "Expiring process %ld", (long)getpid());	EXPreason = COPY(buff);    }    if (Server) {	/* If we fail, leave evidence behind. */	if (ICCopen() < 0) {	    (void)fprintf(stderr, "Can't open channel to server, %s\n",		    strerror(errno));	    CleanupAndExit(FALSE, FALSE, 1);	}	if (ICCreserve(EXPreason) != 0) {	    (void)fprintf(stderr, "Can't reserve server\n");	    CleanupAndExit(FALSE, FALSE, 1);	}    }    /* Make the history filenames. */    HistoryDB = COPY(HistoryText);    (void)sprintf(buff, "%s.dir", HistoryDB);    Historydir = COPY(buff);    (void)sprintf(buff, "%s.pag", HistoryDB);    Historypag = COPY(buff);    if (HistoryPath)	(void)sprintf(buff, "%s/%s.n", HistoryPath, History);    else	(void)sprintf(buff, "%s.n", History);    NHistory = COPY(buff);    (void)sprintf(buff, "%s.dir", NHistory);    NHistorydir = COPY(buff);    (void)sprintf(buff, "%s.pag", NHistory);    NHistorypag = COPY(buff);    if (!Writing)	out = NULL;    else {	/* Open new history files, relative to news lib. */	if (chdir(EXPnewslib) < 0) {	    (void)fprintf(stderr, CANTCD, EXPnewslib, strerror(errno));	    exit(1);	}	out = EXPfopen(TRUE, NHistory, "w");	(void)fclose(EXPfopen(TRUE, NHistorydir, "w"));	(void)fclose(EXPfopen(TRUE, NHistorypag, "w"));	if (EXPverbose > 3)	    (void)printf("created: %s %s %s\n",		    NHistory, NHistorydir, NHistorypag);	(void)dbzincore(1);	if (IgnoreOld) {	    if (dbzfresh(NHistory, dbzsize(0L), '\t', 'C', 0L) < 0) {		(void)fprintf(stderr, "Can't create database, %s\n",			strerror(errno));		exit(1);	    }	}	else if (dbzagain(NHistory, HistoryDB) < 0) {	    (void)fprintf(stderr, "Can't dbzagain, %s\n", strerror(errno));	    exit(1);	}    }    if (chdir(SPOOL) < 0) {	(void)fprintf(stderr, CANTCD, SPOOL, strerror(errno));	exit(1);    }    /* Main processing loop. */    arts = NEW(char*, nGroups);    if ((qp = QIOopen(HistoryText, QIO_BUFFER)) == NULL) {	(void)fprintf(stderr, "Can't open history file, %s\n",		strerror(errno));	CleanupAndExit(Server, FALSE, 1);    }    for (Bad = FALSE, line = 1, Paused = FALSE; ; line++) {	if ((p = QIOread(qp)) != NULL) {	    if (!EXPdoline(out, p, QIOlength(qp), arts)) {		Bad = TRUE;		if (errno == ENOSPC) {		    (void)unlink(NHistory);		    (void)unlink(NHistorydir);		    (void)unlink(NHistorypag);		}		break;	    }	    continue;	}	/* Read or line-format error? */	if (QIOerror(qp)) {	    (void)fprintf(stderr, "Can't read line %d, %s\n",		    line, strerror(errno));	    QIOclose(qp);	    CleanupAndExit(Server, Paused, 1);	}	if (QIOtoolong(qp)) {	    (void)fprintf(stderr, "Line %d too long\n", line);	    QIOclose(qp);	    CleanupAndExit(Server, Paused, 1);	}	/* We hit EOF. */	if (Paused || !Server)	    /* Already paused or we don't want to pause -- we're done. */	    break;	if (ICCpause(EXPreason) != 0) {	    (void)fprintf(stderr, "Can't pause server, %s\n",		    strerror(errno));	    QIOclose(qp);	    CleanupAndExit(Server, Paused, 1);	}	Paused = TRUE;    }    QIOclose(qp);    DISPOSE(arts);    if (Writing) {	/* Close the output files. */	if (ferror(out) || fflush(out) == EOF || fclose(out) == EOF) {	    (void)fprintf(stderr, "Can't close %s, %s\n",		NHistory, strerror(errno));	    Bad = TRUE;	}	if (dbmclose() < 0) {	    (void)fprintf(stderr, "Can't close history, %s\n",		    strerror(errno));	    Bad = TRUE;	}	if (UnlinkFile && EXPunlinkfile == NULL)	    /* Got -z but file was closed; oops. */	    Bad = TRUE;	/* If we're done okay, and we're not tracing, slip in the new files. */	if (EXPverbose) {	    if (Bad)		(void)printf("Expire errors: history files not updated.\n");	    if (EXPtracing)		(void)printf("Expire tracing: history files not updated.\n");	}	if (!Bad && !EXPtracing) {	    if (chdir(EXPnewslib) < 0) {		(void)fprintf(stderr, CANTCD, EXPnewslib, strerror(errno));		CleanupAndExit(Server, Paused, 1);	    }	    /* If user used the -d flag, mark we're done and exit. */	    if (HistoryPath != NULL) {		(void)sprintf(buff, "%s.done", NHistory);		(void)fclose(EXPfopen(FALSE, buff, "w"));		CleanupAndExit(Server, FALSE, 0);	    }	    if (rename(NHistory, HistoryText) < 0	     || rename(NHistorydir, Historydir) < 0	     || rename(NHistorypag, Historypag) < 0) {		(void)fprintf(stderr, "Can't replace history files, %s\n",			strerror(errno));		/* Yes -- leave the server paused. */		CleanupAndExit(Server, FALSE, 1);	    }	}    }    if (EXPsizing)	(void)printf("%s approximately %ldk\n",	    EXPtracing ? "Would remove" : "Removed", EXPsaved);    CleanupAndExit(Server, Paused, Bad ? 1 : 0);    /* NOTREACHED */}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -