home *** CD-ROM | disk | FTP | other *** search
- /* Diavolo CLI Control */
-
- #define VERSION "1.1"
-
- /*
-
- This file is meant as an example for programming the Diavolo Application Programming
- Interface.
-
- It can be used to start and monitor a backup procedure from the CLI. Therefor it is
- possible to make automated backups with Cron tables.
-
-
- This source was written and tested using SAS/C 6.55
-
- For a detailed documentation of the API see DiavoloAPI.h and DiavoloPrefs.h.
-
-
- If you want to print this file, set your printer to 136 characters per line (condensed font).
-
-
- © 1995 Martin Korndörfer.
-
- History:
-
- 1.1
- ---
-
- - Disabled SAS Break Handling
- - Adapted to new API Port name
- */
-
- /* *********************************************************************** */
- /* *********************************************************************** */
- /* */
- /* Includes */
- /* */
- /* *********************************************************************** */
- /* *********************************************************************** */
-
-
- #include <clib/locale_protos.h> /* Contains all prototypes for Amiga functions. May
- have a different name when using another compiler */
-
-
- #include <dos/dos.h>
- #include <dos/dostags.h>
- #include <exec/exec.h>
- #include <stdio.h>
- #include <string.h>
-
- #include "sas:Diavolo/DiavoloPrefs.h" /* Contains documented preference structure and constants */
- #include "sas:Diavolo/DiavoloAPI.h" /* Structures, constants and documentation of Diavolo API */
-
-
- int CXBRK(void) { return(0); } /* Disable Lattice Ctrl-C Handl. */
- void __regargs __chkabort(void) { }
-
-
- /* *********************************************************************** */
- /* *********************************************************************** */
- /* */
- /* ReadArgs() definitions */
- /* */
- /* *********************************************************************** */
- /* *********************************************************************** */
-
- /* This is the CLI template for DiavoloCLICtrl.
-
- Filter: Filename of filter to select files and partitions to backup.
- Must be given.
-
- Config: Name of a Diavolo configuration file. This file will be used for
- all options as for the backup destination as well.
- Must be given.
-
- Name: Name for backup.
-
- AutoCompare: Compare backup after completion
-
- Overwrite: Only for backup to SCSI tape: Number of backup to overwrite.
- 0: Ask user
- 1: Overwrite tape from beginning
- 2..x: Overwrite beginning with backup no. x
- If not given: Append to tape.
-
- Password: Password for the backup. Can be omitted.
-
- Encode: Only valid with a password set. Encode the backup with the given
- backup.
-
- DoNotStartDiavolo: The program will try to start Diavolo when it is not present.
- If this options is set, the program will fail instead.
- */
-
- #define ARG_TEMPLATE "Filter/A,Config/A,Name,AutoCompare/S,Overwrite/K/N,PW=Password/K,Encode/S,ER=ErrorReport,FR=FileReport,DoNotStartDiavolo/S"
- #define ARG_MAX 10
-
- #define ARG_FILTER 0
- #define ARG_CONFIG 1
- #define ARG_NAME 2
- #define ARG_AUTOCOMPARE 3
- #define ARG_OVERWRITE 4
- #define ARG_PASSWORD 5
- #define ARG_ENCODE 6
- #define ARG_ERRORREP 7
- #define ARG_FILEREP 8
- #define ARG_DONTSTARTDB 9
-
- #define ARG_FILTER_DEF NULL
- #define ARG_CONFIG_DEF NULL
- #define ARG_NAME_DEF NULL
- #define ARG_AUTOCOMPARE_DEF FALSE
- #define ARG_OVERWRITE_DEF NULL
- #define ARG_PASSWORD_DEF NULL
- #define ARG_ENCODE_DEF FALSE
- #define ARG_ERRORREP_DEF NULL
- #define ARG_FILEREP_DEF NULL
- #define ARG_DONTSTARTDB_DEF FALSE
-
- LONG ArgArray[ARG_MAX];
-
-
- /* *********************************************************************** */
- /* *********************************************************************** */
- /* */
- /* Global variables */
- /* */
- /* *********************************************************************** */
- /* *********************************************************************** */
-
- #define FETT "\x1b[1m" /* For CLI output, boldface on and off */
- #define NORM "\x1b[0m"
-
- struct MsgPort *MyReplyPort; /* Global Reply Port. Will be used by Diavolo to send its
- messages to the client */
-
- struct MsgPort *APIPort; /* API Port of Diavolo Backup. Global message port which
- must be used to send messages to Diavolo */
-
- BOOL Quit; /* TRUE: Quit requested by Diavolo */
-
- BOOL Break; /* TRUE: Ctrl-C pressed */
-
- char Version[] = "$VER:DBCLICtrl "VERSION" "__AMIGADATE__;
-
-
- /* *********************************************************************** */
- /* *********************************************************************** */
- /* */
- /* Forward function declarations */
- /* */
- /* *********************************************************************** */
- /* *********************************************************************** */
-
-
- void CheckDAPIMsg(struct DiavoloAPIMsg *APIMsg);
-
-
- /* *********************************************************************** */
- /* *********************************************************************** */
- /* */
- /* Frame functions, use them in your code */
- /* */
- /* *********************************************************************** */
- /* *********************************************************************** */
-
- void CheckRequest(struct DiavoloAPIMsg *APIMsg)
-
- /* Will be used to process incoming request messages. After a client has made contact with
- Diavolo, before a requester is displayed to the user, a message will be sent to the client.
- The client can answer this request itself, so the user never sees the request, or make Diavolo
- display the request as normal. Anyway, the client MUST reply the request as fast as possible,
- so the message port must be always watched for incoming messages. If the client does not reply
- a message, there could be a deadlock (Diavolo waiting for client and client waiting for
- Diavolo).
-
- Modify this routine to customize the clients reaction to requesters. Look at the DAPI_RC_...
- defines at the end of DiavoloAPI.h for all possible request codes and their meaning.
-
- */
-
- {
- ULONG RetVal;
- static BOOL DirDiskRequested = FALSE;
-
-
- /* This switch/case statement decides what to do with the requester. */
-
- switch(APIMsg->DAPI_Arg1)
- {
- /* The following requests will not be displayed to the user. Instead Diavolo reacts as if
- the user had pressed RETRY. */
-
- case DAPI_RC_INSERTDISK: /* Insert disk in any drive... */
- case DAPI_RC_BACKDISK: /* This disk contains another backup... */
- case DAPI_RC_DOSDISK: /* This disk is DOS formatted ... */
- case DAPI_RC_ALIENTAPE: /* This tape contains unreadable data or is empty ... */
- case DAPI_RC_FILEEXISTS: /* Backup file already exists, overwrite? ... */
-
- RetVal = 1; /* RetVal will be used as a replycode to Diavolo.
- 1 means the leftmost option, in these cases RETRY. */
- break;
-
- case DAPI_RC_INSERTDIRDISK: /* Insert first disk in any drive.
- This request can be replied with 1 when it is made the
- first time. Maybe the first disk is already present.
- If the request repeats, show it to the user though. */
- if(DirDiskRequested)
- RetVal = ~0;
- else
- {
- RetVal = 1;
- DirDiskRequested = TRUE;
- }
- break;
-
- default: /* In all other cases... */
-
- RetVal = ~0; /* A RetVal of ~0 (bitwise NOT 0, in other words all bits set)
- means that Diavolo should display the requester as normal */
- }
-
- APIMsg->DAPI_Arg1 = RetVal; /* Return the message with RetVal set in Arg1 */
- ReplyMsg(APIMsg);
- }
-
-
-
-
- void CheckDAPIMsg(struct DiavoloAPIMsg *APIMsg)
-
- /* Check incoming messages. */
-
- {
- /* Look if the received message was a reply. Normally replies will only return after you've sended
- a message to Diavolo in the first place. This example is written in a way, that every
- routine knows its sent messages and handles their replies itself, so this generic routine
- should never has to handle replies. */
- if(APIMsg->DAPI_Message.mn_Node.ln_Type == NT_REPLYMSG)
- {
- printf("Reply received. Don't know original message. ERROR!\n");
- }
-
- else
- {
- /* What kind of message is this? */
-
- switch(APIMsg->DAPI_Command)
- {
- case DAPI_REQUEST:
- /* Diavolo has a request. CheckRequest (see above) handles them */
- CheckRequest(APIMsg);
- break;
-
- case DAPI_CLOSEDOWN:
- /* Diavolo is closing down. The client is informed that it has to cut down
- the link to Diavolo, so it can complete the closedown. */
-
- Quit = TRUE; /* Set global Quit flag to TRUE */
- ReplyMsg(APIMsg); /* Return message */
- break;
-
- default:
- /* Another - unknown - message has arrived. Diavolo only sends the two
- messages handled above or replies. */
-
- printf("Unknown message. Command: %lx\n",APIMsg->DAPI_Command);
- ReplyMsg(APIMsg);
- break;
- }
- }
- }
-
-
-
- BOOL DoCommand(struct DiavoloAPIMsg *APIMsg)
-
- /* Send a command to Diavolo and wait for its completion (its reply).
-
- This routine handles all incoming message (also requests) and waits until the command
- was replied.
-
- Use this for all commands you want to send synchronously (which should be most). You
- cannot use them for asynchronous command, which are used to initiate an operation.
- These are DAPI_STARTBACKUP, DAPI_STARTSCAN and DAPI_STARTRESTORE. This application
- doesn't need to use these commands asynchronously, though, so they are handled by
- this routine anyway.
-
- The parameter APIMsg must be filled with the correct parameters you want to send to
- Diavolo (also the command code itself). After the routine replies you can find the
- result codes set by Diavolo in the same structure.
- */
-
- {
- struct DiavoloAPIMsg *Reply;
- BOOL Ok;
-
- /* Set Replyport of the message to send to the global client message port */
- APIMsg->DAPI_Message.mn_ReplyPort = MyReplyPort;
-
- /* Send the message to Diavolo's API Port */
- PutMsg(APIPort, APIMsg);
-
- do
- {
- /* This is a generic method of waiting for a message. If you want to check more
- than one message port, you'll have to add more bits to the Wait() mask. */
-
- while(! (Reply = (struct DiavoloAPIMsg *)GetMsg(MyReplyPort)))
- Wait(1l << MyReplyPort->mp_SigBit);
-
- if(Reply->DAPI_Message.mn_Node.ln_Type != NT_REPLYMSG || Reply != APIMsg)
- {
- /* The received message wasn't the reply for our own message, so process it */
-
- CheckDAPIMsg(Reply);
- Reply = NULL; /* No, we're not finished yet */
- }
- else
- {
- /* Our message has been replied. Fine, now look if there was an error
- set in the reply: */
-
- switch(Reply->DAPI_Errorcode)
- {
- case DAPI_EC_NOERROR:
- /* Everything was fine! */
-
- Ok = TRUE;
- break;
-
- case DAPI_EC_INUSE:
- /* Diavolo's messageport is in use by another application */
-
- printf("Reply: In Use error\n");
- Ok = FALSE;
- break;
-
- case DAPI_EC_NOTAVAILABLE:
- /* The sent command is not available at this moment or entirely unknown */
-
- printf("Reply: Command not available!\n");
- Ok = FALSE;
- break;
-
- case DAPI_EC_NOTMETYET:
- /* You have not intiated the dialogue using DAPI_RENDEZVOUS yet */
-
- printf("Reply: Programs not met yet!\n");
- Ok = FALSE;
- break;
-
- case DAPI_EC_INVALIDCONFIG:
- /* The new configuration was invalid */
-
- printf("Reply: Invalid config!\n");
- Ok = FALSE;
- break;
-
- case DAPI_EC_SELECTFAILED:
- /* The selection (in DAPI_BACKSELECT and DAPI_RESTSELECT) failed */
-
- printf("Reply: Selection failed. Code: %ld!\n", Reply->DAPI_Arg1);
- Ok = FALSE;
- break;
-
- case DAPI_EC_OPPENDING:
- /* You cannot cut the connection (using DAPI_GOODBYE) while a client
- intiated operation is in progress. Cancel the operation first! */
-
- printf("Reply: Operation pending, Goodbye not possible!\n");
- Ok = FALSE;
- break;
-
- case DAPI_EC_OPFAILED:
- /* The oepration failed */
-
- printf("Reply: Operation failed, Code: %ld!\n",Reply->DAPI_Arg1);
- Ok = FALSE;
- break;
-
- default:
- printf("Unknown errorcode: %ld\n",Reply->DAPI_Errorcode);
- Ok = FALSE;
- }
- }
- }
- while(Reply == NULL);
- return(Ok);
- }
-
-
-
-
- int main(int argc, char **argv)
-
- {
- struct DiavoloAPIMsg APIMsg;
- BOOL Ok, DBStarted;
- struct RDArgs *ArgRDArgs;
- char RendezvousName[30];
-
-
- /* Reset argument array with the default values for ReadArgs() */
-
- ArgArray[ARG_FILTER] = ARG_FILTER_DEF;
- ArgArray[ARG_CONFIG] = ARG_CONFIG_DEF;
- ArgArray[ARG_NAME] = ARG_NAME_DEF;
- ArgArray[ARG_AUTOCOMPARE] = ARG_AUTOCOMPARE_DEF;
- ArgArray[ARG_OVERWRITE] = ARG_OVERWRITE_DEF;
- ArgArray[ARG_PASSWORD] = ARG_PASSWORD_DEF;
- ArgArray[ARG_ENCODE] = ARG_ENCODE_DEF;
- ArgArray[ARG_ERRORREP] = ARG_ERRORREP_DEF;
- ArgArray[ARG_FILEREP] = ARG_FILEREP_DEF;
- ArgArray[ARG_DONTSTARTDB] = ARG_DONTSTARTDB_DEF;
-
-
- /* Call ReadArgs() to parse and interprete the command line parameters */
-
- printf(FETT"DBCLICtrl"NORM" - Diavolo Backup Command Line Interface Control\n");
- printf(FETT"V "VERSION" © 1995"NORM" Martin Korndörfer\n\n");
-
- if(! (ArgRDArgs = ReadArgs(ARG_TEMPLATE,ArgArray,NULL)))
- {
- printf("Wrong argument(s)!\n\n");
- printf("Template: "FETT"%s %s"NORM"\n\n",argv[0],ARG_TEMPLATE);
- printf(FETT"Usage: %s"NORM" Filter Config [BackupName] [AUTOCOMPARE] [OVERWRITE x]\n",argv[0]);
- printf(" [PW Password] [ENCODE] [ER File] [FR File] [DONOTSTARTDIAVOLO]\n\n");
- printf(" "FETT"Parameters:"NORM" \n\n");
- printf(" "FETT"Filter"NORM" Filename of filter for file selection\n");
- printf(" "FETT"Config"NORM" Filename of configuration file\n");
- printf(" "FETT"BackupName"NORM" Name of Backup (optional)\n");
- printf(" "FETT"AUTOCOMPARE"NORM" Compare backup (switch)\n");
- printf(" "FETT"OVERWRITE x"NORM" SCSITape: x=Backupnr. to overwrite, 0 ask,\n");
- printf(" append to EOT if omitted\n");
- printf(" "FETT"PW Password"NORM" Password to protect backup with\n");
- printf(" "FETT"ENCODE"NORM" Only with PW set: Encode backup\n");
- printf(" "FETT"ER File"NORM" Write error report to file\n");
- printf(" "FETT"FR File"NORM" Write file list report to file\n");
- printf(" "FETT"DONOTSTARTDIAVOLO"NORM" Do not try to start Diavolo if not present\n\n");
-
- return(20);
- }
-
-
- /* First create our own message port */
-
- if(! (MyReplyPort = CreateMsgPort()))
- {
- printf("Error creating own message port!\n");
- return(30); /* Failed */
- }
-
-
- /* Use forbid to secure the FindPort Operation (suggested in Exex autodocs) */
-
- Forbid();
-
-
- /* Look for Diavolo message port. This will only look for Diavolo.1 */
-
- sprintf(RendezvousName,RENDEZVOUS_NAME,1);
-
- if(! (APIPort = FindPort(RendezvousName)))
- {
- Permit();
- /* Message port not found. Now, if not forbidden, start Diavolo */
-
- if(ArgArray[ARG_DONTSTARTDB])
- {
- DeleteMsgPort(MyReplyPort);
- printf("Diavolo port not found!\n");
- return(20);
- }
-
-
- /* Diavolo detaches itself from the parent task, so there is no need to start Diavolo
- asynchronously. */
-
- if(SystemTags("Diavolo",
- NP_StackSize, 10000,
- NP_Name, "Diavolo",
- TAG_DONE))
- {
- printf("Couldn't start Diavolo!\n");
- DeleteMsgPort(MyReplyPort);
- return(20);
- }
-
- DBStarted = TRUE; /* Diavolo was started by DBCLICtrl */
-
- Delay(100); /* Wait 2 seconds until DB has initialized its rendezvous port */
-
-
- Forbid();
-
- /* Look for Diavolo message port */
-
- if(! (APIPort = FindPort(RendezvousName)))
- {
- Permit();
- printf("Couldn't find Diavolo API port!\n");
- DeleteMsgPort(MyReplyPort);
- return(20);
- }
- }
- else
- DBStarted = FALSE;
-
-
- Permit();
-
- /* Before any action can take place, The client must first make a connection
- with Diavolo.
-
- Diavolo will use the given ReplyPort to send its messages to the client
- as long as the connection is active. */
-
- APIMsg.DAPI_Command = DAPI_RENDEZVOUS;
- Ok = DoCommand(&APIMsg);
-
- if(! Ok)
- printf("Rendezvous with Diavolo failed!\n");
- else
- {
- /* While the client is preparing an operation, any user interference might
- have unwanted results, so it's better to disable the user interface. */
-
- APIMsg.DAPI_Command = DAPI_LOCKUI;
- APIMsg.DAPI_Arg1 = TRUE; /* Lock active */
- Ok = DoCommand(&APIMsg);
-
- if(! Ok)
- printf("Lock user interface failed!\n");
- }
-
- if(Ok)
- {
- /* This function initiates the backup, just the same as when the user presses
- the button "Backup" in the main menu. The Device Selection window will open
- then. */
-
- APIMsg.DAPI_Command = DAPI_INITBACKUP;
- Ok = DoCommand(&APIMsg);
- if(! Ok)
- printf("Backup initialization failed!\n");
- }
-
- if(Ok)
- {
- /* There may be a previous file selection active in Diavolo. Before the client
- makes its own selection, it should make sure that there is no previous selection
- active. */
-
- APIMsg.DAPI_Command = DAPI_CLEARLISTS;
- Ok = DoCommand(&APIMsg);
- if(! Ok)
- printf("Clearing selection lists failed!\n");
- }
-
- if(Ok)
- {
- /* The configuration file given in the arguments must be loaded. */
-
- APIMsg.DAPI_Command = DAPI_LOADCONFIG;
- APIMsg.DAPI_Ptr1 = (APTR)ArgArray[ARG_CONFIG];
- Ok = DoCommand(&APIMsg) && APIMsg.DAPI_Arg1; /* Success will be reported in Arg1 */
- if(! Ok)
- printf("Couldn't read configuration file!\n");
- }
-
- if(Ok)
- {
- /* Use the specified filter file to make the selections. */
-
- APIMsg.DAPI_Command = DAPI_USEFILTER;
- APIMsg.DAPI_Ptr1 = (APTR)ArgArray[ARG_FILTER];
- Ok = DoCommand(&APIMsg);
- if(Ok)
- {
- printf("Files selected: %ld, Size of backup: %ld\n",APIMsg.DAPI_Arg3,APIMsg.DAPI_Arg4);
- Ok = (APIMsg.DAPI_Arg4 != 0);
- }
- if(! Ok)
- printf("Fileselection failed!\n");
- }
-
- if(Ok)
- {
- /* Before starting the backup procedure itself, the user interface lock should be
- removed, so that the user has a chance of interrupting the backup. */
-
- APIMsg.DAPI_Command = DAPI_LOCKUI;
- APIMsg.DAPI_Arg1 = FALSE; /* Lock not active */
- Ok = DoCommand(&APIMsg);
-
- if(! Ok)
- printf("Unlock user interface failed!\n");
- }
-
- if(Ok)
- {
- /* This command now starts the backup procedure. All parameter normally given
- by the user before starting the backup (i.e. Backup name, password etc.)
- must be given through this command. The message will not be replied until
- the backup procedure is complete or cancelled. */
-
- APIMsg.DAPI_Command = DAPI_STARTBACKUP;
- APIMsg.DAPI_Arg1 = ArgArray[ARG_PASSWORD] != NULL; /* Use PW if parameter given */
- APIMsg.DAPI_Arg2 = (BOOL)ArgArray[ARG_ENCODE];
- if(ArgArray[ARG_OVERWRITE])
- APIMsg.DAPI_Arg3 = *((LONG *)ArgArray[ARG_OVERWRITE]);
- else
- APIMsg.DAPI_Arg3 = ~0; /* Append */
-
- if(ArgArray[ARG_NAME])
- APIMsg.DAPI_Ptr1 = (APTR)ArgArray[ARG_NAME];
- else
- APIMsg.DAPI_Ptr1 = "Automated backup by DiavoloCLICtrl";
-
- APIMsg.DAPI_Ptr2 = (APTR)ArgArray[ARG_PASSWORD];
-
- Ok = DoCommand(&APIMsg);
- if(Ok)
- printf("Time for backup: %ld seconds\n",APIMsg.DAPI_Arg3);
- else
- printf("Backup procedure failed!\n");
- }
-
- if(Ok && ArgArray[ARG_AUTOCOMPARE])
- {
- /* The backup procedure has been completed, so if the respective option was
- set in the command line, start the auto compare procedure. */
-
- APIMsg.DAPI_Command = DAPI_COMPAREBACKUP;
-
- Ok = DoCommand(&APIMsg);
- if(Ok)
- printf("Time for compare: %ld seconds\n",APIMsg.DAPI_Arg2);
- else
- printf("Compare procedure failed!\n");
- }
-
- if(Ok && ArgArray[ARG_ERRORREP])
- {
- /* Eventually, after all procedures have been completed, and the respective
- option was given, create the error report */
-
- APIMsg.DAPI_Command = DAPI_CREATEREPORT;
- APIMsg.DAPI_Arg1 = FALSE; /* Create errorlist */
- APIMsg.DAPI_Ptr1 = (APTR)ArgArray[ARG_ERRORREP];
-
- Ok = DoCommand(&APIMsg);
- if(! Ok)
- printf("Creation of error report failed!\n");
- }
-
- if(Ok && ArgArray[ARG_FILEREP])
- {
- /* ... and the filelist report */
-
- APIMsg.DAPI_Command = DAPI_CREATEREPORT;
- APIMsg.DAPI_Arg1 = TRUE; /* Create filelist */
- APIMsg.DAPI_Arg2 = TRUE; /* Use wide format */
- APIMsg.DAPI_Ptr1 = (APTR)ArgArray[ARG_FILEREP];
-
- Ok = DoCommand(&APIMsg);
- if(! Ok)
- printf("Creation of filelist report failed!\n");
- }
-
-
- /* The following commands should be executed, whether an error occured or not */
-
-
- /* Back to main menu */
-
- APIMsg.DAPI_Command = DAPI_MAINMENU;
- DoCommand(&APIMsg);
-
-
- /* Quit Diavolo Backup, only if started by DBCLICtrl */
-
- if(DBStarted)
- {
- APIMsg.DAPI_Command = DAPI_QUIT;
- DoCommand(&APIMsg);
- }
-
-
- /* Close down connection with Diavolo. This command MUST be given, if the client has
- connected with DAPI_RENDEZVOUS. If this command is not given, Diavolo will be unable
- to remove itself from memory and no other client can connect to Diavolo. */
-
- APIMsg.DAPI_Command = DAPI_GOODBYE;
- DoCommand(&APIMsg);
-
- DeleteMsgPort(MyReplyPort);
- FreeArgs(ArgRDArgs);
-
- if(Ok)
- return(0);
- else
- return(10);
- }
-