home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Unix System Administration Handbook 1997 October
/
usah_oct97.iso
/
news
/
nn.tar
/
nn-6.5.1
/
folder.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-04-29
|
12KB
|
578 lines
/*
* (c) Copyright 1990, Kim Fabricius Storm. All rights reserved.
*
* Folder handling
*/
/*#include <errno.h>*/
#include "config.h"
#include "articles.h"
#include "news.h"
#include "keymap.h"
#include "nn_term.h"
#include "menu.h"
#include <pwd.h>
/* folder.c */
static char *tilde_expansion __APROTO((char **srcp, int compl));
static folder_header __APROTO((void));
import char *home_directory;
import int current_folder_type;
import int use_mail_folders;
import int use_mmdf_folders;
extern int bypass_consolidation;
export int dont_sort_folders = 0;
export char *folder_directory = NULL;
export int folder_rewrite_trace = 1;
export char *backup_folder_path = "BackupFolder~";
export int keep_backup_folder = 1;
export int convert_folder_mode = 0; /* ignore folder's format on rewrite */
export int consolidated_manual = 0;
export int ignore_fancy_select = 0; /* turn off select features for folders */
import int fmt_linenum;
import char *header_lines;
extern struct passwd *getpwnam();
/*
* expand ~[user][/...] form
* src ptr is advanced to last char of user name.
*/
static char *tilde_expansion(srcp, compl)
char **srcp;
int compl;
{
struct passwd *pwd;
register char *name = *srcp;
register char *tail, x;
tail = ++name; /* skip ~ */
while (*tail && isascii(*tail) && !isspace(*tail) && *tail != '/')
tail++;
if (compl && *tail != '/') return NULL;
if (tail == name) return home_directory;
*srcp = tail - 1;
x = *tail;
*tail = NUL;
pwd = getpwnam(name);
if (pwd == NULL && !compl)
msg("User %s not found", name);
*tail = x;
return (pwd == NULL) ? NULL : pwd->pw_dir;
}
/*
* file name completion and expansion
*
* expand_mode bits:
* 1: expand path names
* 2: don't expand $N
* 4: don't expand any $? (but $(...) is expanded)
* 8: don't complain about ~... (shell will do that)
* 10: doing filename completion
*/
int
expand_file_name(dest, src, expand_mode)
char *dest, *src;
int expand_mode;
{
register char *cp, *dp, c;
int parse, remap;
char *cur_grp, *cur_art;
cur_grp = current_group ? current_group->group_name : NULL;
cur_art = (group_file_name && *group_file_name) ? group_path_name : NULL;
for (dp = dest, parse = 1; (c = *src); src++) {
if (parse) {
if ((expand_mode & 1) && c == '+') {
if (folder_directory == NULL) {
if (!(cp = getenv("FOLDER")))
cp = FOLDER_DIRECTORY;
folder_directory = home_relative(cp);
}
cp = folder_directory;
goto cp_str;
}
if ((expand_mode & 1) && c == '~') {
if ((cp = tilde_expansion(&src, (expand_mode & 0x10))) == NULL) {
return 0;
}
cp_str:
while (*cp) *dp++ = *cp++;
if (dp[-1] != '/') *dp++ = '/';
goto no_parse;
}
if ((expand_mode & 4) == 0 &&
cur_art && c == '%' && (src[1] == ' ' || src[1] == NUL)) {
cp = cur_art;
while (*cp) *dp++ = *cp++;
goto no_parse;
}
}
if (c == '$' && src[1] == '(') {
char envar[64];
for (src += 2, cp = envar; (c = *src) != NUL && c != ')'; src++)
*cp++ = c;
*cp = NUL;
if (cp != envar) {
if ((cp = getenv(envar)) != NULL)
while (*cp) *dp++ = *cp++;
else {
msg("Environment variable $(%s) not set", envar);
return 0;
}
}
goto no_parse;
}
if ((expand_mode & 4) == 0 && c == '$' && !isalnum(src[2])) {
remap = 0;
cp = NULL;
switch (src[1]) {
case 'A':
cp = cur_art;
break;
case 'F':
cp = cur_grp;
remap = 1;
break;
case 'G':
cp = cur_grp;
break;
case 'L':
if ((cp = strrchr(cur_grp, '.')))
cp++;
else
cp = cur_grp;
break;
case 'N':
if (expand_mode & 2) goto copy;
if (cur_art) cp = group_file_name;
if (cp == NULL) goto copy;
break;
default:
goto copy;
}
src++;
if (!cp) {
msg("$%c not defined on this level", c);
return 0;
}
while (*cp)
if (remap && *cp == '.')
cp++, *dp++ = '/';
else
*dp++ = *cp++;
goto no_parse;
}
if (c == '/')
#ifdef ALLOW_LEADING_DOUBLE_SLASH
if (dp != &dest[1])
#endif
if (dp != dest && dp[-1] == '/') goto no_parse;
copy:
*dp++ = c;
parse = isspace(c);
continue;
no_parse:
parse = 0;
}
*dp = NUL;
return 1;
}
int
file_completion(path, index)
char *path;
int index;
{
static dir_in_use = 0;
static char *head, *tail = NULL;
static int tail_offset;
char nbuf[FILENAME], buffer[FILENAME];
char *dir, *base;
if (path) {
if (dir_in_use) {
close_directory();
dir_in_use = 0;
}
if (index < 0) return 0;
head = path;
tail = path + index;
}
if (!dir_in_use) {
path = head;
*tail = NUL;
if (*path == '|') return -1; /* no completion for pipes */
if (*path == '+' || *path == '~') {
if (!expand_file_name(nbuf, path, 0x11))
return 0; /* no completions */
} else
strcpy(nbuf, path);
if ((base = strrchr(nbuf, '/'))) {
if (base == nbuf) {
dir = "/";
base++;
} else {
*base++ = NUL;
dir = nbuf;
}
} else {
base = nbuf;
dir = ".";
}
tail_offset = strlen(base);
dir_in_use = list_directory(dir, base);
return dir_in_use;
}
if (index)
return compl_help_directory();
if (!next_directory(buffer, 1)) return 0;
strcpy(tail, buffer+tail_offset);
return 1;
}
static int cancel_count;
void
fcancel(ah)
article_header *ah;
{
if (ah->attr == A_CANCEL) {
cancel_count--;
ah->attr = 0;
} else {
cancel_count++;
ah->attr = A_CANCEL;
}
}
static int
folder_header()
{
so_printxy(0, 0, "Folder: %s", current_group->group_name);
return 1; /* number of header lines */
}
/*
* mode values:
* 0: normal folder or digest
* 1: online manual
* 2: mailbox
*/
int
folder_menu(path, mode)
char *path;
int mode;
{
FILE *folder;
register article_header *ah;
news_header_buffer dgbuf;
char buffer[256];
int more, length, re, menu_cmd, was_raw;
memory_marker mem_marker;
group_header fake_group;
int cc_save;
char folder_name[FILENAME], folder_file[FILENAME];
int orig_layout;
char *orig_hdr_lines;
orig_layout = fmt_linenum;
orig_hdr_lines = header_lines;
strcpy(folder_name, path);
fake_group.group_name = folder_name;
if (!expand_file_name(folder_file, folder_name, 1)) return ME_NO_REDRAW;
fake_group.archive_file = path = folder_file;
fake_group.next_group = fake_group.prev_group = NULL;
fake_group.group_flag = G_FOLDER | G_FAKED;
fake_group.master_flag = 0;
fake_group.save_file = NULL;
current_group = NULL;
init_group(&fake_group);
folder = open_file(path, OPEN_READ);
if (folder == NULL) {
msg("%s not found", path);
return ME_NO_REDRAW;
}
switch (get_folder_type(folder)) {
case 0:
msg("Reading: %-.65s", path); break;
case 1:
case 2:
msg("Reading %s folder: %-.50s",
current_folder_type==1 ? "mail" : "mmdf", path);
break;
default:
msg("Folder is empty");
fclose(folder);
return ME_NO_REDRAW;
}
rewind(folder);
was_raw = no_raw();
s_keyboard = 0;
current_group = &fake_group;
mark_memory(&mem_marker);
ah = alloc_art();
more = 1;
while (more && (more = get_digest_article(folder, dgbuf)) >= 0) {
if (s_keyboard) break;
ah->a_number = 0;
ah->flag = A_FOLDER;
ah->attr = 0;
ah->lines = digest.dg_lines;
ah->hpos = digest.dg_hpos;
ah->fpos = digest.dg_fpos;
ah->lpos = digest.dg_lpos;
if (digest.dg_from) {
length = pack_name(buffer, digest.dg_from, NAME_LENGTH);
ah->sender = alloc_str(length);
strcpy(ah->sender, buffer);
ah->name_length = length;
if (mode == 1) fold_string(ah->sender);
} else {
ah->sender = "";
ah->name_length = 0;
}
if (digest.dg_subj) {
length = pack_subject(buffer, digest.dg_subj, &re, 255);
ah->replies = re;
ah->subject = alloc_str(length);
strcpy(ah->subject, buffer);
ah->subj_length = length;
if (mode == 1 && length > 1) fold_string(ah->subject + 1);
} else {
ah->replies = 0;
ah->subject = "";
ah->subj_length = 0;
}
ah->t_stamp = digest.dg_date ? pack_date(digest.dg_date) : 0;
add_article(ah);
ah = alloc_art();
}
fclose(folder);
if (s_keyboard) {
menu_cmd = ME_NO_REDRAW;
} else
if (n_articles == 0) {
msg("Not a folder (no article header)");
menu_cmd = ME_NO_REDRAW;
} else {
if (n_articles > 1) {
clrdisp();
prompt_line = 2;
if (mode == 0 && !dont_sort_folders)
sort_articles(-1);
else if (mode == 1) {
article_number n;
for (n = 0; n < n_articles; n++) {
ah = articles[n];
if (n == 0)
ah->flag |= A_ROOT_ART;
else if (strcmp(ah->sender, articles[n-1]->sender) == 0)
articles[n-1]->flag |= A_NEXT_SAME;
else
ah->flag |= A_ROOT_ART;
}
bypass_consolidation = consolidated_manual ? 2 : 1;
} else
no_sort_articles();
} else
no_sort_articles();
cc_save = cancel_count;
cancel_count = 0;
if (mode == 1) {
fmt_linenum = -1;
header_lines = "*";
}
reenter_menu:
ignore_fancy_select = 1;
menu_cmd = menu(folder_header);
ignore_fancy_select = 0;
if (mode == 0 && cancel_count) {
register article_number cur;
cancel_count = 0;
for (cur = 0; cur < n_articles; cur++) {
if (articles[cur]->attr == A_CANCEL) cancel_count++;
}
}
if (mode == 0 && cancel_count) {
clrdisp();
tprintf("\rFolder: %s\n\rFile: %s\n\n\r", folder_name, folder_file);
if (cancel_count == n_articles)
tprintf("Cancel all articles and remove folder? ");
else
tprintf("Remove %d article%s from folder? ",
cancel_count, plural((long)cancel_count));
fl;
switch (yes(1)) {
case 1:
tprintf("\n\n");
if (cancel_count == n_articles) {
if (unlink(group_path_name) < 0 &&
nn_truncate(group_path_name, (off_t)0) < 0) {
tprintf("\rCould not unlink %s\n\r", group_path_name);
any_key(0);
}
} else
rewrite_folder();
break;
case 0:
break;
default:
goto reenter_menu;
}
}
cancel_count = cc_save;
}
release_memory(&mem_marker);
if (fmt_linenum == -1) {
fmt_linenum = orig_layout;
header_lines = orig_hdr_lines;
}
if (was_raw) nn_raw();
return menu_cmd;
}
void
rewrite_folder()
{
register FILE *src, *dst;
char *oldfile;
register int c;
register long cnt;
register article_header *ah, **ahp;
register article_number n;
if (strchr(backup_folder_path, '/'))
oldfile = backup_folder_path;
else
oldfile = relative(nn_directory, backup_folder_path);
if (move_file(group_path_name, oldfile, 1) < 0) {
tprintf("\r\n\nCannot backup folder in %s\n", oldfile);
goto confirm;
}
if ((src = open_file(oldfile, OPEN_READ)) == NULL) {
tprintf("\rCannot open %s\n\r", oldfile);
goto move_back;
}
if ((dst = open_file(group_path_name, OPEN_CREATE)) == NULL) {
fclose(src);
tprintf("\rCannot create %s\n\r", group_path_name);
goto move_back;
}
sort_articles(-2);
tprintf("\rCompressing folder...\n\r"); fl;
get_folder_type(src);
for (ahp = articles, n = n_articles; --n >= 0; ahp++) {
ah = *ahp;
cnt = ah->lpos - ah->hpos;
if (folder_rewrite_trace)
tprintf("%s\t%s (%ld-%ld=%ld)\n\r",
ah->attr == A_CANCEL ? "CANCEL" : "KEEP",
ah->subject, (long)(ah->hpos), (long)(ah->lpos), cnt);
if (ah->attr == A_CANCEL) continue;
fseek(src, ah->hpos, 0);
mailbox_format(dst, -1);
while (--cnt >= 0) {
if ((c = getc(src)) == EOF) break;
putc(c, dst);
}
mailbox_format(dst, 0);
}
fclose(src);
if (fclose(dst) == EOF) goto move_back;
if (!keep_backup_folder) unlink(oldfile);
if (folder_rewrite_trace) goto confirm;
return;
move_back:
if (move_file(oldfile, group_path_name, 2) == 0)
tprintf("Cannot create new file -- Folder restored\n\r");
else
tprintf("Cannot create new file\n\n\rFolder saved in %s\n\r", oldfile);
confirm:
any_key(0);
}