#pragma save_binary
#define MAX_MESGS 50
#define PAGE 20
// Intermud Mailer by Huthar@portals
// Touched up by Buddha@TMI for his own mudlib (name unknown).
// Zak 930127 Added 'Q' (quit no changes), 's' (save note, mark for
// delete, 'c' (save note, leave alone)
// Watcher 930327 added 'more' reading of the mail
// Zak 930411 fixed null subject bugs, added 'x' (same as 'q').
//
// Zak 930413 V2.1: rewrote most of it, basically to use mappings
// added '$' (resync folder), 'n' (set current msg #)
//
// Zak 930502 V2.2: added 'p' (current message info). Now need a space
// for 1st arg (excess chars chopped off).
// Zak 930601 improved group handling.
// fixed a lot of the 'reply' code.
// Zak 930603 added do_resync, put in safety valve for null 'from' entry
//
// Zak 930605 upped to v2.5 (why not? :)
// Zak 930606 cleaned up text, refer to mail as `items' not `messages'.
// Zak 930622 fixed reply text.. now puts `<from> writes:' now
// Zak 930703 to save mail, now need a home dir. also, default
// directory for saving is ~ NOT $CWD.
// Zak 930704 incorporated Dainia@TMI's personal group code. Sets
// `using_mail' if in mailer. Implemented forwarding
// (idea was Huthar's)
// Zak 930705 fixed `owner' bugs, display more accurate illegal note #
// mesg. Display prompt after edit abort().
// Zak 930708 minor bugs fixed: cmsg not reset between resync
// using_mail not being reset within `frm'
// Zak, 930714 check for null entries in TO/CC fields & ignore them.
// Grendel, 930809 Put a \\n after the subject when saving to a file.
// Grendel, 930904 Fixed a bug in mailing to remote groups
// Inspiral, 931230 added support for udp mail system.
// Inspiral, 940111 'w' option to save to file without headers
// Blue, 941027 Changed to allow saving to current directory,
// not just home. Added extra security there,
// just to be on the safe side. It was possible
// before anyway, so there's no extra leak - just
// extra convenience.
// Also limited headers display to PAGE [20] lines
// at a time.
// Blue, 941031 Added 'mail_headers' env variable for the number
// of headers to display in a page.
// Leto 941109 Changed status to int.
#include <mailer.h>
#include <config.h>
#include <mudlib.h>
#include <uid.h>
#include <commands.h>
#include <daemons.h>
#include <net/daemons.h>
#include <net/services.h>
#include <net/macros.h>
inherit SECURE_OBJECT;
static int cmsg, maxmsg, start_flag, in_mailer, quitmailflag;
static string owner, tmpfilename;
static mapping newmsg;
static string mail_a_file;
mapping my_groups;
mapping *mailbox;
// contains:
// "from", "date", "cc", "subject", "message", "flags", "to"
static void parse_mailcmd( string cmd );
void get_text();
static void mail( string arg );
void
create() {
seteuid( ROOT_UID );
set( "id", ({ "mailer" }) );
mailbox = ({ });
my_groups = ([ ]);
} // create
void
init() {
int i, j;
if( in_mailer ) {
remove();
destruct( this_object() );
return;
}
my_groups = ([ ]);
owner = ( string ) this_player() -> link_data( "name" );
if (!owner) {
remove();
destruct(this_object());
return;
}
tmpfilename = temp_file( owner, this_player() ) + ".m";
restore_object( user_mbox_file( owner ), 1 );
maxmsg = sizeof( mailbox );
i = maxmsg;
if( !i ) {
cmsg = 0;
return;
}
for( cmsg = - 1, i = 0; i <maxmsg; i++ )
if( !( mailbox[i]["flags"]&MAIL_READ ) ) {
cmsg = i;
break;
}
if( cmsg == - 1 ) {
cmsg = maxmsg - 1;
if( cmsg < 0 )
cmsg = 0;
}
this_player() -> set( "using_mail", 1 );
} // init
string
get_time( int t ) {
return extract( ctime( t ), 0, 9 );
} // get_time
string
implode_caps( string *a ) {
int i;
string temp;
i = sizeof( a );
while( i-- )
if( a[i] ) {
temp = "";
if( sscanf( a[i], "%s@%s", a[i], temp ) )
temp = "@" + nntoh( temp );
a[i] = capitalize( a[i] ) + temp;
}
return( implode( a, ", " ) );
} // implode_caps
int
validate_num( string str ) {
int num;
if( str == "" )
num = cmsg + 1;
else
sscanf( str, "%d", num );
if( num < 1 || num> maxmsg )
num = 0; // force num to -1 on exit
return--num;
} // validate_num
int
inccmsg() {
if( !maxmsg )
cmsg = 0;
else if( ++cmsg >= maxmsg )
cmsg = maxmsg - 1;
return cmsg;
} // inccmsg
int *numlist( string str ) {
mixed *ret, *tmp;
int i, j, x, y;
ret = ({ });
str = replace_string( str, " ", "" );
tmp = explode( str, "," );
i = sizeof( tmp );
while( i-- ) {
if( sscanf( tmp[i], "%d-%d", x, y ) == 2 ) {
while( x <= y ) {
ret += ({ x });
x++;
}
}
else
ret += ({ to_int( tmp[i] ) });
}
ret = uniq_array( ret );
return ret;
}
static
varargs void
headers( int start, int newonly ) {
int i, cnt, no_of_h;
if( !maxmsg ) {
printf( "No mail.\n" );
cmsg = 0;
return;
}
cnt = 0;
no_of_h = this_player()->getenv( "mail_headers" );
if (!no_of_h || !intp(no_of_h))
no_of_h = PAGE;
for ( i = start; (i < maxmsg) && (cnt < no_of_h); i++ ) {
if( newonly && ( mailbox[i]["flags"]&MAIL_READ ) )
continue;
cnt++;
if( !mailbox[i]["from"] ) {
mailbox[i]["flags"] |= OWNERDELETED;
continue;
}
if( !mailbox[i]["idx"] ) mailbox[i]["idx"] = mailbox[i]["date"] + "";
printf( "%s%s%2d %-30s (%s) %s\n",
mailbox[i]["flags"]&MAIL_READ ? " " : "U",
i == cmsg ?( mailbox[i]["flags"] & OWNERDELETED ? "<" : ">" )
:( mailbox[i]["flags"] & OWNERDELETED ? "*" : " " ),
i + 1,
capitalize( mailbox[i]["from"] ),
intp( mailbox[i]["date"] )?
ctime( mailbox[i]["date"] )[0..9] : mailbox[i]["date"][0..9],
mailbox[i]["subject"][0..25] );
}
if( newonly == 2 && !cnt ) // for 'from' command
printf( "No new mail.\n" );
} // headers
static
string *
expand_to( string *raw_list ) {
int i, j;
string a, b, lcname, *zeta;
mapping grps, rtn;
rtn = ([ ]);
grps = ( mapping ) GROUP_OB -> query_groups();
raw_list -= ({ "" });
raw_list -= ({ 0 });
i = sizeof( raw_list );
while( i-- ) {
if( !raw_list[i] )
continue;
lcname = lower_case( raw_list[i] );
if( !undefinedp( rtn[lcname] ) )
continue;
if( sscanf( lcname, "%s@%s", a, b ) == 2 ) {
b = nntoh( b );
if( !(int) DNS_MASTER -> dns_mudp( b ) ||
!(int) DNS_MASTER -> query_named_service( b, "mail_q" ) ) {
printf( "Cannot locate mud or mud doesn't support DNS mail: %s.\n",
b );
printf( "Aborting send to %s@%s.\n", a, b );
continue;
}
if( !a || a == "" )
printf( "You must specify a username at the remote site.\n" );
else
rtn[lcname] = 1;
} else {
if( sscanf( raw_list[i], "(%s)", a ) )
lcname = a;
if( !user_exists( lcname ) ) {
if( !undefinedp( grps[lcname] ) ) {
lcname = "(" + lcname + ")";
if( undefinedp( rtn[lcname] ) )
rtn[lcname] = 1;
} else {
zeta = my_groups[lcname];
if( undefinedp( zeta ) || !sizeof( zeta ) )
printf( "No such user or group: %s.\n", lcname );
else {
j = sizeof( zeta );
while( j-- )
rtn[zeta[j]] = 1;
}
}
}
else
rtn[lcname] = 1;
}
}
return( keys( rtn ) );
} // expand_to
void
prompt() {
if( maxmsg )
printf( "[%d of %d]& ", cmsg + 1, maxmsg );
else
printf( "& " );
} // prompt
static
varargs void
do_mail( string cmd ) {
in_mailer = 1;
if( cmd && cmd != "" ) {
quitmailflag = 1;
mail( cmd );
return;
}
if( !in_edit( this_player() ) && !in_input( this_player() ) )
prompt();
input_to( "parse_mailcmd" );
} // do_mail
static
void
get_cc( string arg ) {
int i, max;
string *rtn;
string tmpfile;
arg = replace_string( arg, ",", " " );
if( !pointerp( newmsg["cc"] ) ) newmsg["cc"] = ({ });
newmsg["cc"] = expand_to( uniq_array( newmsg["cc"] + explode( arg, " " ) ) );
rtn = ( string * ) MAILBOX_D -> send_mail( newmsg );
max = sizeof( rtn );
if( max )
printf( "Mailing to: %s\n", implode_caps( rtn ) );
else {
tmpfile = sprintf( "%s/%s.dead-letter", TMP_DIR, owner );
printf( "No recipients found. Appending to: '%s'\n", tmpfile );
write_file( tmpfile, newmsg["message"] + "\n" );
}
if( quitmailflag )
{
MAILBOX_D -> flush_files( my_groups );
this_player() -> delete( "using_mail" );
destruct( this_object() );
}
else
do_mail();
} // get_cc
static
void
get_to( string arg ) {
if( arg == "" ) {
printf( "No users/groups specified.\n" );
do_mail();
return;
}
newmsg = ([ ]);
arg = replace_string( arg, ",", " " );
newmsg["from"] = capitalize( owner );
newmsg["date"] = time();
newmsg["to"] = expand_to( explode( arg, " " ) );
if( !sizeof( newmsg["to"] ) ) {
if( quitmailflag ) {
this_player() -> delete( "using_mail" );
destruct( this_object() );
}
else
do_mail();
return;
}
newmsg["cc"] = ({ });
if( !mail_a_file ) {
printf( "Subject: " );
input_to( "get_subject" );
}
else this_object() -> get_subject();
} // get_to
static
void
mail( string arg ) {
sscanf( arg, "%s<%s", arg, mail_a_file );
if( stringp( mail_a_file ) && strlen( mail_a_file ) ) {
mail_a_file = replace_string( mail_a_file, " ", "" );
mail_a_file = resolv_path( "cwd", mail_a_file );
if( !file_exists( mail_a_file ) || !master()->valid_read( mail_a_file,
geteuid( this_player() ), "read_file" ) ) {
write( "File: " + identify( mail_a_file ) +
" does not exist. Continuing.\n" );
mail_a_file = 0;
}
}
else mail_a_file = 0;
if( arg == "" ) {
printf( "To: " );
input_to( "get_to" );
return;
}
get_to( arg );
} // mail
int
do_from( string arg ) {
if (file_name(previous_object()) != CMD_FROM)
return 0;
start_flag = 0;
init();
cmsg = - 1; // don't print cur message marker in 'frm'
if( arg == "new" )
headers( 0, 2 );
else
// Changed by Dm 15 March 1996 because to_int was unrecognized.
// Changed back after a bit more checking.
headers( to_int(arg) );
in_mailer = 0;
this_player() -> delete( "using_mail" );
destruct( this_object() );
return 1;
} // do_from
static
int
update_box() {
int i, num;
i = maxmsg;
while( i-- ) {
if( mailbox[i]["flags"] & OWNERDELETED ) {
num++;
MAILBOX_D -> remove_message( owner, i );
}
else
MAILBOX_D -> set_flags( owner, i, mailbox[i]["flags"] );
}
return num;
} // update_box
static
void
do_quit( string cmd ) {
int num, size;
if( cmd == "Q" )
printf( "No changes to mailbox.\n" );
else {
num = update_box();
if( !num )
printf( "No items deleted.\n" );
else
printf( "%d item%s deleted.\n", num, ( num == 1 ? "" : "s" ) );
}
if( !adminp(geteuid( this_player() )) &&
(size = sizeof( mailbox ) - num) > MAX_MESGS ) {
printf( "You have %d messages, and our limit is %d.\n"
"Please delete %d message(s) before you quit.\n",
size, MAX_MESGS, size - MAX_MESGS );
do_mail();
return;
}
MAILBOX_D -> flush_files( my_groups );
this_player() -> delete( "using_mail" );
in_mailer = 0;
destruct( this_object() );
return;
} // do_quit
int
done_more() {
do_mail();
return 1;
} // done_more
static
void
get_subject( string sub ) {
int i, max;
if( mail_a_file )
sub = "File: " + mail_a_file;
if( sub == "" ) {
printf( "Null subject line. Hope that's ok.\n" );
sub = "<no subject>";
}
newmsg["subject"] = sub;
printf( "\n\nFrom : %s\nTo : %s",
newmsg["from"], implode_caps( newmsg["to"] ) );
printf( "\nDate : %s\nSubject: %s\n",
ctime( newmsg["date"] ), newmsg["subject"] );
rm( tmpfilename );
if( !mail_a_file )
this_player() -> edit( tmpfilename, "get_text", this_object() );
else {
write( "Inserting file " + identify( mail_a_file ) +
" into message buffer.\n" );
get_text();
}
} // get_subject
void
abort() {
if( previous_object() != find_player( owner ) ) return;
rm( tmpfilename );
if( quitmailflag ) {
this_player() -> delete( "using_mail" );
destruct( this_object() );
return;
}
prompt(); // because abort() is still technically `in_edit()'
do_mail();
} // abort
void
get_text() {
if( previous_object() != find_player( owner ) ) return;
if( mail_a_file )
newmsg["message"] = read_file( mail_a_file );
else
newmsg["message"] = read_file( tmpfilename );
if( !newmsg["message"] || newmsg["message"] == "" )
newmsg["message"] = "Blank message!\n";
rm( tmpfilename );
if( !this_player() -> getenv( "mail_no_cc" ) ) {
printf( "Cc: " );
input_to( "get_cc" );
return;
}
get_cc( "" );
}
static
void
do_header( string arg ) {
int start;
if( arg == "" )
headers( 0 );
else {
if( ( start = validate_num( arg ) ) == - 1 )
printf( "Mail # out of range.\n" );
else
headers( start );
}
} // do_header
static
void
do_setpos( string arg ) {
int p;
if( ( p = validate_num( arg ) ) == - 1 )
printf( "No such item #%s\n", arg );
else {
printf( "Current item set to %d\n", p + 1 );
cmsg = p;
}
} // do_setpos
static
void
read_mail( int num ) {
string tmp_msg, to, cc;
int i, max;
to = cc = "";
max = sizeof( mailbox[num]["to"] );
for( i = 0; i <max; i++ )
to += capitalize( mailbox[num]["to"][i] ) + " ";
max = sizeof( mailbox[num]["cc"] );
if( max ) {
cc = "Cc : ";
for( i = 0; i < max; i++ ) {
if( !mailbox[num]["cc"][i] )
continue;
cc += capitalize( mailbox[num]["cc"][i] ) + " ";
}
cc += "\n";
}
if( !mailbox[num]["from"] )
mailbox[num]["from"] = "Unknown Sender (mailerob)!";
tmp_msg = sprintf(
"Item #%d%s\nTo : %s\n%sFrom : %s\nDate : %s\n"
"Subject: %s\n===================================\n"
"%s\n",
( num + 1 ),
( mailbox[num]["flags"] & OWNERDELETED )? " \t[DELETED]" : "",
to,
cc,
capitalize( mailbox[num]["from"] ),
intp( mailbox[num]["date"] )?
ctime( mailbox[num]["date"] ): mailbox[num]["date"],
mailbox[num]["subject"],
MAILMESG_D -> get_mesg( mailbox[num]["idx"] )
);
this_player() -> more( explode( tmp_msg, "\n" ), 1, "Message #" + ( num + 1 ) );
mailbox[num]["flags"] |= MAIL_READ;
} // read_mail
static
void
do_help( string arg ) {
if( arg == "long" )
this_player() -> more( MAILER_LONG, 1 );
else
this_player() -> more( MAILER_SHORT, 1 );
} // do_help
static
void
delete_mail( string str ) {
int i, num;
int *list;
if( !str || str == "" )
list = ({ "" });
else
list = numlist( str );
i = sizeof( list );
while(i--) {
if( ( num = validate_num( list[i] + "" ) ) == - 1 ) {
printf( "Illegal item value: %d\n", list[i]+1 );
do_mail();
continue;
}
if( mailbox[num]["flags"] & OWNERDELETED ) {
printf( "Item #%d already deleted.\n", num + 1 );
continue;
}
mailbox[num]["flags"] |= OWNERDELETED;
printf( "Item #%d marked for deletion.\n", num + 1 );
}
} // delete_mail
static
void undelete_mail( string str ) {
int num;
if( ( num = validate_num( str ) ) == - 1 ) {
printf( "Illegal item value.\n" );
return;
}
if( !( mailbox[num]["flags"] & OWNERDELETED ) ) {
printf( "Item #%d is not deleted.\n", num + 1 );
return;
}
mailbox[num]["flags"] &= ~OWNERDELETED;
printf( "Item #%d has been restored.\n", num + 1 );
} // undelete_mail
static
void do_reply( string cmd, string numstr ) {
int num, i, max;
if( ( num = validate_num( numstr ) ) == - 1 ) {
printf( "Illegal item number!\n" );
return;
}
newmsg = ([ ]);
if( cmd == "r" ) {
newmsg["to"] = ({ mailbox[num]["from"] });
} else {
newmsg["to"] = uniq_array( ({ mailbox[num]["from"] })
+ mailbox[num]["to"] );
newmsg["cc"] = mailbox[num]["cc"];
}
newmsg["from"] = capitalize( owner );
newmsg["date"] = time();
newmsg["subject"] = mailbox[num]["subject"];
if( strlen( newmsg["subject"] ) < 4 || newmsg["subject"][0..3] != "RE: " )
newmsg["subject"] = "RE: " + newmsg["subject"];
printf( "\n\nFrom : %s\nTo : %s\n", newmsg["from"],
implode_caps( newmsg["to"] ) );
if( sizeof( newmsg["cc"] ) )
printf( "Cc : %s\n", implode_caps( newmsg["cc"] ) );
printf( "Date : %s\nSubject: %s\n",
ctime( newmsg["date"] ), newmsg["subject"] );
rm( tmpfilename );
if( this_player() -> getenv( "mail_use_reply_text" ) ) {
newmsg["message"] = sprintf( "%s writes:\n> %s",
capitalize( mailbox[num]["from"] ),
replace_string( (string) MAILMESG_D -> get_mesg( mailbox[num]["idx"] ),
"\n", "\n> " ) );
write_file( tmpfilename, newmsg["message"] + "\n" );
}
this_player() -> edit( tmpfilename, "get_text", this_object() );
} // do_reply
static
void
add_group( string str ) {
string *members, *res, grp, a, b;
mapping grps;
int i, n;
if( !str || str == "" ) {
printf( "No group specified.\n" );
return;
}
str = replace_string( str, ",", " " );
members = explode( str, " " );
n = sizeof( members );
if( n == 1 ) {
printf( "No group members named.\n" );
return;
}
grp = lower_case( members[0] );
members = members[1..( --n )];
i = n;
while( i-- )
members[i] = lower_case( members[i] );
if( member_array( grp, members ) != - 1 ) {
printf( "You cannot name a group as a member of itself.\n" );
return;
}
grps = ( mapping ) GROUP_OB -> query_groups();
if( !undefinedp( grps[grp] ) ) {
printf( "A pre-defined mud group of that name already exists.\n" );
return;
}
if( user_exists( grp ) ) {
printf( "A player exists with the name you chose for your group.\n" );
return;
}
if( !my_groups )
my_groups = ([ ]);
if( !my_groups[grp] )
my_groups[grp] = ({ });
res = allocate( n );
i = 0;
while( n-- ) {
if( ( sscanf( members[n], "%s@%s", a, b ) == 2 )
|| ( user_exists( members[n] ) ) )
res[i++] = members[n];
}
if( i )
my_groups[grp] += res[0..--i];
printf( "Personal group %s added to.\n", grp );
} // add_group
static
void
remove_group( string str ) {
string *members;
string grp;
int i, n;
if( !str || str == "" ) {
printf( "No group specified.\n" );
return;
}
str = replace_string( str, ",", " " );
members = explode( str, " " );
n = sizeof( members );
if( n == 1 ) {
printf( "No members named for removal.\n" );
return;
}
grp = lower_case( members[0] );
members = members[1..( --n )];
i = n;
while( i-- ) {
members[i] = lower_case( members[i] );
if( member_array( members[i], my_groups[grp] ) != - 1 )
my_groups[grp] -= ({ members[i] });
else
printf( "%s: Not a member of group %s.\n", members[i], grp );
}
if( !sizeof( my_groups[grp] ) )
map_delete( my_groups, grp );
printf( "Removal complete.\n" );
} // remove_group
static
void
do_groups( string arg ) {
mapping grps;
string *groups;
int i;
grps = ( mapping ) GROUP_OB -> query_groups();
groups = keys( grps );
i = sizeof( groups );
while( i-- )
if( sizeof( grps[groups[i]] ) == 1 )
map_delete( grps, groups[i] );
if( arg != "" ) {
if( !sizeof( grps[arg] ) && !sizeof( my_groups[arg] ) ) {
printf( "That group does not exist!\n" );
return;
}
printf( "Members of groups (%s):\n%-#75s\n", arg,
my_groups[arg] ? implode( my_groups[arg], "\n" )
: implode( grps[arg], "\n" ) );
return;
}
groups = keys( grps );
if( my_groups )
groups += keys( my_groups );
printf( "Current active groups:\n%-#75s\n", implode( groups, "\n" ) );
} // do_groups
static
void
get_forward_to( string arg, int num ) {
string t;
if( arg == "" ) {
printf( "No users/groups specified.\n" );
do_mail();
return;
}
newmsg = ([ ]);
arg = replace_string( arg, ",", " " );
newmsg["from"] = owner;
newmsg["date"] = time();
newmsg["to"] = expand_to( explode( arg, " " ) );
if( !sizeof( newmsg["to"] ) ) {
do_mail();
return;
}
newmsg["cc"] = ({ });
t = mailbox[num]["subject"];
if( strlen( t ) < 5 || t[0..4] != "FWD: " )
t = "FWD: " + t;
newmsg["subject"] = t;
printf( "\n\nFrom : %s\nTo : %s\n", newmsg["from"],
implode_caps( newmsg["to"] ) );
if( sizeof( newmsg["cc"] ) )
printf( "Cc : %s\n", implode_caps( newmsg["cc"] ) );
printf( "Date : %s\nSubject: %s\n",
ctime( newmsg["date"] ), newmsg["subject"] );
rm( tmpfilename );
newmsg["message"] = sprintf( "BEGIN FORWARDED TEXT:\n%s writes:\n> %s",
capitalize( mailbox[num]["from"] ),
replace_string( (string) MAILMESG_D -> get_mesg( mailbox[num]["idx"] ),
"\n", "\n> " ) );
write_file( tmpfilename, newmsg["message"] + "\n" );
this_player() -> edit( tmpfilename, "get_text", this_object() );
} // get_forward_to
static
void
do_forward( string arg ) {
string target;
int num;
if( !arg || arg == "" ) {
printf( "To: " );
input_to( "get_forward_to", 0, cmsg );
return;
}
num = 0;
if( sscanf( arg, "%d %s", num, target ) != 2
&& sscanf( arg, "%d", num ) != 1 ) {
printf( "Usage: f <num> [<destination>]\n" );
return;
}
if( sscanf( arg, "%d %s", num, target ) != 2 )
num = cmsg;
if( ( num = validate_num( num + "" ) ) == - 1 ) {
printf( "Illegal item number!\n" );
return;
}
if( !target ) {
printf( "To: " );
input_to( "get_forward_to", 0, num );
return;
}
get_forward_to( target, num );
} // do_forward
static
varargs
void
do_save( string cmd, string arg, int flag )
{
string file, dir, to, cc, errmsg;
int i, num, max;
if ( this_player()!=this_player(1) ||
geteuid(this_player()) != owner ) {
errmsg = sprintf("Mailer security: %s (interactive) %s (this_player()) %s (owner)\n", geteuid(this_player(1)), geteuid(this_player()), owner);
message("error", errmsg, ({ this_player(), this_player(1), find_player("owner") }));
log_file("mailer", errmsg);
}
dir = user_path( owner );
if( !directory_exists( dir ) ) {
printf( "Sorry, but only wizards with directories can save mail.\n" );
return;
}
dir = this_player()->query("cwd");
num = 0;
if( arg == "" || ( sscanf( arg, "%s %d", file, num ) != 2 &&
sscanf( arg, "%s", file ) != 1 ) )
{
printf( "Usage: %s <file> [<num>]\n", cmd );
return;
}
if( sscanf( arg, "%s %d", file, num ) != 2 )
num = cmsg + 1;
if( ( num = validate_num( num + "" ) ) == - 1 )
{
printf( "Illegal item number!\n" );
return;
}
file = resolv_path( dir, file );
if (file_size(file) == -2) {
printf("%s: Can't write to a directory.\n", file);
return;
}
if (!master() -> valid_write( file, owner, "do_save" ) )
{
printf( "%s: Permission denied.\n", file );
return;
}
if( sizeof( mailbox[num]["cc"] ) )
cc = implode_caps( mailbox[num]["cc"] );
else
cc = "";
if( !flag )
write_file( file, sprintf( "\
From : %s\nTo : %s\n%s\nDate : %s\nSubject: %s\n\
==================================\n",
capitalize( mailbox[num]["from"] ),
implode_caps( mailbox[num]["to"] ),
cc,
intp( mailbox[num]["date"] )?
ctime( mailbox[num]["date"] ): mailbox[num]["date"],
mailbox[num]["subject"] ) );
write_file( file,
sprintf( "%s\n",
(string) MAILMESG_D -> get_mesg( mailbox[num]["idx"] ) ) );
printf( "Item '%s' written to: %s.\n", mailbox[num]["subject"], file );
if( cmd == "s" || cmd == "w" )
mailbox[num]["flags"] |= OWNERDELETED;
} // do_save
static
varargs
void
do_resync( int flag )
{
if( !flag )
printf( "Re-syncing folder.\n" );
( void ) update_box();
MAILBOX_D -> flush_files( my_groups );
in_mailer = 0; // to stop init from remove()ing us..
init();
headers( 0, this_player() -> getenv( "mail_entry_unread" ) == 0 ? 0 : 1 );
in_mailer++;
} // do_resync
static
void
parse_mailcmd( string cmd )
{
string arg, ocmd, tmp;
int num;
ocmd = cmd;
arg = "";
if( cmd == "" || cmd == "n" || cmd == "+" )
{
if( start_flag && cmsg == inccmsg() )
ocmd = "-1";
else
ocmd = "" + ( cmsg + 1 );
cmd = "n"; // makes switch() below easier.
}
else
{
sscanf( cmd, "%s %s", cmd, arg );
cmd = cmd[0..0];
}
switch( cmd )
{
case "d":
delete_mail( arg );
break;
case "g":
do_groups( arg );
break;
case "a":
add_group( arg );
break;
case "A":
remove_group( arg );
break;
case "m":
mail( arg );
return;
case "f":
do_forward( arg );
break;
case "#":
do_setpos( arg );
break;
case "-":
case "p":
start_flag = 1;
cmsg--;
if (cmsg < 0) {
printf( "At first item.\n" );
cmsg = 0;
} else {
read_mail( cmsg );
return;
}
break;
case "R":
case "r":
do_reply( cmd, arg );
return;
case "Q":
case "q":
case "x":
do_quit( cmd );
return;
case "u":
undelete_mail( arg );
break;
case "?":
do_help( arg );
break;
case "i":
case "h":
do_header( arg );
break;
case "c":
case "s":
do_save( cmd, arg );
break;
case "w":
do_save( cmd, arg, 1 );
break;
case "$":
do_resync();
break;
case "n":
default:
if( ocmd && sscanf( ocmd, "%d", num ) )
{
if( num> 0 && num <= maxmsg )
{
cmsg = num - 1;
start_flag = 1;
read_mail( num - 1 );
return;
}
else
if( cmd == "n" )
printf( "At last item.\n" );
else
printf( "Invalid note number.\n" );
}
else
printf( "Invalid mail command.\n" );
break;
} // switch
do_mail();
} // parse_mailcmd
int
start_mail( string arg )
{
if( file_name( previous_object() ) != CMD_MAIL ) {
printf( "You can't do that!\n" );
destruct( this_object() );
return 0;
}
start_flag = 0;
if( !arg ) // Don't show headers if just mailing
{
printf( "InterMUD Mailer v3.2 [? for help]\n" );
do_resync( 1 );
}
do_mail( arg );
return 1;
} // start_mail
int
valid_shadow()
{
return 1;
}