home *** CD-ROM | disk | FTP | other *** search
/ The Net Power 1997 August / NETDisc0897.iso / mac / Get Organized / TCP Switcher / mswitch.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-28  |  13.2 KB  |  530 lines  |  [TEXT/MMCC]

  1. /*---------------------------------------------------------------------------
  2.  
  3.     MacTCP Switcher - A Program to Save and Restore MacTCP Settings
  4.     
  5.     John Norstad
  6.     Academic Computing and Network Services
  7.     Northwestern University
  8.     
  9.     j-norstad@nwu.edu
  10.     
  11.     Copyright ⌐ 1993-1995, Northwestern University
  12.     
  13. ---------------------------------------------------------------------------*/
  14.  
  15. #include <ctype.h>
  16.  
  17. #define kErrOpeningSourceSettingsFile        100
  18. #define kErrOpeningDestinationSettingsFile    101
  19. #define kErrMacTCPNotFound                    102
  20.  
  21. #define kCreator     'MCPS'
  22. #define kFileType     'MCPT'
  23.  
  24. #define kMacTCPPrepCreator        'mtcp'
  25. #define kMacTCPPrepFileType        'mtpp'
  26.  
  27. #define kMacTCPConfigRsrcType    'ipln'
  28. #define kMacTCPConfigRsrcID        128
  29. #define kMacTCPDnrInfoRsrcType    'dnsl'
  30. #define kMacTCPDnrInfoRsrcID    128
  31.  
  32. #define kMacTCPDriverName         "\p.ipp"
  33.  
  34. #define kStringsID         128
  35. #define kMBarID         128
  36.  
  37. #define kErrAlert             128
  38. #define kUnexpectedErrAlert 129
  39. #define kSetMacTCPAlert        130
  40. #define kDamagedFileAlert    131
  41. #define kRestartAlert        132
  42. #define kMacTCPSetAlert        133
  43.  
  44. #define kNeedSystem7Alert    200
  45.  
  46. #define kSetMacTCPAlertSet        1
  47. #define kSetMacTCPAlertCancel    2
  48. #define kSetMacTCPAlertSave        3
  49.  
  50. #define kRestartAlertOK            1
  51. #define kRestartAlertRestart    2
  52.  
  53. #define kMacTCPPrepStr            1
  54. #define kSaveAsPromptStr        2
  55. #define kMacTCPStr                3
  56. #define kMacTCPNotFoundStr        4
  57. #define kCanOnlyOpenOneDocStr    5
  58.  
  59. #define kAppleMenu         128
  60. #define kEmptyItem        1
  61.  
  62. #define kFileMenu         129
  63.  
  64. #define kEditMenu         130
  65. #define kUndoItem         1
  66. #define kCutItem         3
  67. #define kCopyItem         4
  68. #define kPasteItem         5
  69. #define kClearItem         6
  70.  
  71. typedef struct TDialogCommandKeyItem {
  72.     short itemNumber;
  73.     char key;
  74. } TDialogCommandKeyItem;
  75.  
  76. static FSSpec gSourceSettingsFile;
  77. static FSSpec gDestinationSettingsFile;
  78.  
  79. static short gNumDialogCommandKeyItems;
  80. static TDialogCommandKeyItem gDialogCommandKeyItems[2];
  81.  
  82. static unsigned short NumToolboxTraps (void)
  83. {
  84.     return NGetTrapAddress(_InitGraf, ToolTrap) == 
  85.         NGetTrapAddress(0xAA6E, ToolTrap) ? 0x200 : 0x400;
  86. }
  87.  
  88. static TrapType GetTrapType (unsigned short theTrap)
  89. {
  90.     return (theTrap & 0x0800) > 0 ? ToolTrap : OSTrap;
  91. }
  92.  
  93. static Boolean TrapAvailable (unsigned short theTrap)
  94. {
  95.     TrapType tType;
  96.     
  97.     tType = GetTrapType(theTrap);
  98.     if (tType == ToolTrap) {
  99.         theTrap = theTrap & 0x07ff;
  100.         if (theTrap >= NumToolboxTraps()) theTrap = _Unimplemented;
  101.     }
  102.     return NGetTrapAddress(theTrap, tType) != 
  103.         NGetTrapAddress(_Unimplemented, ToolTrap);
  104. }
  105.  
  106. static void DlgFlashButton (DialogPtr dlg, short item)
  107. {
  108.     short itemType;
  109.     ControlHandle theItem;
  110.     Rect box;
  111.     long myticks;
  112.     
  113.     GetDItem(dlg, item, &itemType, (Handle*)&theItem, &box);
  114.     HiliteControl(theItem, 1);
  115.     Delay(8, &myticks);
  116.     HiliteControl(theItem, 0);
  117. }
  118.  
  119. static pascal Boolean DialogFilter (DialogPtr dlg, EventRecord *theEvent, 
  120.     short *itemHit)
  121. {
  122.     GrafPtr savedPort;
  123.     Boolean result = false;
  124.     char key;
  125.     TDialogCommandKeyItem *p, *pEnd;
  126.  
  127.     if ((theEvent->what == keyDown || theEvent->what == autoKey) &&
  128.         (theEvent->modifiers & cmdKey) != 0)
  129.     {
  130.         key = toupper(theEvent->message & charCodeMask);
  131.         p = gDialogCommandKeyItems;
  132.         pEnd = p + gNumDialogCommandKeyItems;
  133.         while (p < pEnd) {
  134.             if (key == toupper(p->key)) {
  135.                 *itemHit = p->itemNumber;
  136.                 DlgFlashButton(dlg, p->itemNumber);
  137.                 return true;
  138.             }
  139.             p++;
  140.         }
  141.     }
  142.     GetPort(&savedPort);
  143.     SetPort(dlg);
  144.     result = StdFilterProc(dlg, theEvent, itemHit);
  145.     SetPort(savedPort);
  146.     return result;
  147. }
  148.  
  149. static void MyModalDialog (short dlgID, short okItem, short cancelItem, 
  150.     StringPtr p1, StringPtr p2, short numCommandKeys, short *itemHit)
  151. {
  152.     DialogPtr dlg;
  153.     short hit;
  154.     
  155.     InitCursor();
  156.     dlg = GetNewDialog(dlgID, nil, (WindowPtr)-1);
  157.     if (okItem != 0) SetDialogDefaultItem(dlg, okItem);
  158.     if (cancelItem != 0) SetDialogCancelItem(dlg, cancelItem);
  159.     ParamText(p1, p2, "\p", "\p");
  160.     gNumDialogCommandKeyItems = numCommandKeys;
  161.     ModalDialog(DialogFilter, &hit);
  162.     DisposeDialog(dlg);
  163.     if (itemHit != nil) *itemHit = hit;
  164. }
  165.  
  166. static OSErr MyFSpOpenResFile (FSSpec *fSpec, short permission, short *refNum)
  167. {
  168.     OSErr err;
  169.     
  170.     *refNum = FSpOpenResFile(fSpec, permission);
  171.     if (*refNum != -1) return noErr;
  172.     err = ResError();
  173.     if (err != noErr) return err;
  174.     return resFNotFound;
  175. }
  176.  
  177. static OSErr MyFSpCreateResFile (FSSpec *fSpec, OSType creator, OSType fileType,
  178.     ScriptCode scriptTag)
  179. {
  180.     FSpCreateResFile(fSpec, creator, fileType, scriptTag);
  181.     return ResError();
  182. }
  183.  
  184. static OSErr MyGet1Resource (OSType type, short id, Handle *h)
  185. {
  186.     OSErr err;
  187.     
  188.     *h = Get1Resource(type, id);
  189.     if (*h != nil) return noErr;
  190.     err = ResError();
  191.     if (err != noErr) return err;
  192.     return resNotFound;
  193. }
  194.  
  195. static OSErr MyAddResource (Handle h, OSType type, short id)
  196. {
  197.     Handle rsrc;
  198.     OSErr err;
  199.     
  200.     rsrc = Get1Resource(type, id);
  201.     if (rsrc != nil) {
  202.         RmveResource(rsrc);
  203.         err = ResError();
  204.         if (err != noErr) return err;
  205.         DisposeHandle(rsrc);
  206.     }
  207.     AddResource(h, type, id, "\p");
  208.     return ResError();
  209. }
  210.  
  211. static void ErrorMessage (short errNum)
  212. {
  213.     Str255 msg;
  214.  
  215.     GetIndString(msg, kStringsID, errNum);
  216.     MyModalDialog(kErrAlert, ok, 0, msg, "\p", 0, nil);
  217. }
  218.  
  219. static void UnexpectedErrorMessage (OSErr err)
  220. {
  221.     Str255 errStr;
  222.     
  223.     if (err == kErrOpeningSourceSettingsFile) {
  224.         MyModalDialog(kDamagedFileAlert, ok, 0, gSourceSettingsFile.name, "\p", 0, nil);
  225.     } else if (err == kErrOpeningDestinationSettingsFile) {
  226.         MyModalDialog(kDamagedFileAlert, ok, 0, gDestinationSettingsFile.name, "\p", 0, nil);
  227.     } else if (err == kErrMacTCPNotFound) {
  228.         ErrorMessage(kMacTCPNotFoundStr);
  229.     } else {
  230.         NumToString(err, errStr);
  231.         MyModalDialog(kUnexpectedErrAlert, ok, 0, errStr, "\p", 0, nil);
  232.     }
  233. }
  234.  
  235. static Boolean MacTCPIsOpen (void)
  236. {
  237.     DCtlHandle *unitTableBase, *unitTableEntryPtr, *unitTableEnd, dctlHandle;
  238.     short unitTableEntryCount;
  239.     short flags;
  240.     Ptr driver;
  241.  
  242.     unitTableBase = (DCtlHandle*)LMGetUTableBase();
  243.     unitTableEntryCount = LMGetUnitTableEntryCount();
  244.     unitTableEnd = unitTableBase + unitTableEntryCount;
  245.     for (unitTableEntryPtr = unitTableBase; 
  246.         unitTableEntryPtr < unitTableEnd; 
  247.         unitTableEntryPtr++) 
  248.     {
  249.         dctlHandle = *unitTableEntryPtr;
  250.         if (dctlHandle != nil) {
  251.             flags = (**dctlHandle).dCtlFlags;
  252.             driver = (**dctlHandle).dCtlDriver;
  253.             if (flags & 0x40) driver = *(Handle)driver;
  254.             if (EqualString(kMacTCPDriverName, (StringPtr)(driver+18), true, true))
  255.                 return (flags & 0x20) != 0;
  256.         }
  257.     }
  258.     return false;
  259. }
  260.  
  261. static void Restart (void)
  262. {
  263.     ProcessSerialNumber psn;
  264.     AppleEvent message;
  265.     AEAddressDesc targetAddr;
  266.     OSErr err;
  267.     Boolean targetAddrCreated = false;
  268.     Boolean messageCreated = false;
  269.     
  270.     psn.highLongOfPSN = 0;
  271.     psn.lowLongOfPSN = kSystemProcess;
  272.     err = AECreateDesc(typeProcessSerialNumber, (Ptr)&psn, 
  273.         sizeof(ProcessSerialNumber), &targetAddr);
  274.     if (err != noErr) goto exit;
  275.     targetAddrCreated = true;
  276.     err = AECreateAppleEvent(kCoreEventClass, kAERestart,
  277.         &targetAddr, kAutoGenerateReturnID, kAnyTransactionID, &message);
  278.     if (err != noErr) goto exit;
  279.     messageCreated = true;
  280.     err = AESend(&message, nil, kAENoReply | kAECanInteract, kAENormalPriority,
  281.         kAEDefaultTimeout, nil, nil);
  282.     if (err != noErr) goto exit;
  283.     AEDisposeDesc(&message);
  284.     AEDisposeDesc(&targetAddr);
  285.     return;
  286.     
  287. exit:
  288.  
  289.     if (messageCreated) AEDisposeDesc(&message);
  290.     if (targetAddrCreated) AEDisposeDesc(&targetAddr);
  291.     UnexpectedErrorMessage(err);
  292. }
  293.  
  294. static OSErr CopyResources (FSSpec *source, FSSpec *dest, OSType creator, OSType fileType)
  295. {
  296.     short refNum = -1;
  297.     OSErr err;
  298.     Handle ipConfig, dnrInfo;
  299.     
  300.     gSourceSettingsFile = *source;
  301.     gDestinationSettingsFile = *dest;
  302.     err = MyFSpOpenResFile(source, fsRdPerm, &refNum);
  303.     if (err != noErr) {
  304.         err = kErrOpeningSourceSettingsFile;
  305.         goto exit;
  306.     }
  307.     err = MyGet1Resource(kMacTCPConfigRsrcType, kMacTCPConfigRsrcID, &ipConfig);
  308.     if (err != noErr) goto exit;
  309.     DetachResource(ipConfig);
  310.     err = MyGet1Resource(kMacTCPDnrInfoRsrcType, kMacTCPDnrInfoRsrcID, &dnrInfo);
  311.     if (err != noErr) goto exit;
  312.     DetachResource(dnrInfo);
  313.     CloseResFile(refNum);
  314.     refNum = -1;
  315.     
  316.     err = MyFSpOpenResFile(dest, fsRdWrPerm, &refNum);
  317.     if (err == fnfErr && creator != 0) {
  318.         err = MyFSpCreateResFile(dest, creator, fileType, smSystemScript);
  319.         if (err != noErr) goto exit;
  320.         err = MyFSpOpenResFile(dest, fsRdWrPerm, &refNum);
  321.     }
  322.     if (err != noErr) {
  323.         err = kErrOpeningDestinationSettingsFile;
  324.         goto exit;
  325.     }
  326.     err = MyAddResource(ipConfig, kMacTCPConfigRsrcType, kMacTCPConfigRsrcID);
  327.     if (err != noErr) goto exit;
  328.     err = MyAddResource(dnrInfo, kMacTCPDnrInfoRsrcType, kMacTCPDnrInfoRsrcID);
  329.     if (err != noErr) goto exit;
  330.     CloseResFile(refNum);
  331.     FlushVol(nil, dest->vRefNum);
  332.     return noErr; 
  333.     
  334. exit:
  335.  
  336.     if (refNum != -1) CloseResFile(refNum);
  337.     FlushVol(nil, dest->vRefNum);
  338.     return err;
  339. }
  340.  
  341. static OSErr SaveMacTCPConfigToFile (void)
  342. {
  343.     Str255 prompt;
  344.     StandardFileReply sfReply;
  345.     FSSpec fSpec;
  346.     FInfo fndrInfo;
  347.     OSErr err;
  348.  
  349.     GetIndString(prompt, kStringsID, kSaveAsPromptStr);
  350.     StandardPutFile(prompt, "\p", &sfReply);
  351.     if (!sfReply.sfGood) return userCanceledErr;
  352.     err = FindFolder(kOnSystemDisk, kPreferencesFolderType, true, 
  353.         &fSpec.vRefNum, &fSpec.parID);
  354.     if (err != noErr) return err;
  355.     GetIndString(fSpec.name, kStringsID, kMacTCPPrepStr);
  356.     err = FSpGetFInfo(&fSpec, &fndrInfo);
  357.     if (err == noErr) {
  358.         err = CopyResources(&fSpec, &sfReply.sfFile, kCreator, kFileType);
  359.         if (err == kErrOpeningSourceSettingsFile) {
  360.             /* If MacTCP Prep is damaged, trash it and use the MacTCP file instead. */
  361.             FSpDelete(&fSpec);
  362.         } else {
  363.             return err;
  364.         }
  365.     }
  366.     err = FindFolder(kOnSystemDisk, kControlPanelFolderType, true,
  367.         &fSpec.vRefNum, &fSpec.parID);
  368.     if (err != noErr) return err;
  369.     GetIndString(fSpec.name, kStringsID, kMacTCPStr);
  370.     err = FSpGetFInfo(&fSpec, &fndrInfo);
  371.     if (err != noErr) {
  372.         if (err == fnfErr) err = kErrMacTCPNotFound;
  373.         return err;
  374.     }
  375.     return CopyResources(&fSpec, &sfReply.sfFile, kCreator, kFileType);
  376. }
  377.  
  378. static pascal OSErr HandleAEOpenApp (AppleEvent *event, AppleEvent *reply, long refCon)
  379. {
  380.     OSErr err;
  381.  
  382.     err = SaveMacTCPConfigToFile();
  383.     if (err == userCanceledErr) return noErr;
  384.     if (err != noErr) goto exit;
  385.     return noErr;
  386.     
  387. exit:
  388.  
  389.     UnexpectedErrorMessage(err);
  390.     return err;
  391. }
  392.  
  393. static pascal OSErr HandleAEOpenDoc (AppleEvent *event, AppleEvent *reply, long refCon)
  394. {
  395.     OSErr err;
  396.     AEDescList docList;
  397.     long numItems;
  398.     AEKeyword keywd;
  399.     DescType returnedType;
  400.     Size actualSize;
  401.     FSSpec source, dest;
  402.     short itemHit;
  403.     
  404.     err = AEGetParamDesc(event, keyDirectObject, typeAEList, &docList);
  405.     if (err != noErr) goto exit;
  406.     err = AECountItems(&docList, &numItems);
  407.     if (err != noErr) goto exit;
  408.     if (numItems != 1) {
  409.         ErrorMessage(kCanOnlyOpenOneDocStr);
  410.         return noErr;
  411.     }
  412.     err = AEGetNthPtr(&docList, 1, typeFSS, &keywd, &returnedType,
  413.         (Ptr)&source, sizeof(source), &actualSize);
  414.     if (err != noErr) goto exit;
  415.     err = AEDisposeDesc(&docList);
  416.     if (err != noErr) goto exit;
  417.      while (true) {
  418.         gDialogCommandKeyItems[0].itemNumber = kSetMacTCPAlertSave;
  419.         gDialogCommandKeyItems[0].key = 'S';
  420.         MyModalDialog(kSetMacTCPAlert, kSetMacTCPAlertSet, kSetMacTCPAlertCancel,
  421.             source.name, "\p", 1, &itemHit);
  422.         if (itemHit == kSetMacTCPAlertSet) break;
  423.         if (itemHit == kSetMacTCPAlertCancel) return noErr;
  424.         if (itemHit == kSetMacTCPAlertSave) {
  425.             err = SaveMacTCPConfigToFile();
  426.             if (err == userCanceledErr) return noErr;
  427.             if (err != noErr) goto exit;
  428.         }
  429.     }
  430.     err = FindFolder(kOnSystemDisk, kPreferencesFolderType, true, 
  431.         &dest.vRefNum, &dest.parID);
  432.     if (err != noErr) goto exit;
  433.     GetIndString(dest.name, kStringsID, kMacTCPPrepStr);
  434.     err = CopyResources(&source, &dest, kMacTCPPrepCreator, kMacTCPPrepFileType);
  435.     if (err == kErrOpeningDestinationSettingsFile) {
  436.         /* If MacTCP Prep is damaged, trash it and recreate it. */
  437.         FSpDelete(&dest);
  438.         err = CopyResources(&source, &dest, kMacTCPPrepCreator, kMacTCPPrepFileType);
  439.     }
  440.     if (err != noErr) goto exit;
  441.     if (MacTCPIsOpen()) {
  442.         gDialogCommandKeyItems[0].itemNumber = kRestartAlertRestart;
  443.         gDialogCommandKeyItems[0].key = 'R';
  444.         MyModalDialog(kRestartAlert, ok, 0, "\p", "\p", 1, &itemHit);
  445.         if (itemHit == kRestartAlertRestart) Restart();
  446.     } else {
  447.         MyModalDialog(kMacTCPSetAlert, ok, 0, "\p", "\p", 0, nil);
  448.     }
  449.     return noErr;
  450.  
  451. exit:
  452.  
  453.     UnexpectedErrorMessage(err);
  454.     return err;
  455. }
  456.  
  457. static pascal OSErr HandleAEPrintDoc (AppleEvent *event, AppleEvent *reply, long refCon)
  458. {
  459.     return noErr;
  460. }
  461.  
  462. static pascal OSErr HandleAEQuit (AppleEvent *event, AppleEvent *reply, long refCon)
  463. {
  464.     return noErr;
  465. }
  466.  
  467. static void Init (void)
  468. {
  469.     EventRecord ev;
  470.     long systemVersion;
  471.     OSErr err;
  472.     Boolean haveSystem7;
  473.  
  474.     MaxApplZone();
  475.     
  476.     InitGraf(&qd.thePort);
  477.     InitFonts();
  478.     InitWindows();
  479.     InitMenus();
  480.     TEInit();
  481.     InitDialogs(nil);
  482.     InitCursor();
  483.  
  484.     FlushEvents(everyEvent,0);
  485.     EventAvail(everyEvent, &ev);
  486.  
  487.     haveSystem7 = TrapAvailable(_Gestalt);
  488.     if (haveSystem7) {
  489.         err = Gestalt(gestaltSystemVersion, &systemVersion);
  490.         haveSystem7 = err == noErr && systemVersion >= 0x0700;
  491.     }
  492.     if (!haveSystem7) {
  493.         StopAlert(kNeedSystem7Alert, nil);
  494.         ExitToShell();
  495.     }
  496.  
  497.     SetMenuBar(GetNewMBar(kMBarID));
  498.     AddResMenu(GetMHandle(kAppleMenu), 'DRVR');
  499.     DrawMenuBar();
  500.  
  501.     AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
  502.         HandleAEOpenApp, 0, false);
  503.     AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
  504.         HandleAEOpenDoc, 0, false);
  505.     AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
  506.         HandleAEPrintDoc, 0, false);
  507.     AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
  508.         HandleAEQuit, 0, false);
  509. }
  510.  
  511. static void MainEvent (void)
  512. {
  513.     EventRecord ev;
  514.     Boolean    gotEvt;
  515.  
  516.     while (true) {
  517.         gotEvt = WaitNextEvent(everyEvent, &ev, 10, nil);
  518.         if (gotEvt && ev.what == kHighLevelEvent) {
  519.             AEProcessAppleEvent(&ev);
  520.             break;
  521.         }
  522.     }
  523. }
  524.  
  525. void main (void)
  526. {
  527.     Init();
  528.     MainEvent();
  529. }
  530.