error("can't get login name", (char*)0);
if (chdir(maildir) == -1)
error("can't cd to %s", maildir);
for (;;) {
if (stat(name, buf) == -1) /* no mailbox */
buf.st_size = 0;
if (buf.st_size lastsize)
fprintf(stderr, "\nYou have mail\007\n");
lastsize = buf.st_size;
sleep(60);
}
}
Функция getlogin(3)
возвращает ваше регистрационное имя или NULL
, если это невозможно, checkmail
переходит к почтовому каталогу с помощью системного вызова chdir
, так что последующие вызовы stat
не должны будут "добираться" до почтового каталога через все каталоги, начиная от корневого. Возможно, вы должны адаптировать maildir
для своей системы. Мы написали checkmail
так, чтобы она работала, даже если нет почтового ящика, поскольку большинство версий mail убирают почтовый ящик в том случае, когда он пуст.
Мы приводили эту программу в гл. 5 для иллюстрации циклов shell
. Всякий раз при проверке почтового ящика она создает несколько процессов и загружает систему больше, чем хотелось бы. Версия на Си — единственный процесс, который выполняет stat
для файла каждую минуту. Сколько времени требуется на то, чтобы checkmail
постоянно выполнялась как фоновая задача? Как показали наши измерения, это время составляет меньше секунды в час, так что им вполне можно пренебречь.
sv
: иллюстрация обработки ошибокСледующей мы собираемся написать похожую на cp
программу sv
, которая будет копировать множество файлов в каталог, заменяя каждый файл лишь в том случае, если его нет в каталоге или он "старше" копируемого с тем же именем (имя sv
означает "сохранять"). Суть действия программы состоит в том, что она не переписывает новую версию файла, sv
использует больше информации из индексного дескриптора, чем checkmail
. Вызов sv
будет иметь такую конструкцию:
$ sv file1 file2 ... dir
Она копирует file1
в dir/file1
, file2
в dir/file2
и т.д., если только целевой файл не новее, чем файл-источник; в этой ситуации копирование не происходит и печатается соответствующее предупреждение. Во избежание создания большого числа копий или связанных файлов sv
не допускает применения символов '/'
в любом исходном имени файла.
/* sv: save new files */
#include stdio.h
#include sys/types.h
#include sys/dir.h
#include sys/stat.h
char *progname;
main(argc, argv)
int argc;
char *argv[];
{
int i;
struct stat stbuf;
char *dir = argv[argc-1];
progname = argv[0];
if (argc = 2)
error("Usage: %s files... dir", progname);
if (stat(dir, stbuf) == -1)
error("can't access directory %s", dir);
if ((stbuf.st_mode S_IFMT) != S_IFDIR)
error("%s is not a directory", dir);
for (i = 1; i argc-1; i++)
sv(argv[i], dir);
exit(0);
}
Значения времени, хранящиеся в индексных дескрипторах, исчисляются в секундах (за начало отсчета принято время 0:00 по Гринвичу, 1 января 1970 г.), так что более старые файлы имеют меньшие значения в поле st_mtime
.
sv(file, dir) /* save file in dir */
char *file, *dir;
{
struct stat sti, sto;
int fin, fout, n;
char target[BUFSIZ], buf[BUFSIZ], *index;
sprintf(target, "%s/%s", dir, file);
if (index(file, '/') != NULL) /* strchr in some systems */
error("won't handle /'s in %s", file);
if (stat(file, sti) == -1)
error("can't stat %s", file);
if (stat(target, sto) == -1) /* target not present */
sto.st_mtime = 0; /* so make it look old */
if (sti.st_mtime sto.st_mtime) /* target is newer */
fprintf(stderr, "%s: %s not copied\n", progname, file);
else if ((fin = open(file, 0)) == -1)
error("can't open file %s", file);
else if ((fout = creat(target, sti.st_mode)) == -1)
error("can't create %s", target);
else