summaryrefslogtreecommitdiff
path: root/pith/init.c
diff options
context:
space:
mode:
authorEduardo Chappa <echappa@gmx.com>2013-02-03 00:59:38 -0700
committerEduardo Chappa <echappa@gmx.com>2013-02-03 00:59:38 -0700
commit094ca96844842928810f14844413109fc6cdd890 (patch)
treee60efbb980f38ba9308ccb4fb2b77b87bbc115f3 /pith/init.c
downloadalpine-094ca96844842928810f14844413109fc6cdd890.tar.xz
Initial Alpine Version
Diffstat (limited to 'pith/init.c')
-rw-r--r--pith/init.c546
1 files changed, 546 insertions, 0 deletions
diff --git a/pith/init.c b/pith/init.c
new file mode 100644
index 00000000..d7942dcb
--- /dev/null
+++ b/pith/init.c
@@ -0,0 +1,546 @@
+#if !defined(lint) && !defined(DOS)
+static char rcsid[] = "$Id: init.c 769 2007-10-24 00:15:40Z hubert@u.washington.edu $";
+#endif
+
+/*
+ * ========================================================================
+ * Copyright 2006-2007 University of Washington
+ * Copyright 2013 Eduardo Chappa
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * ========================================================================
+ */
+
+/*======================================================================
+ init.c
+ Routines for pine start up and initialization
+ ====*/
+
+
+#include "../pith/headers.h"
+#include "../pith/init.h"
+#include "../pith/conf.h"
+#include "../pith/status.h"
+#include "../pith/folder.h"
+
+
+/*
+ * Internal prototypes
+ */
+int compare_sm_files(const qsort_t *, const qsort_t *);
+
+
+
+/*----------------------------------------------------------------------
+ Sets login, full_username and home_dir
+
+ Args: ps -- The Pine structure to put the user name, etc in
+
+ Result: sets the fullname, login and home_dir field of the pine structure
+ returns 0 on success, -1 if not.
+ ----*/
+
+int
+init_username(struct pine *ps)
+{
+ char *expanded;
+ int rv;
+
+ rv = 0;
+ expanded = NULL;
+#if defined(DOS) || defined(OS2)
+ if(ps->COM_USER_ID)
+ expanded = expand_variables(tmp_20k_buf, SIZEOF_20KBUF,
+ ps->COM_USER_ID, 0);
+
+ if(!expanded && ps->vars[V_USER_ID].post_user_val.p)
+ expanded = expand_variables(tmp_20k_buf, SIZEOF_20KBUF,
+ ps->vars[V_USER_ID].post_user_val.p, 0);
+
+ if(!expanded && ps->vars[V_USER_ID].main_user_val.p)
+ expanded = expand_variables(tmp_20k_buf, SIZEOF_20KBUF,
+ ps->vars[V_USER_ID].main_user_val.p, 0);
+
+ if(!expanded)
+ ps->blank_user_id = 1;
+
+ ps->VAR_USER_ID = cpystr(expanded ? expanded : "");
+#else
+ ps->VAR_USER_ID = cpystr(ps->ui.login);
+ if(!ps->VAR_USER_ID[0]){
+ fprintf(stderr, "Who are you? (Unable to look up login name)\n");
+ rv = -1;
+ }
+#endif
+
+ expanded = NULL;
+ if(ps->vars[V_PERSONAL_NAME].is_fixed){
+ if(ps->FIX_PERSONAL_NAME){
+ expanded = expand_variables(tmp_20k_buf, SIZEOF_20KBUF,
+ ps->FIX_PERSONAL_NAME, 0);
+ }
+ if(ps->vars[V_PERSONAL_NAME].main_user_val.p ||
+ ps->vars[V_PERSONAL_NAME].post_user_val.p){
+ ps_global->give_fixed_warning = 1;
+ ps_global->fix_fixed_warning = 1;
+ }
+ else if(ps->COM_PERSONAL_NAME)
+ ps_global->give_fixed_warning = 1;
+ }
+ else{
+ if(ps->COM_PERSONAL_NAME)
+ expanded = expand_variables(tmp_20k_buf, SIZEOF_20KBUF,
+ ps->COM_PERSONAL_NAME, 0);
+
+ if(!expanded && ps->vars[V_PERSONAL_NAME].post_user_val.p)
+ expanded = expand_variables(tmp_20k_buf, SIZEOF_20KBUF,
+ ps->vars[V_PERSONAL_NAME].post_user_val.p, 0);
+
+ if(!expanded && ps->vars[V_PERSONAL_NAME].main_user_val.p)
+ expanded = expand_variables(tmp_20k_buf, SIZEOF_20KBUF,
+ ps->vars[V_PERSONAL_NAME].main_user_val.p, 0);
+ }
+
+ if(!expanded){
+ expanded = ps->ui.fullname;
+#if defined(DOS) || defined(OS2)
+ ps->blank_personal_name = 1;
+#endif
+ }
+
+ ps->VAR_PERSONAL_NAME = cpystr(expanded ? expanded : "");
+
+ dprint((1, "Userid: %s\nFullname: \"%s\"\n",
+ ps->VAR_USER_ID, ps->VAR_PERSONAL_NAME));
+ return(rv);
+}
+
+
+/*----------------------------------------------------------------------
+ Sets home_dir
+
+ Args: ps -- The Pine structure to put the user name, etc in
+
+ Result: sets the home_dir field of the pine structure
+ returns 0 on success, -1 if not.
+ ----*/
+
+int
+init_userdir(struct pine *ps)
+{
+ char fld_dir[MAXPATH+1];
+
+ if(strlen(ps->home_dir) + strlen(ps->VAR_MAIL_DIRECTORY)+2 > MAXPATH){
+ printf(_("Folders directory name is longer than %d\n"), MAXPATH);
+ printf(_("Directory name: \"%s/%s\"\n"),ps->home_dir,
+ ps->VAR_MAIL_DIRECTORY);
+ return(-1);
+ }
+#if defined(DOS) || defined(OS2)
+ if(ps->VAR_MAIL_DIRECTORY[1] == ':'){
+ strncpy(fld_dir, ps->VAR_MAIL_DIRECTORY, sizeof(fld_dir)-1);
+ fld_dir[sizeof(fld_dir)-1] = '\0';
+ }
+ else
+#endif
+ build_path(fld_dir, ps->home_dir, ps->VAR_MAIL_DIRECTORY, sizeof(fld_dir));
+ ps->folders_dir = cpystr(fld_dir);
+
+ return(0);
+}
+
+
+/*----------------------------------------------------------------------
+ Fetch the hostname of the current system and put it in pine struct
+
+ Args: ps -- The pine structure to put the hostname, etc in
+
+ Result: hostname, localdomain, userdomain and maildomain are set
+
+
+** Pine uses the following set of names:
+ hostname - The fully-qualified hostname. Obtained with
+ gethostbyname() which reads /etc/hosts or does a DNS
+ lookup. This may be blank.
+ localdomain - The domain name without the host. Obtained from the
+ above hostname if it has a "." in it. Removes first
+ segment. If hostname has no "." in it then the hostname
+ is used. This may be blank.
+ userdomain - Explicitly configured domainname. This is read out of the
+ global pine.conf or user's .pinerc. The user's entry in the
+ .pinerc overrides.
+
+** Pine has the following uses for such names:
+
+ 1. On outgoing messages in the From: line
+ Uses userdomain if there is one. If not uses, uses
+ hostname unless Pine has been configured to use localdomain.
+
+ 2. When expanding/fully-qualifying unqualified addresses during
+ composition
+ (same as 1)
+
+ 3. When expanding/fully-qualifying unqualified addresses during
+ composition when a local entry in the password file exists for
+ name.
+ If no userdomain is given, then this lookup is always done
+ and the hostname is used unless Pine's been configured to
+ use the localdomain. If userdomain is defined, it is used,
+ but no local lookup is done. We can't assume users on the
+ local host are valid in the given domain (and, for simplicity,
+ have chosen to ignore the cases userdomain matches localdomain
+ or localhost). Setting user-lookup-even-if-domain-mismatch
+ feature will tell pine to override this behavior and perform
+ the local lookup anyway. The problem of a global "even-if"
+ set and a .pinerc-defined user-domain of something odd causing
+ the local lookup, but this will only effect the personal name,
+ and is not judged to be a significant problem.
+
+ 4. In determining if an address is that of the current pine user for
+ formatting index and filtering addresses when replying
+ If a userdomain is specified the address must match the
+ userdomain exactly. If a userdomain is not specified or the
+ userdomain is the same as the hostname or domainname, then
+ an address will be considered the users if it matches either
+ the domainname or the hostname. Of course, the userid must
+ match too.
+
+ 5. In Message ID's
+ The fully-qualified hostname is always users here.
+
+
+** Setting the domain names
+ To set the domain name for all Pine users on the system to be
+different from what Pine figures out from DNS, set the domain name in
+the "user-domain" variable in pine.conf. To set the domain name for an
+individual user, set the "user-domain" variable in his .pinerc.
+The .pinerc setting overrides any other setting.
+ ----*/
+int
+init_hostname(struct pine *ps)
+{
+ char hostname[MAX_ADDRESS+1], domainname[MAX_ADDRESS+1];
+
+ getdomainnames(hostname, sizeof(hostname)-1,
+ domainname, sizeof(domainname)-1);
+
+ if(ps->hostname)
+ fs_give((void **)&ps->hostname);
+
+ ps->hostname = cpystr(hostname);
+
+ if(ps->localdomain)
+ fs_give((void **)&ps->localdomain);
+
+ ps->localdomain = cpystr(domainname);
+ ps->userdomain = NULL;
+
+ if(ps->VAR_USER_DOMAIN && ps->VAR_USER_DOMAIN[0]){
+ ps->maildomain = ps->userdomain = ps->VAR_USER_DOMAIN;
+ }else{
+#if defined(DOS) || defined(OS2)
+ if(ps->VAR_USER_DOMAIN)
+ ps->blank_user_domain = 1; /* user domain set to null string! */
+
+ ps->maildomain = ps->localdomain[0] ? ps->localdomain : ps->hostname;
+#else
+ ps->maildomain = strucmp(ps->VAR_USE_ONLY_DOMAIN_NAME, "yes")
+ ? ps->hostname : ps->localdomain;
+#endif
+ }
+
+ /*
+ * Tell c-client what domain to use when completing unqualified
+ * addresses it finds in local mailboxes. Remember, it won't
+ * affect what's to the right of '@' for unqualified addresses in
+ * remote folders...
+ */
+ mail_parameters(NULL, SET_LOCALHOST, (void *) ps->maildomain);
+ if(F_OFF(F_QUELL_MAILDOMAIN_WARNING, ps) && !strchr(ps->maildomain, '.')){
+ snprintf(tmp_20k_buf, SIZEOF_20KBUF, _("Incomplete maildomain \"%s\"."),
+ ps->maildomain);
+ init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
+ strncpy(tmp_20k_buf,
+ _("Return address in mail you send may be incorrect."), SIZEOF_20KBUF);
+ tmp_20k_buf[SIZEOF_20KBUF-1] = '\0';
+ init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
+ }
+
+ dprint((1,"User domain name being used \"%s\"\n",
+ ps->userdomain == NULL ? "" : ps->userdomain));
+ dprint((1,"Local Domain name being used \"%s\"\n",
+ ps->localdomain ? ps->localdomain : "?"));
+ dprint((1,"Host name being used \"%s\"\n",
+ ps->hostname ? ps->hostname : "?"));
+ dprint((1,
+ "Mail Domain name being used (by c-client too) \"%s\"\n",
+ ps->maildomain ? ps->maildomain : "?"));
+
+ if(!ps->maildomain || !ps->maildomain[0]){
+#if defined(DOS) || defined(OS2)
+ if(ps->blank_user_domain)
+ return(0); /* prompt for this in send.c:dos_valid_from */
+#endif
+ fprintf(stderr, _("No host name or domain name set\n"));
+ return(-1);
+ }
+ else
+ return(0);
+}
+
+
+/*----------------------------------------------------------------------
+ Make sure the default save folders exist in the default
+ save context.
+ ----*/
+void
+init_save_defaults(void)
+{
+ CONTEXT_S *save_cntxt;
+
+ if(!ps_global->VAR_DEFAULT_FCC ||
+ !*ps_global->VAR_DEFAULT_FCC ||
+ !ps_global->VAR_DEFAULT_SAVE_FOLDER ||
+ !*ps_global->VAR_DEFAULT_SAVE_FOLDER)
+ return;
+
+ if(!(save_cntxt = default_save_context(ps_global->context_list)))
+ save_cntxt = ps_global->context_list;
+
+ if(!(folder_exists(save_cntxt, ps_global->VAR_DEFAULT_FCC) & FEX_ISFILE))
+ context_create(save_cntxt, NULL, ps_global->VAR_DEFAULT_FCC);
+
+ if(!(folder_exists(save_cntxt, ps_global->VAR_DEFAULT_SAVE_FOLDER) &
+ FEX_ISFILE))
+ context_create(save_cntxt, NULL, ps_global->VAR_DEFAULT_SAVE_FOLDER);
+
+ free_folder_list(save_cntxt);
+}
+
+
+/*----------------------------------------------------------------------
+ Put sent-mail files in date order
+
+ Args: a, b -- The names of two files. Expects names to be sent-mail-mmm-yy
+ Other names will sort in order and come before those
+ in above format.
+ ----*/
+int
+compare_sm_files(const qsort_t *aa, const qsort_t *bb)
+{
+ struct sm_folder *a = (struct sm_folder *)aa,
+ *b = (struct sm_folder *)bb;
+
+ if(a->month_num == -1 && b->month_num == -1 && a->name && b->name)
+ return(strucmp(a->name, b->name));
+ if(a->month_num == -1) return(-1);
+ if(b->month_num == -1) return(1);
+
+ return(a->month_num - b->month_num);
+}
+
+
+
+/*----------------------------------------------------------------------
+ Create an ordered list of sent-mail folders and their month numbers
+
+ Args: dir -- The directory to find the list of files in
+
+ Result: Pointer to list of files is returned.
+
+This list includes all files that start with "sent-mail", but not "sent-mail"
+itself.
+ ----*/
+struct sm_folder *
+get_mail_list(CONTEXT_S *list_cntxt, char *folder_base)
+{
+ register struct sm_folder *sm = NULL;
+ struct sm_folder *sml = NULL;
+ char *filename;
+ int i, folder_base_len;
+ int max_files;
+ char searchname[MAXPATH+1];
+
+ if((folder_base_len = strlen(folder_base)) == 0 || !list_cntxt){
+ sml = (struct sm_folder *) fs_get(sizeof(struct sm_folder));
+ memset((void *)sml, 0, sizeof(struct sm_folder));
+ return(sml);
+ }
+
+#ifdef DOS
+ if(*list_cntxt->context != '{'){ /* NOT an IMAP collection! */
+ snprintf(searchname, sizeof(searchname), "%4.4s*", folder_base);
+ folder_base_len = strlen(searchname) - 1;
+ }
+ else
+#endif
+ snprintf(searchname, sizeof(searchname), "%.*s*", sizeof(searchname)-2, folder_base);
+
+ build_folder_list(NULL, list_cntxt, searchname, NULL, BFL_FLDRONLY);
+
+ max_files = MIN(MAX(0, folder_total(FOLDERS(list_cntxt))), 5000);
+ sml = sm = (struct sm_folder *) fs_get(sizeof(struct sm_folder)*(max_files+1));
+ memset((void *)sml, 0, sizeof(struct sm_folder) * (max_files+1));
+
+ for(i = 0; i < folder_total(FOLDERS(list_cntxt)); i++){
+ filename = folder_entry(i, FOLDERS(list_cntxt))->name;
+#ifdef DOS
+ if(struncmp(filename, folder_base, folder_base_len) == 0
+ && strucmp(filename, folder_base)){
+
+ if(*list_cntxt->context != '{'){
+ int j;
+ for(j = 0; j < 4; j++)
+ if(!isdigit((unsigned char)filename[folder_base_len + j]))
+ break;
+
+ if(j < 4) /* not proper date format! */
+ continue; /* keep trying */
+ }
+#else
+#ifdef OS2
+ if(strnicmp(filename, folder_base, folder_base_len) == 0
+ && stricmp(filename, folder_base)){
+#else
+ if(strncmp(filename, folder_base, folder_base_len) == 0
+ && strcmp(filename, folder_base)){
+#endif
+#endif
+ sm->name = cpystr(filename);
+#ifdef DOS
+ if(*list_cntxt->context != '{'){ /* NOT an IMAP collection! */
+ sm->month_num = (sm->name[folder_base_len] - '0') * 10;
+ sm->month_num += sm->name[folder_base_len + 1] - '0';
+ }
+ else
+#endif
+ sm->month_num = month_num(sm->name + (size_t)folder_base_len + 1);
+ sm++;
+ if(sm >= &sml[max_files])
+ break; /* Too many files, ignore the rest ; shouldn't occur */
+ }
+ }
+
+ /* anything to sort?? */
+ if(sml->name && *(sml->name) && (sml+1)->name && *((sml+1)->name)){
+ qsort(sml,
+ sm - sml,
+ sizeof(struct sm_folder),
+ compare_sm_files);
+ }
+
+ return(sml);
+}
+
+
+
+int
+check_prune_time(time_t *now, struct tm **tm_now)
+{
+ char tmp[50];
+
+ *now = time((time_t *) 0);
+ *tm_now = localtime(now);
+
+ /*
+ * If the last time we did this is blank (as if pine's run for
+ * first time), don't go thru list asking, but just note it for
+ * the next time...
+ */
+ if(ps_global->VAR_LAST_TIME_PRUNE_QUESTION == NULL){
+ ps_global->last_expire_year = (*tm_now)->tm_year;
+ ps_global->last_expire_month = (*tm_now)->tm_mon;
+ snprintf(tmp, sizeof(tmp), "%d.%d", ps_global->last_expire_year,
+ ps_global->last_expire_month + 1);
+ set_variable(V_LAST_TIME_PRUNE_QUESTION, tmp, 1, 1, Main);
+ return(0);
+ }
+
+ if(ps_global->last_expire_year != -1 &&
+ ((*tm_now)->tm_year < ps_global->last_expire_year ||
+ ((*tm_now)->tm_year == ps_global->last_expire_year &&
+ (*tm_now)->tm_mon <= ps_global->last_expire_month)))
+ return(0);
+
+ return(1);
+}
+
+
+int
+first_run_of_month(void)
+{
+ time_t now;
+ struct tm *tm_now;
+
+ now = time((time_t *) 0);
+ tm_now = localtime(&now);
+
+ if(ps_global->last_expire_year == -1 ||
+ (tm_now->tm_year < ps_global->last_expire_year ||
+ (tm_now->tm_year == ps_global->last_expire_year &&
+ tm_now->tm_mon <= ps_global->last_expire_month)))
+ return(0);
+
+ return(1);
+}
+
+
+int
+first_run_of_year(void)
+{
+ time_t now;
+ struct tm *tm_now;
+
+ now = time((time_t *) 0);
+ tm_now = localtime(&now);
+
+ if(ps_global->last_expire_year == -1 ||
+ (tm_now->tm_year <= ps_global->last_expire_year))
+ return(0);
+
+ return(1);
+}
+
+
+/*
+ * prune_move_folder - rename folder in context and delete old copy
+ * Returns -1 if unsuccessful.
+ */
+int
+prune_move_folder(char *oldpath, char *newpath, CONTEXT_S *prune_cntxt)
+{
+ char spath[MAXPATH+1];
+
+ strncpy(spath, oldpath, sizeof(spath)-1);
+ spath[sizeof(spath)-1] = '\0';
+
+ /*--- User says OK to rename ---*/
+ dprint((5, "rename \"%s\" to \"%s\"\n",
+ spath ? spath : "?", newpath ? newpath : "?"));
+ q_status_message1(SM_ORDER, 1, 3,
+ /* TRANSLATORS: arg is a filename */
+ _("Renaming \"%s\" at start of month"),
+ pretty_fn(spath ? spath : "?"));
+
+ if(!context_rename(prune_cntxt, NULL, spath, newpath)){
+ q_status_message2(SM_ORDER | SM_DING, 3, 4,
+ /* TRANSLATORS: 1st arg is filename, 2nd is error message */
+ _("Error renaming \"%s\": %s"),
+ pretty_fn(spath ? spath : "?"),
+ error_description(errno));
+ dprint((1, "Error renaming %s to %s: %s\n",
+ spath ? spath : "?", newpath ? newpath : "?",
+ error_description(errno)));
+ display_message('x');
+ return -1;
+ }
+
+ context_create(prune_cntxt, NULL, spath);
+
+ return 0;
+}