home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Amiga Shareware Floppies / ma64.dms / ma64.adf / FTPMount-1.0 / Source / startup.c < prev    next >
C/C++ Source or Header  |  1995-09-06  |  15KB  |  652 lines

  1. /*
  2.  * This source file is Copyright 1995 by Evan Scott.
  3.  * All rights reserved.
  4.  * Permission is granted to distribute this file provided no
  5.  * fees beyond distribution costs are levied.
  6.  */
  7.  
  8. #include <exec/types.h>
  9. #include <exec/memory.h>
  10. #include <exec/alerts.h>
  11.  
  12. #include <dos/dos.h>
  13. #include <dos/dosextens.h>
  14. #include <dos/dostags.h>
  15.  
  16. #include <proto/exec.h>
  17. #include <proto/dos.h>
  18. #include <proto/graphics.h>
  19. #include <proto/intuition.h>
  20. #include <proto/locale.h>
  21.  
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <string.h>
  25.  
  26. #include "evtypes.h"
  27. #include "verify.h"
  28. #include "tcp.h"
  29.  
  30. #include "site.h"
  31. #include "ftp.h"
  32. #include "local.h"
  33. #include "request.h"
  34.  
  35. #define DECLARE_GLOBALS_HERE 1
  36. #include "globals.h"
  37. #include "strings.h"
  38.  
  39. struct DosPacket *fh_listen(void);
  40. void fh_ignore(void);
  41.  
  42. boolean launch_tcp_handler(void);
  43. boolean launch_local(void);
  44. void shutdown_tcp_handler(void);
  45. void shutdown_local(void);
  46.  
  47. boolean open_libraries(void);
  48. void close_libraries(void);
  49.  
  50. boolean make_gims(void);
  51. void free_gims(void);
  52.  
  53. void startup_error(b8 *s);
  54.  
  55. boolean get_anon_login(void);
  56.  
  57. boolean create_volume(void);
  58. void destroy_volume(void);
  59.  
  60. boolean launch_status(void);
  61. void shutdown_status(void);
  62.  
  63. void setup_strings(void);
  64. void cleanup_strings(void);
  65.  
  66. void __saveds start(void)
  67. {
  68.     struct Process *me;
  69.     struct Message *msg;
  70.     struct DosPacket *dp;
  71.     struct MsgPort *reply;
  72.     struct DateTime dtime;
  73.     b8 temp[15];
  74.  
  75.     SysBase = *(struct ExecBase **)4;
  76.  
  77.     me = (struct Process *)FindTask(0l);
  78.     
  79.     ftp_port = &me->pr_MsgPort;
  80.     
  81.     WaitPort(ftp_port);    /* wait for startup packet */
  82.     msg = GetMsg(ftp_port);
  83.     
  84.     dp = (struct DosPacket *)msg->mn_Node.ln_Name;
  85.     reply = dp->dp_Port;
  86.     dp->dp_Port = ftp_port;
  87.     
  88.     ftp_device = (struct DosList *)(dp->dp_Arg3 << 2);
  89.     ftp_device->dol_Task = ftp_port;    /* fill in our message port */
  90.     
  91.     /* get down to initializing everything */
  92.     
  93.     sites = nil;
  94.     orphaned_locks = nil;
  95.     
  96.     if (open_libraries()) {
  97.         ftpdir_lock = Lock("FTPMountDir:", SHARED_LOCK);
  98.         if (ftpdir_lock) {
  99.             UnLock(CurrentDir(ftpdir_lock));
  100.             UnLock(SetProgramDir(ftpdir_lock));
  101.             
  102.             /* setup PROGDIR: so we can open the catalog asap */
  103.             
  104.             setup_strings();
  105.  
  106.             mem_tracking_on();
  107.         
  108.             DateStamp(&dtime.dat_Stamp);
  109.         
  110.             dtime.dat_StrDate = temp;
  111.             dtime.dat_StrDay = nil;
  112.             dtime.dat_StrTime = nil;
  113.             dtime.dat_Flags = 0;
  114.             dtime.dat_Format = FORMAT_INT;
  115.         
  116.             DateToStr(&dtime);
  117.         
  118.             year = atoi(temp);
  119.         
  120.             if (year >= 78) year += 1900;
  121.             else year += 2000;
  122.         
  123.             if (get_anon_login()) {
  124.                 if (make_gims()) {
  125.                     if (launch_tcp_handler()) {
  126.                         if (launch_local()) {
  127.                             ftphosts_lock = Lock(strings[MSG_HOSTS], SHARED_LOCK);
  128.                             if (ftphosts_lock) {
  129.                                 if (launch_status()) {
  130.                                     if (create_volume()) {
  131.                                         /* initialization is complete */
  132.                                         dp->dp_Res1 = DOSTRUE;
  133.                                         dp->dp_Res2 = 0;
  134.                                 
  135.                                         PutMsg(reply, dp->dp_Link);
  136.                                 
  137.                                         dp = fh_listen();
  138.                                 
  139.                                         /* only comes back on a DIE */
  140.                                         
  141.                                         shutdown_sites();
  142.  
  143.                                         shutdown_status();
  144.                                         shutdown_local();
  145.                                         shutdown_tcp_handler();
  146.                 
  147.                                         UnLock(ftphosts_lock);
  148.                                         UnLock(ftpdir_lock);
  149.                                 
  150.                                         free_gims();
  151.                                     
  152.                                         if (anon_login) 
  153.                                             deallocate(anon_login, V_cstr);
  154.                                     
  155.                                         destroy_volume();
  156.  
  157.                                         check_memory();
  158.                                 
  159.                                         close_libraries();
  160.  
  161.                                         if (dp) {
  162.                                             dp->dp_Res1 = DOSTRUE;
  163.                                             dp->dp_Res2 = 0;
  164.                                     
  165.                                             reply = dp->dp_Port;
  166.                                             dp->dp_Port = ftp_port;
  167.                                     
  168.                                             PutMsg(reply, dp->dp_Link);
  169.                                         }
  170.                                     
  171.                                         fh_ignore();    /* never comes back */
  172.                                     } else dp->dp_Res2 = ERROR_NO_FREE_STORE;
  173.                                     shutdown_status();
  174.                                 } else dp->dp_Res2 = ERROR_NO_FREE_STORE;
  175.                                 UnLock(ftphosts_lock);
  176.                             } else {
  177.                                 startup_error(strings[MSG_CANT_FIND_HOSTS]);
  178.                                 dp->dp_Res2 = ERROR_DIR_NOT_FOUND;
  179.                             }
  180.                             shutdown_local();
  181.                         } else dp->dp_Res2 = ERROR_NO_FREE_STORE;
  182.                         shutdown_tcp_handler();
  183.                     } else dp->dp_Res2 = ERROR_NO_FREE_STORE;
  184.                     free_gims();
  185.                 } else dp->dp_Res2 = ERROR_NO_FREE_STORE;
  186.                 if (anon_login) deallocate(anon_login, V_cstr);
  187.             } else dp->dp_Res2 = ERROR_REQUIRED_ARG_MISSING;
  188.         
  189.             check_memory();
  190.             
  191.             cleanup_strings();
  192.             
  193.             SetProgramDir(0);
  194.             CurrentDir(0);
  195.         
  196.             UnLock(ftpdir_lock);
  197.         } else dp->dp_Res2 = ERROR_DIR_NOT_FOUND;
  198.         close_libraries();
  199.     } else dp->dp_Res2 = ERROR_INVALID_RESIDENT_LIBRARY;
  200.  
  201.     ftp_device->dol_Task = 0;
  202.     
  203.     dp->dp_Res1 = DOSFALSE;
  204.     
  205.     Forbid();    /* this is so they can't unloadseg us until we have finished */
  206.     PutMsg(reply, dp->dp_Link);
  207.     return;
  208. }
  209.  
  210. /* has to be after the startup function */
  211. #include "verify_code.h"
  212.  
  213. void startup_error(b8 *s)
  214. {
  215.     struct EasyStruct es;
  216.     
  217.     es.es_StructSize = sizeof(struct EasyStruct);
  218.     es.es_Flags = 0;
  219.     es.es_Title = strings[MSG_FTPM_STARTUP_ERROR];
  220.     es.es_GadgetFormat = strings[MSG_OK];
  221.     es.es_TextFormat = s;
  222.     
  223.     EasyRequest(nil, &es, nil);
  224. }
  225.  
  226. boolean launch_tcp_handler(void)
  227. {
  228.     struct Process *child;
  229.     tcpmessage *tm;
  230.     
  231.     unique_name(FindTask(0), ": FTPMount", unique_buffer);
  232.     
  233.     startup_sync = CreatePort(unique_buffer, 0);
  234.     if (startup_sync) {
  235.         child = CreateNewProcTags(
  236.             NP_Entry,    tcp_handler,
  237.             NP_Arguments,    unique_buffer,
  238.             NP_Name,    strings[MSG_TCP_HANDLER],
  239.             NP_StackSize,    6000,
  240.             TAG_END,    0
  241.         );
  242.         if (child) {
  243.             Wait(1 << startup_sync->mp_SigBit);
  244.             tm = (tcpmessage *)GetMsg(startup_sync);
  245.             
  246.             if (tm) {
  247.                 verify(tm, V_tcpmessage);
  248.                 
  249.                 if (tm->result) {
  250.                     tcp = tm->data;
  251.                     ReplyMsg(&tm->header);
  252.                     
  253.                     WaitPort(startup_sync);
  254.                     prime = (tcpmessage *)GetMsg(startup_sync);
  255.                     
  256.                     /* ok!  off we trundle */
  257.                     
  258.                     prime->command = TCP_SERVICE;
  259.                     prime->data = strings[MSG_SERVICE];
  260.                     
  261.                     PutMsg(tcp, &prime->header);
  262.                     WaitPort(startup_sync); GetMsg(startup_sync);
  263.                     
  264.                     if (prime->result) {
  265.                         ftp_port_number = prime->port.w;
  266.                     } else {
  267.                         ftp_port_number = 0;    /* fill it in at connect time */
  268.                     }
  269.                     
  270.                     return true;
  271.                 }
  272.                 ReplyMsg(&tm->header);
  273.                 
  274.                 /* whether child is still alive here??? */
  275.             }
  276.         }
  277.         DeletePort(startup_sync);
  278.     }
  279.     
  280.     startup_error(strings[MSG_CANT_LAUNCH_TCP]);
  281.     
  282.     return false;
  283. }
  284.  
  285. void shutdown_tcp_handler(void)
  286. {
  287.     prime->command = TCP_DIE;
  288.     prime->header.mn_ReplyPort = startup_sync;
  289.     
  290.     PutMsg(tcp, &prime->header);
  291.     
  292.     Wait(1 << startup_sync->mp_SigBit);    /* Wait til the child signals it is dead */
  293.     
  294.     DeletePort(startup_sync);
  295.     return;
  296. }
  297.  
  298. boolean launch_local(void)
  299. {
  300.     struct StandardPacket *sp;
  301.     struct Process *child;
  302.     
  303.     sp = (struct StandardPacket *)allocate_flags(sizeof(*sp), MEMF_PUBLIC, V_StandardPacket);
  304.     if (!sp) return false;
  305.     
  306.     local_msg = &sp->sp_Msg;
  307.     local_msg->mn_Node.ln_Name = (char *)&sp->sp_Pkt;
  308.     sp->sp_Pkt.dp_Link = local_msg;
  309.     
  310.     sp->sp_Pkt.dp_Type = ACTION_DIE;    /* for startup it should ignore this :) */
  311.     
  312.     sp->sp_Pkt.dp_Port = startup_sync;    /* this is bad programming ... increases linkage */
  313.     
  314.     child = CreateNewProcTags(
  315.         NP_Entry,    local_handler,
  316.         NP_Name,    strings[MSG_LOCAL_HANDLER],
  317.         NP_StackSize,    6000,
  318.         TAG_END,    0
  319.     );
  320.     if (child) {
  321.         local_port = &child->pr_MsgPort;
  322.         
  323.         PutMsg(local_port, local_msg);
  324.         WaitPort(startup_sync); GetMsg(startup_sync);
  325.         
  326.         if (sp->sp_Pkt.dp_Res1) {
  327.             return true;
  328.         }
  329.     }
  330.  
  331.     deallocate(sp, V_StandardPacket);
  332.  
  333.     startup_error(strings[MSG_CANT_LAUNCH_LOCAL]);
  334.     
  335.     return false;
  336. }
  337.  
  338. void shutdown_local(void)
  339. {
  340.     struct StandardPacket *sp;
  341.     
  342.     sp = (struct StandardPacket *)local_msg;
  343.     
  344.     sp->sp_Pkt.dp_Port = startup_sync;
  345.     
  346.     PutMsg(local_port, local_msg);
  347.     WaitPort(startup_sync); GetMsg(startup_sync);
  348.     
  349.     deallocate(sp, V_StandardPacket);
  350.     
  351.     return;
  352. }
  353.  
  354. boolean open_libraries(void)
  355. {
  356.     IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 36);
  357.     if (IntuitionBase) {
  358.         DOSBase = (struct DosLibrary *)OpenLibrary("dos.library", 36);
  359.         if (DOSBase) {
  360.             GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 0);
  361.             if (GfxBase) {
  362.                 IconBase = OpenLibrary("icon.library", 0);
  363.                 LocaleBase = OpenLibrary("locale.library", 0);
  364.                 
  365.                 return true;
  366.             } else startup_error("FTPMount cannot open graphics.library");
  367.             CloseLibrary((struct Library *)DOSBase);
  368.         } else startup_error("FTPMount requires V36 dos.library");
  369.         CloseLibrary((struct Library *)IntuitionBase);
  370.     }
  371.     
  372.     return false;
  373. }
  374.  
  375. void close_libraries(void)
  376. {
  377.     if (LocaleBase) CloseLibrary(LocaleBase);
  378.     if (IconBase) CloseLibrary(IconBase);
  379.     CloseLibrary((struct Library *)GfxBase);
  380.     CloseLibrary((struct Library *)DOSBase);
  381.     CloseLibrary((struct Library *)IntuitionBase);
  382. }
  383.  
  384. boolean make_gims(void)
  385. {
  386.     struct Screen *s;
  387.     struct DrawInfo *drawinfo;
  388.     
  389.     s = LockPubScreen(nil);
  390.     if (!s) return false;
  391.     
  392.     lightpen = 2;
  393.     darkpen = 1;
  394.     textpen = 1;
  395.     fillpen = 3;
  396.     
  397.     drawinfo = GetScreenDrawInfo(s);
  398.     if (drawinfo) {
  399.         if (drawinfo->dri_NumPens > SHADOWPEN) {
  400.             lightpen = drawinfo->dri_Pens[SHINEPEN];
  401.             darkpen = drawinfo->dri_Pens[SHADOWPEN];
  402.             textpen = drawinfo->dri_Pens[TEXTPEN];
  403.             fillpen = drawinfo->dri_Pens[FILLPEN];
  404.         }
  405.         FreeScreenDrawInfo(s, drawinfo);
  406.     }
  407.     
  408.     cancel_gim = make_gim(strings[MSG_CANCEL], textpen, lightpen, darkpen, s, IntuitionBase, GfxBase);
  409.     if (cancel_gim) {
  410.         abort_gim = make_gim(strings[MSG_ABORT], textpen, lightpen, darkpen, s, IntuitionBase, GfxBase);
  411.         if (abort_gim) {
  412.             disconnect_gim = make_gim(strings[MSG_DISCONNECT], textpen, lightpen, darkpen, s, IntuitionBase, GfxBase);
  413.             if (disconnect_gim) {
  414.                 login_gim = make_gim(strings[MSG_LOGIN], textpen, lightpen, darkpen, s, IntuitionBase, GfxBase);
  415.                 if (login_gim) {
  416.                     UnlockPubScreen(nil, s);
  417.                     return true;
  418.                 }
  419.                 free_gim(disconnect_gim, IntuitionBase, GfxBase);
  420.             }
  421.             free_gim(abort_gim, IntuitionBase, GfxBase);
  422.         }
  423.         free_gim(cancel_gim, IntuitionBase, GfxBase);
  424.     }
  425.     
  426.     UnlockPubScreen(nil, s);
  427.     
  428.     return false;
  429. }
  430.  
  431. void free_gims(void)
  432. {
  433.     free_gim(login_gim, IntuitionBase, GfxBase);
  434.     free_gim(disconnect_gim, IntuitionBase, GfxBase);
  435.     free_gim(abort_gim, IntuitionBase, GfxBase);
  436.     free_gim(cancel_gim, IntuitionBase, GfxBase);
  437. }
  438.  
  439. #define BUFF_SIZE 100
  440.  
  441. boolean get_anon_login(void)
  442. {
  443.     b8 user[BUFF_SIZE], host[BUFF_SIZE];
  444.     sb32 i, j;
  445.     struct EasyStruct es;
  446.     
  447.     es.es_StructSize = sizeof(struct EasyStruct);
  448.     es.es_Flags = 0;
  449.     es.es_Title = strings[MSG_FTPM_STARTUP_ERROR];
  450.     es.es_GadgetFormat = strings[MSG_CONTINUE_EXIT];
  451.     
  452.     i = GetVar(strings[MSG_USER], user, BUFF_SIZE, 0);
  453.     j = GetVar(strings[MSG_HOST], host, BUFF_SIZE, 0);
  454.     
  455.     /* four cases here */
  456.     if (i >= 0 && j >= 0) {
  457.         anon_login = (b8 *)allocate(i + j + 2, V_cstr);
  458.         if (!anon_login) return false;
  459.         
  460.         strcpy(anon_login, user);
  461.         anon_login[i] = '@';
  462.         strcpy(anon_login + i + 1, host);
  463.     } else if (i < 0 && j >= 0) {
  464.         anon_login = (b8 *)allocate(j + 9, V_cstr);
  465.         if (!anon_login) return false;
  466.  
  467.         strcpy(anon_login, "unknown@");
  468.         strcat(anon_login, host);
  469.  
  470.         es.es_TextFormat = strings[MSG_USER_NOT_SET];
  471.         if (!EasyRequest(nil, &es, 0, anon_login)) {
  472.             deallocate(anon_login, V_cstr);
  473.             return false;
  474.         }
  475.     } else if (i >= 0 && j < 0) {
  476.         anon_login = (b8 *)allocate(i + 9, V_cstr);
  477.         if (!anon_login) return false;
  478.  
  479.         strcpy(anon_login, user);
  480.         strcat(anon_login, "@unknown");
  481.  
  482.         es.es_TextFormat = strings[MSG_HOST_NOT_SET];
  483.         if (!EasyRequest(nil, &es, 0, anon_login)) {
  484.             deallocate(anon_login, V_cstr);
  485.             return false;
  486.         }
  487.     } else {
  488.         anon_login = (b8 *)allocate(16, V_cstr);
  489.         if (!anon_login) return false;
  490.  
  491.         strcpy(anon_login, "unknown@unknown");
  492.             
  493.         es.es_TextFormat = strings[MSG_USER_HOST_NOT_SET];
  494.         if (!EasyRequest(nil, &es, 0, anon_login)) {
  495.             deallocate(anon_login, V_cstr);
  496.             return false;
  497.         }
  498.     }
  499.     
  500.     return true;
  501. }
  502.  
  503. boolean create_volume(void)
  504. {
  505.     b32 vlen;
  506.  
  507.     ftp_volume = (struct DosList *)allocate_flags(sizeof(struct DosList), MEMF_PUBLIC, V_DosList);
  508.     if (ftp_volume) {
  509.         ftp_volume->dol_Type = DLT_VOLUME;
  510.         ftp_volume->dol_Task = ftp_port;
  511.         ftp_volume->dol_Lock = 0;
  512.         DateStamp(&ftp_volume->dol_misc.dol_volume.dol_VolumeDate);
  513.         ftp_volume->dol_misc.dol_volume.dol_LockList = 0;
  514.         ftp_volume->dol_misc.dol_volume.dol_DiskType = ID_DOS_DISK;
  515.     
  516.         vlen = strlen(strings[MSG_VOLUME]);
  517.         volume_name = (b8 *)allocate_flags(vlen + 2, MEMF_PUBLIC, V_bstr);
  518.         if (volume_name) {
  519.             volume_name[0] = vlen;
  520.             strcpy(&volume_name[1], strings[MSG_VOLUME]);
  521.  
  522.             ftp_volume->dol_Name = (b32)volume_name >> 2;
  523.             if (AddDosEntry(ftp_volume)) {
  524.                 return true;
  525.             }
  526.             
  527.             deallocate(volume_name, V_bstr);
  528.         }
  529.         deallocate(ftp_volume, V_DosList);
  530.     }
  531.     
  532.     return false;
  533. }
  534.  
  535. void destroy_volume(void)
  536. {
  537.     struct DosList *dllock;
  538.     
  539.     dllock = LockDosList(LDF_VOLUMES | LDF_DELETE | LDF_WRITE);
  540.     
  541.     if (RemDosEntry(ftp_volume)) {
  542.         deallocate(volume_name, V_bstr);
  543.         deallocate(ftp_volume, V_DosList);
  544.     }
  545.     
  546.     UnLockDosList(LDF_VOLUMES | LDF_DELETE | LDF_WRITE);
  547.     
  548.     return;
  549. }
  550.  
  551. boolean launch_status(void)
  552. {
  553.     struct Process *child;
  554.     
  555.     status_mess = (status_message *)allocate(sizeof(*status_mess), V_status_message);
  556.     if (!status_mess) return false;
  557.     
  558.     status_mess->header.mn_Length = sizeof(*status_mess);
  559.     status_mess->header.mn_Node.ln_Name = "status startup message";
  560.     status_mess->header.mn_Node.ln_Type = NT_MESSAGE;
  561.     status_mess->header.mn_Node.ln_Pri = 0;
  562.     
  563.     ensure(status_mess, V_status_message);
  564.     
  565.     status_control = CreatePort(0, 0);
  566.     if (status_control) {
  567.         child = CreateNewProcTags(
  568.             NP_Entry,    status_handler,
  569.             NP_Name,    strings[MSG_STATUS_HANDLER],
  570.             NP_StackSize,    6000,
  571.             TAG_END,    0
  572.         );
  573.     
  574.         if (child) {
  575.             status_port = &child->pr_MsgPort;
  576.         
  577.             status_mess->header.mn_ReplyPort = startup_sync;
  578.             PutMsg(status_port, &status_mess->header);
  579.         
  580.             WaitPort(startup_sync); GetMsg(startup_sync);
  581.         
  582.             if (status_mess->command != SM_KILL) {
  583.                 return true;
  584.             }
  585.         }
  586.         
  587.         DeletePort(status_control);
  588.     }
  589.     
  590.     deallocate(status_mess, V_status_message);
  591.     
  592.     startup_error(strings[MSG_CANT_LAUNCH_STATUS]);
  593.     
  594.     return false;
  595. }
  596.  
  597. void shutdown_status(void)
  598. {
  599.     status_message *sm;
  600.     
  601.     status_mess->command = SM_KILL;
  602.     status_mess->header.mn_ReplyPort = startup_sync;
  603.     
  604.     PutMsg(status_port, &status_mess->header);
  605.     
  606.     while (1) {
  607.         Wait ((1 << status_control->mp_SigBit) | (1 << startup_sync->mp_SigBit));
  608.         
  609.         while (sm = (status_message *)GetMsg(status_control)) {
  610.             verify(sm, V_status_message);
  611.             
  612.             ReplyMsg(&sm->header);
  613.         }
  614.         
  615.         if (sm = (status_message *)GetMsg(startup_sync)) {
  616.             deallocate(status_mess, V_status_message);
  617.             DeletePort(status_control);
  618.             return;
  619.         }
  620.     }
  621. }
  622.  
  623. void setup_strings(void)
  624. {
  625.     int i;
  626.  
  627.     my_locale = nil;
  628.     cat = nil;
  629.  
  630.     if (LocaleBase) {
  631.         my_locale = OpenLocale(0);
  632.         if (my_locale) {
  633.             cat = OpenCatalog(my_locale, "FTPMount.catalog",
  634.                 OC_BuiltInLanguage, "english",
  635.                 TAG_END
  636.             );
  637.         }
  638.     }
  639.     
  640.     if (cat) {
  641.         for (i = 0; i < NUM_MSGS; i++) {
  642.             strings[i] = GetCatalogStr(cat, i, strings[i]);
  643.         }
  644.     }
  645. }
  646.  
  647. void cleanup_strings(void)
  648. {
  649.     if (cat) CloseCatalog(cat);
  650.     if (my_locale) CloseLocale(my_locale);
  651. }
  652.