/* mailcheck.c -- The check is in the mail... */
-/* Copyright (C) 1987,1989 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2009 Free Software Foundation, Inc.
-This file is part of GNU Bash, the Bourne Again SHell.
+ This file is part of GNU Bash, the Bourne Again SHell.
-Bash is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
-version.
+ Bash is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
-Bash is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-for more details.
+ Bash is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
-You should have received a copy of the GNU General Public License along
-with Bash; see the file COPYING. If not, write to the Free Software
-Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+ You should have received a copy of the GNU General Public License
+ along with Bash. If not, see <http://www.gnu.org/licenses/>.
+*/
#include "config.h"
#include <stdio.h>
#include "bashtypes.h"
#include "posixstat.h"
-#ifndef _MINIX
+#if defined (HAVE_SYS_PARAM_H)
# include <sys/param.h>
#endif
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
+#include "posixtime.h"
#include "bashansi.h"
+#include "bashintl.h"
#include "shell.h"
-#include "maxpath.h"
#include "execute_cmd.h"
#include "mailcheck.h"
#include <tilde/tilde.h>
-#ifndef NOW
-#define NOW ((time_t)time ((time_t *)0))
-#endif
+/* Values for flags word in struct _fileinfo */
+#define MBOX_INITIALIZED 0x01
+
+extern time_t shell_start_time;
-typedef struct {
+extern int mailstat __P((const char *, struct stat *));
+
+typedef struct _fileinfo {
char *name;
char *msg;
time_t access_time;
time_t mod_time;
off_t file_size;
+ int flags;
} FILEINFO;
/* The list of remembered mail files. */
static int mailfiles_count;
/* The last known time that mail was checked. */
-static int last_time_mail_checked;
+static time_t last_time_mail_checked = 0;
/* Non-zero means warn if a mail file has been read since last checked. */
int mail_warning;
+static int find_mail_file __P((char *));
+static void init_mail_file __P((int));
+static void update_mail_file __P((int));
+static int add_mail_file __P((char *, char *));
+
+static FILEINFO *alloc_mail_file __P((char *, char *));
+static void dispose_mail_file __P((FILEINFO *));
+
+static int file_mod_date_changed __P((int));
+static int file_access_date_changed __P((int));
+static int file_has_grown __P((int));
+
+static char *parse_mailpath_spec __P((char *));
+
/* Returns non-zero if it is time to check mail. */
int
time_to_check_mail ()
{
char *temp;
time_t now;
- long seconds;
+ intmax_t seconds;
temp = get_string_value ("MAILCHECK");
- seconds = -1L;
-
- /* Skip leading whitespace in MAILCHECK. */
- if (temp)
- {
- while (whitespace (*temp))
- temp++;
-
- seconds = atoi (temp);
- }
/* Negative number, or non-numbers (such as empty string) cause no
checking to take place. */
- if (seconds < 0)
+ if (temp == 0 || legal_number (temp, &seconds) == 0 || seconds < 0)
return (0);
now = NOW;
{ \
mailfiles[i]->access_time = mailfiles[i]->mod_time = 0; \
mailfiles[i]->file_size = 0; \
+ mailfiles[i]->flags = 0; \
+ } \
+ while (0)
+
+#define UPDATE_MAIL_FILE(i, finfo) \
+ do \
+ { \
+ mailfiles[i]->access_time = finfo.st_atime; \
+ mailfiles[i]->mod_time = finfo.st_mtime; \
+ mailfiles[i]->file_size = finfo.st_size; \
+ mailfiles[i]->flags |= MBOX_INITIALIZED; \
} \
while (0)
+static void
+init_mail_file (i)
+ int i;
+{
+ mailfiles[i]->access_time = mailfiles[i]->mod_time = last_time_mail_checked ? last_time_mail_checked : shell_start_time;
+ mailfiles[i]->file_size = 0;
+ mailfiles[i]->flags = 0;
+}
+
static void
update_mail_file (i)
int i;
struct stat finfo;
file = mailfiles[i]->name;
- if (stat (file, &finfo) == 0)
- {
- mailfiles[i]->access_time = finfo.st_atime;
- mailfiles[i]->mod_time = finfo.st_mtime;
- mailfiles[i]->file_size = finfo.st_size;
- }
+ if (mailstat (file, &finfo) == 0)
+ UPDATE_MAIL_FILE (i, finfo);
else
RESET_MAIL_FILE (i);
}
i = find_mail_file (filename);
if (i >= 0)
{
- if (stat (filename, &finfo) == 0)
- {
- mailfiles[i]->mod_time = finfo.st_mtime;
- mailfiles[i]->access_time = finfo.st_atime;
- mailfiles[i]->file_size = finfo.st_size;
- }
+ if (mailstat (filename, &finfo) == 0)
+ UPDATE_MAIL_FILE (i, finfo);
+
free (filename);
return i;
}
mailfiles = (FILEINFO **)xrealloc
(mailfiles, mailfiles_count * sizeof (FILEINFO *));
- mailfiles[i] = (FILEINFO *)xmalloc (sizeof (FILEINFO));
- mailfiles[i]->name = filename;
- mailfiles[i]->msg = msg ? savestring (msg) : (char *)NULL;
- update_mail_file (i);
+ mailfiles[i] = alloc_mail_file (filename, msg);
+ init_mail_file (i);
+
return i;
}
register int i;
for (i = 0; i < mailfiles_count; i++)
- {
- RESET_MAIL_FILE (i);
- }
+ RESET_MAIL_FILE (i);
+}
+
+static FILEINFO *
+alloc_mail_file (filename, msg)
+ char *filename, *msg;
+{
+ FILEINFO *mf;
+
+ mf = (FILEINFO *)xmalloc (sizeof (FILEINFO));
+ mf->name = filename;
+ mf->msg = msg ? savestring (msg) : (char *)NULL;
+ mf->flags = 0;
+
+ return mf;
+}
+
+static void
+dispose_mail_file (mf)
+ FILEINFO *mf;
+{
+ free (mf->name);
+ FREE (mf->msg);
+ free (mf);
}
/* Free the information that we have about the remembered mail files. */
register int i;
for (i = 0; i < mailfiles_count; i++)
- {
- free (mailfiles[i]->name);
- FREE (mailfiles[i]->msg);
- free (mailfiles[i]);
- }
+ dispose_mail_file (mailfiles[i]);
if (mailfiles)
free (mailfiles);
mailfiles = (FILEINFO **)NULL;
}
+void
+init_mail_dates ()
+{
+ if (mailfiles == 0)
+ remember_mail_dates ();
+}
+
/* Return non-zero if FILE's mod date has changed and it has not been
- accessed since modified. */
+ accessed since modified. If the size has dropped to zero, reset
+ the cached mail file info. */
static int
file_mod_date_changed (i)
int i;
file = mailfiles[i]->name;
mtime = mailfiles[i]->mod_time;
- if ((stat (file, &finfo) == 0) && (finfo.st_size > 0))
- return (mtime != finfo.st_mtime);
+ if (mailstat (file, &finfo) != 0)
+ return (0);
+
+ if (finfo.st_size > 0)
+ return (mtime < finfo.st_mtime);
+
+ if (finfo.st_size == 0 && mailfiles[i]->file_size > 0)
+ UPDATE_MAIL_FILE (i, finfo);
return (0);
}
file = mailfiles[i]->name;
atime = mailfiles[i]->access_time;
- if ((stat (file, &finfo) == 0) && (finfo.st_size > 0))
- return (atime != finfo.st_atime);
+ if (mailstat (file, &finfo) != 0)
+ return (0);
+
+ if (finfo.st_size > 0)
+ return (atime < finfo.st_atime);
return (0);
}
file = mailfiles[i]->name;
size = mailfiles[i]->file_size;
- return ((stat (file, &finfo) == 0) && (finfo.st_size > size));
+ return ((mailstat (file, &finfo) == 0) && (finfo.st_size > size));
}
/* Take an element from $MAILPATH and return the portion from
char *
make_default_mailpath ()
{
+#if defined (DEFAULT_MAIL_DIRECTORY)
char *mp;
get_current_user_info ();
- mp = xmalloc (2 + sizeof (DEFAULT_MAIL_DIRECTORY) + strlen (current_user.user_name));
+ mp = (char *)xmalloc (2 + sizeof (DEFAULT_MAIL_DIRECTORY) + strlen (current_user.user_name));
strcpy (mp, DEFAULT_MAIL_DIRECTORY);
mp[sizeof(DEFAULT_MAIL_DIRECTORY) - 1] = '/';
strcpy (mp + sizeof (DEFAULT_MAIL_DIRECTORY), current_user.user_name);
return (mp);
+#else
+ return ((char *)NULL);
+#endif
}
/* Remember the dates of the files specified by MAILPATH, or if there is
no MAILPATH, by the file specified in MAIL. If neither exists, use a
default value, which we randomly concoct from using Unix. */
+
void
remember_mail_dates ()
{
if (mailpaths == 0)
{
mailpaths = make_default_mailpath ();
- add_mail_file (mailpaths, (char *)NULL);
- free (mailpaths);
+ if (mailpaths)
+ {
+ add_mail_file (mailpaths, (char *)NULL);
+ free (mailpaths);
+ }
return;
}
char *current_mail_file, *message;
int i, use_user_notification;
char *dollar_underscore, *temp;
- WORD_LIST *tlist;
dollar_underscore = get_string_value ("_");
if (dollar_underscore)
int file_is_bigger;
use_user_notification = mailfiles[i]->msg != (char *)NULL;
- message = mailfiles[i]->msg ? mailfiles[i]->msg : "You have mail in $_";
+ message = mailfiles[i]->msg ? mailfiles[i]->msg : _("You have mail in $_");
- bind_variable ("_", current_mail_file);
+ bind_variable ("_", current_mail_file, 0);
#define atime mailfiles[i]->access_time
#define mtime mailfiles[i]->mod_time
/* If the mod time is later than the access time and the file
has grown, note the fact that this is *new* mail. */
if (use_user_notification == 0 && (atime < mtime) && file_is_bigger)
- message = "You have new mail in $_";
+ message = _("You have new mail in $_");
#undef atime
#undef mtime
- if ((tlist = expand_string (message, Q_DOUBLE_QUOTES)))
+ if (temp = expand_string_to_string (message, Q_DOUBLE_QUOTES))
{
- temp = string_list (tlist);
puts (temp);
free (temp);
- dispose_words (tlist);
}
else
putchar ('\n');
if (mail_warning && file_access_date_changed (i))
{
update_mail_file (i);
- printf ("The mail in %s has been read\n", current_mail_file);
+ printf (_("The mail in %s has been read\n"), current_mail_file);
}
}
if (dollar_underscore)
{
- bind_variable ("_", dollar_underscore);
+ bind_variable ("_", dollar_underscore, 0);
free (dollar_underscore);
}
else