home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Magazyn Amiga Shareware Floppies
/
ma64.dms
/
ma64.adf
/
FTPMount-1.0
/
Source
/
startup.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-09-06
|
15KB
|
652 lines
/*
* This source file is Copyright 1995 by Evan Scott.
* All rights reserved.
* Permission is granted to distribute this file provided no
* fees beyond distribution costs are levied.
*/
#include <exec/types.h>
#include <exec/memory.h>
#include <exec/alerts.h>
#include <dos/dos.h>
#include <dos/dosextens.h>
#include <dos/dostags.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/graphics.h>
#include <proto/intuition.h>
#include <proto/locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "evtypes.h"
#include "verify.h"
#include "tcp.h"
#include "site.h"
#include "ftp.h"
#include "local.h"
#include "request.h"
#define DECLARE_GLOBALS_HERE 1
#include "globals.h"
#include "strings.h"
struct DosPacket *fh_listen(void);
void fh_ignore(void);
boolean launch_tcp_handler(void);
boolean launch_local(void);
void shutdown_tcp_handler(void);
void shutdown_local(void);
boolean open_libraries(void);
void close_libraries(void);
boolean make_gims(void);
void free_gims(void);
void startup_error(b8 *s);
boolean get_anon_login(void);
boolean create_volume(void);
void destroy_volume(void);
boolean launch_status(void);
void shutdown_status(void);
void setup_strings(void);
void cleanup_strings(void);
void __saveds start(void)
{
struct Process *me;
struct Message *msg;
struct DosPacket *dp;
struct MsgPort *reply;
struct DateTime dtime;
b8 temp[15];
SysBase = *(struct ExecBase **)4;
me = (struct Process *)FindTask(0l);
ftp_port = &me->pr_MsgPort;
WaitPort(ftp_port); /* wait for startup packet */
msg = GetMsg(ftp_port);
dp = (struct DosPacket *)msg->mn_Node.ln_Name;
reply = dp->dp_Port;
dp->dp_Port = ftp_port;
ftp_device = (struct DosList *)(dp->dp_Arg3 << 2);
ftp_device->dol_Task = ftp_port; /* fill in our message port */
/* get down to initializing everything */
sites = nil;
orphaned_locks = nil;
if (open_libraries()) {
ftpdir_lock = Lock("FTPMountDir:", SHARED_LOCK);
if (ftpdir_lock) {
UnLock(CurrentDir(ftpdir_lock));
UnLock(SetProgramDir(ftpdir_lock));
/* setup PROGDIR: so we can open the catalog asap */
setup_strings();
mem_tracking_on();
DateStamp(&dtime.dat_Stamp);
dtime.dat_StrDate = temp;
dtime.dat_StrDay = nil;
dtime.dat_StrTime = nil;
dtime.dat_Flags = 0;
dtime.dat_Format = FORMAT_INT;
DateToStr(&dtime);
year = atoi(temp);
if (year >= 78) year += 1900;
else year += 2000;
if (get_anon_login()) {
if (make_gims()) {
if (launch_tcp_handler()) {
if (launch_local()) {
ftphosts_lock = Lock(strings[MSG_HOSTS], SHARED_LOCK);
if (ftphosts_lock) {
if (launch_status()) {
if (create_volume()) {
/* initialization is complete */
dp->dp_Res1 = DOSTRUE;
dp->dp_Res2 = 0;
PutMsg(reply, dp->dp_Link);
dp = fh_listen();
/* only comes back on a DIE */
shutdown_sites();
shutdown_status();
shutdown_local();
shutdown_tcp_handler();
UnLock(ftphosts_lock);
UnLock(ftpdir_lock);
free_gims();
if (anon_login)
deallocate(anon_login, V_cstr);
destroy_volume();
check_memory();
close_libraries();
if (dp) {
dp->dp_Res1 = DOSTRUE;
dp->dp_Res2 = 0;
reply = dp->dp_Port;
dp->dp_Port = ftp_port;
PutMsg(reply, dp->dp_Link);
}
fh_ignore(); /* never comes back */
} else dp->dp_Res2 = ERROR_NO_FREE_STORE;
shutdown_status();
} else dp->dp_Res2 = ERROR_NO_FREE_STORE;
UnLock(ftphosts_lock);
} else {
startup_error(strings[MSG_CANT_FIND_HOSTS]);
dp->dp_Res2 = ERROR_DIR_NOT_FOUND;
}
shutdown_local();
} else dp->dp_Res2 = ERROR_NO_FREE_STORE;
shutdown_tcp_handler();
} else dp->dp_Res2 = ERROR_NO_FREE_STORE;
free_gims();
} else dp->dp_Res2 = ERROR_NO_FREE_STORE;
if (anon_login) deallocate(anon_login, V_cstr);
} else dp->dp_Res2 = ERROR_REQUIRED_ARG_MISSING;
check_memory();
cleanup_strings();
SetProgramDir(0);
CurrentDir(0);
UnLock(ftpdir_lock);
} else dp->dp_Res2 = ERROR_DIR_NOT_FOUND;
close_libraries();
} else dp->dp_Res2 = ERROR_INVALID_RESIDENT_LIBRARY;
ftp_device->dol_Task = 0;
dp->dp_Res1 = DOSFALSE;
Forbid(); /* this is so they can't unloadseg us until we have finished */
PutMsg(reply, dp->dp_Link);
return;
}
/* has to be after the startup function */
#include "verify_code.h"
void startup_error(b8 *s)
{
struct EasyStruct es;
es.es_StructSize = sizeof(struct EasyStruct);
es.es_Flags = 0;
es.es_Title = strings[MSG_FTPM_STARTUP_ERROR];
es.es_GadgetFormat = strings[MSG_OK];
es.es_TextFormat = s;
EasyRequest(nil, &es, nil);
}
boolean launch_tcp_handler(void)
{
struct Process *child;
tcpmessage *tm;
unique_name(FindTask(0), ": FTPMount", unique_buffer);
startup_sync = CreatePort(unique_buffer, 0);
if (startup_sync) {
child = CreateNewProcTags(
NP_Entry, tcp_handler,
NP_Arguments, unique_buffer,
NP_Name, strings[MSG_TCP_HANDLER],
NP_StackSize, 6000,
TAG_END, 0
);
if (child) {
Wait(1 << startup_sync->mp_SigBit);
tm = (tcpmessage *)GetMsg(startup_sync);
if (tm) {
verify(tm, V_tcpmessage);
if (tm->result) {
tcp = tm->data;
ReplyMsg(&tm->header);
WaitPort(startup_sync);
prime = (tcpmessage *)GetMsg(startup_sync);
/* ok! off we trundle */
prime->command = TCP_SERVICE;
prime->data = strings[MSG_SERVICE];
PutMsg(tcp, &prime->header);
WaitPort(startup_sync); GetMsg(startup_sync);
if (prime->result) {
ftp_port_number = prime->port.w;
} else {
ftp_port_number = 0; /* fill it in at connect time */
}
return true;
}
ReplyMsg(&tm->header);
/* whether child is still alive here??? */
}
}
DeletePort(startup_sync);
}
startup_error(strings[MSG_CANT_LAUNCH_TCP]);
return false;
}
void shutdown_tcp_handler(void)
{
prime->command = TCP_DIE;
prime->header.mn_ReplyPort = startup_sync;
PutMsg(tcp, &prime->header);
Wait(1 << startup_sync->mp_SigBit); /* Wait til the child signals it is dead */
DeletePort(startup_sync);
return;
}
boolean launch_local(void)
{
struct StandardPacket *sp;
struct Process *child;
sp = (struct StandardPacket *)allocate_flags(sizeof(*sp), MEMF_PUBLIC, V_StandardPacket);
if (!sp) return false;
local_msg = &sp->sp_Msg;
local_msg->mn_Node.ln_Name = (char *)&sp->sp_Pkt;
sp->sp_Pkt.dp_Link = local_msg;
sp->sp_Pkt.dp_Type = ACTION_DIE; /* for startup it should ignore this :) */
sp->sp_Pkt.dp_Port = startup_sync; /* this is bad programming ... increases linkage */
child = CreateNewProcTags(
NP_Entry, local_handler,
NP_Name, strings[MSG_LOCAL_HANDLER],
NP_StackSize, 6000,
TAG_END, 0
);
if (child) {
local_port = &child->pr_MsgPort;
PutMsg(local_port, local_msg);
WaitPort(startup_sync); GetMsg(startup_sync);
if (sp->sp_Pkt.dp_Res1) {
return true;
}
}
deallocate(sp, V_StandardPacket);
startup_error(strings[MSG_CANT_LAUNCH_LOCAL]);
return false;
}
void shutdown_local(void)
{
struct StandardPacket *sp;
sp = (struct StandardPacket *)local_msg;
sp->sp_Pkt.dp_Port = startup_sync;
PutMsg(local_port, local_msg);
WaitPort(startup_sync); GetMsg(startup_sync);
deallocate(sp, V_StandardPacket);
return;
}
boolean open_libraries(void)
{
IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 36);
if (IntuitionBase) {
DOSBase = (struct DosLibrary *)OpenLibrary("dos.library", 36);
if (DOSBase) {
GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 0);
if (GfxBase) {
IconBase = OpenLibrary("icon.library", 0);
LocaleBase = OpenLibrary("locale.library", 0);
return true;
} else startup_error("FTPMount cannot open graphics.library");
CloseLibrary((struct Library *)DOSBase);
} else startup_error("FTPMount requires V36 dos.library");
CloseLibrary((struct Library *)IntuitionBase);
}
return false;
}
void close_libraries(void)
{
if (LocaleBase) CloseLibrary(LocaleBase);
if (IconBase) CloseLibrary(IconBase);
CloseLibrary((struct Library *)GfxBase);
CloseLibrary((struct Library *)DOSBase);
CloseLibrary((struct Library *)IntuitionBase);
}
boolean make_gims(void)
{
struct Screen *s;
struct DrawInfo *drawinfo;
s = LockPubScreen(nil);
if (!s) return false;
lightpen = 2;
darkpen = 1;
textpen = 1;
fillpen = 3;
drawinfo = GetScreenDrawInfo(s);
if (drawinfo) {
if (drawinfo->dri_NumPens > SHADOWPEN) {
lightpen = drawinfo->dri_Pens[SHINEPEN];
darkpen = drawinfo->dri_Pens[SHADOWPEN];
textpen = drawinfo->dri_Pens[TEXTPEN];
fillpen = drawinfo->dri_Pens[FILLPEN];
}
FreeScreenDrawInfo(s, drawinfo);
}
cancel_gim = make_gim(strings[MSG_CANCEL], textpen, lightpen, darkpen, s, IntuitionBase, GfxBase);
if (cancel_gim) {
abort_gim = make_gim(strings[MSG_ABORT], textpen, lightpen, darkpen, s, IntuitionBase, GfxBase);
if (abort_gim) {
disconnect_gim = make_gim(strings[MSG_DISCONNECT], textpen, lightpen, darkpen, s, IntuitionBase, GfxBase);
if (disconnect_gim) {
login_gim = make_gim(strings[MSG_LOGIN], textpen, lightpen, darkpen, s, IntuitionBase, GfxBase);
if (login_gim) {
UnlockPubScreen(nil, s);
return true;
}
free_gim(disconnect_gim, IntuitionBase, GfxBase);
}
free_gim(abort_gim, IntuitionBase, GfxBase);
}
free_gim(cancel_gim, IntuitionBase, GfxBase);
}
UnlockPubScreen(nil, s);
return false;
}
void free_gims(void)
{
free_gim(login_gim, IntuitionBase, GfxBase);
free_gim(disconnect_gim, IntuitionBase, GfxBase);
free_gim(abort_gim, IntuitionBase, GfxBase);
free_gim(cancel_gim, IntuitionBase, GfxBase);
}
#define BUFF_SIZE 100
boolean get_anon_login(void)
{
b8 user[BUFF_SIZE], host[BUFF_SIZE];
sb32 i, j;
struct EasyStruct es;
es.es_StructSize = sizeof(struct EasyStruct);
es.es_Flags = 0;
es.es_Title = strings[MSG_FTPM_STARTUP_ERROR];
es.es_GadgetFormat = strings[MSG_CONTINUE_EXIT];
i = GetVar(strings[MSG_USER], user, BUFF_SIZE, 0);
j = GetVar(strings[MSG_HOST], host, BUFF_SIZE, 0);
/* four cases here */
if (i >= 0 && j >= 0) {
anon_login = (b8 *)allocate(i + j + 2, V_cstr);
if (!anon_login) return false;
strcpy(anon_login, user);
anon_login[i] = '@';
strcpy(anon_login + i + 1, host);
} else if (i < 0 && j >= 0) {
anon_login = (b8 *)allocate(j + 9, V_cstr);
if (!anon_login) return false;
strcpy(anon_login, "unknown@");
strcat(anon_login, host);
es.es_TextFormat = strings[MSG_USER_NOT_SET];
if (!EasyRequest(nil, &es, 0, anon_login)) {
deallocate(anon_login, V_cstr);
return false;
}
} else if (i >= 0 && j < 0) {
anon_login = (b8 *)allocate(i + 9, V_cstr);
if (!anon_login) return false;
strcpy(anon_login, user);
strcat(anon_login, "@unknown");
es.es_TextFormat = strings[MSG_HOST_NOT_SET];
if (!EasyRequest(nil, &es, 0, anon_login)) {
deallocate(anon_login, V_cstr);
return false;
}
} else {
anon_login = (b8 *)allocate(16, V_cstr);
if (!anon_login) return false;
strcpy(anon_login, "unknown@unknown");
es.es_TextFormat = strings[MSG_USER_HOST_NOT_SET];
if (!EasyRequest(nil, &es, 0, anon_login)) {
deallocate(anon_login, V_cstr);
return false;
}
}
return true;
}
boolean create_volume(void)
{
b32 vlen;
ftp_volume = (struct DosList *)allocate_flags(sizeof(struct DosList), MEMF_PUBLIC, V_DosList);
if (ftp_volume) {
ftp_volume->dol_Type = DLT_VOLUME;
ftp_volume->dol_Task = ftp_port;
ftp_volume->dol_Lock = 0;
DateStamp(&ftp_volume->dol_misc.dol_volume.dol_VolumeDate);
ftp_volume->dol_misc.dol_volume.dol_LockList = 0;
ftp_volume->dol_misc.dol_volume.dol_DiskType = ID_DOS_DISK;
vlen = strlen(strings[MSG_VOLUME]);
volume_name = (b8 *)allocate_flags(vlen + 2, MEMF_PUBLIC, V_bstr);
if (volume_name) {
volume_name[0] = vlen;
strcpy(&volume_name[1], strings[MSG_VOLUME]);
ftp_volume->dol_Name = (b32)volume_name >> 2;
if (AddDosEntry(ftp_volume)) {
return true;
}
deallocate(volume_name, V_bstr);
}
deallocate(ftp_volume, V_DosList);
}
return false;
}
void destroy_volume(void)
{
struct DosList *dllock;
dllock = LockDosList(LDF_VOLUMES | LDF_DELETE | LDF_WRITE);
if (RemDosEntry(ftp_volume)) {
deallocate(volume_name, V_bstr);
deallocate(ftp_volume, V_DosList);
}
UnLockDosList(LDF_VOLUMES | LDF_DELETE | LDF_WRITE);
return;
}
boolean launch_status(void)
{
struct Process *child;
status_mess = (status_message *)allocate(sizeof(*status_mess), V_status_message);
if (!status_mess) return false;
status_mess->header.mn_Length = sizeof(*status_mess);
status_mess->header.mn_Node.ln_Name = "status startup message";
status_mess->header.mn_Node.ln_Type = NT_MESSAGE;
status_mess->header.mn_Node.ln_Pri = 0;
ensure(status_mess, V_status_message);
status_control = CreatePort(0, 0);
if (status_control) {
child = CreateNewProcTags(
NP_Entry, status_handler,
NP_Name, strings[MSG_STATUS_HANDLER],
NP_StackSize, 6000,
TAG_END, 0
);
if (child) {
status_port = &child->pr_MsgPort;
status_mess->header.mn_ReplyPort = startup_sync;
PutMsg(status_port, &status_mess->header);
WaitPort(startup_sync); GetMsg(startup_sync);
if (status_mess->command != SM_KILL) {
return true;
}
}
DeletePort(status_control);
}
deallocate(status_mess, V_status_message);
startup_error(strings[MSG_CANT_LAUNCH_STATUS]);
return false;
}
void shutdown_status(void)
{
status_message *sm;
status_mess->command = SM_KILL;
status_mess->header.mn_ReplyPort = startup_sync;
PutMsg(status_port, &status_mess->header);
while (1) {
Wait ((1 << status_control->mp_SigBit) | (1 << startup_sync->mp_SigBit));
while (sm = (status_message *)GetMsg(status_control)) {
verify(sm, V_status_message);
ReplyMsg(&sm->header);
}
if (sm = (status_message *)GetMsg(startup_sync)) {
deallocate(status_mess, V_status_message);
DeletePort(status_control);
return;
}
}
}
void setup_strings(void)
{
int i;
my_locale = nil;
cat = nil;
if (LocaleBase) {
my_locale = OpenLocale(0);
if (my_locale) {
cat = OpenCatalog(my_locale, "FTPMount.catalog",
OC_BuiltInLanguage, "english",
TAG_END
);
}
}
if (cat) {
for (i = 0; i < NUM_MSGS; i++) {
strings[i] = GetCatalogStr(cat, i, strings[i]);
}
}
}
void cleanup_strings(void)
{
if (cat) CloseCatalog(cat);
if (my_locale) CloseLocale(my_locale);
}