1
/* Copyright (c) 1996-2004, Adaptec Corporation
4
* Redistribution and use in source and binary forms, with or without
5
* modification, are permitted provided that the following conditions are met:
7
* - Redistributions of source code must retain the above copyright notice, this
8
* list of conditions and the following disclaimer.
9
* - Redistributions in binary form must reproduce the above copyright notice,
10
* this list of conditions and the following disclaimer in the documentation
11
* and/or other materials provided with the distribution.
12
* - Neither the name of the Adaptec Corporation nor the names of its
13
* contributors may be used to endorse or promote products derived from this
14
* software without specific prior written permission.
16
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26
* POSSIBILITY OF SUCH DAMAGE.
29
/* File - ENG_UNIX.C */
30
/*****************************************************************************/
33
/* This Module Contains Those Functions That Get Linked Into The */
34
/* Unix DPT Engine To Make It An Executable Program. */
37
/*Author: Bob Pasteur */
44
/*Modification History - Not implemented until going to version 1.D7 */
46
/* M0000 - 2/18/95 Bob Pasteur */
47
/* - Added more verbose print statements */
48
/* M0001 - 3/01/95 Bob Pasteur */
49
/* - Added UnixWare Support */
50
/* M0002 - 10/27/95 Bob Pasteur */
51
/* - Added a date/time value to the verbose print statements : Unmarked */
52
/* M0003 - 01/16/97 Bob Pasteur */
53
/* - Added support for DGUX */
55
/*****************************************************************************/
57
/*Include Files -------------------------------------------------------------*/
72
#include <sys/types.h>
78
#if (defined(__FreeBSD__))
79
# define _DPT_FREE_BSD
81
#if (defined(_DPT_BSDI) || defined(_DPT_FREE_BSD))
82
# include <sys/malloc.h>
103
/* Definitions - Defines & Constants ---------------------------------------*/
105
/* Definitions - Structure & Typedef ---------------------------------------*/
107
/* Variables - External ----------------------------------------------------*/
109
extern uLONG LoggerID;
111
/* Variables - Global ------------------------------------------------------*/
114
uCHAR *fromEng_P = NULL;
115
uCHAR *toEng_P = NULL;
125
ofstream est("/tmp/dpteng_dbg.log");
130
int EngineMessageTimeout = 0;
134
int NumOpenClients = 0;
136
struct msqid_ds CtlBuf;
137
static char TimeString[80];
139
/* Command Line Parameters Structure */
163
// For FindPath routine
170
/* Prototypes - function ---------------------------------------------------*/
172
int ProcessTurnAroundMessage(MsgHdr *HdrBuff_P);
173
void ProgramUnload(void);
174
void AlarmHandler(void);
175
uSHORT ParseCommandLine(int argc,char *argv[]);
176
void DisplayHelp(void);
178
// this is used to ignore the first signal sent to the engine when a shutdown command occurs
179
void DptSignalIgnore(int);
181
/* Prototypes - external function ------------------------------------------*/
183
extern void FormatTimeString(char *String,uLONG Time);
185
extern void SNI_set_compile_date(dpt_sig_S *);
186
extern dpt_sig_S engineSig;
189
/***************************** Main Entry Point *****************************/
191
main(int argc, char *argv[])
195
struct sigaction sig;
199
// Set up our argument pointers for others to use
205
# if (defined(_DPT_SOLARIS) || defined(_DPT_ROOTONLY))
206
// Only root or sys are allowed to run dptutil.
207
if ( ( getuid () != 0 ) && ( geteuid () != 0 )
208
&& ( getuid () != 3 ) && ( geteuid () != 3 )
209
&& ( getgid () != 0 ) && ( getegid () != 0 )
210
&& ( getgid () != 3 ) && ( getegid () != 3 ) )
212
printf ("You must be root to run this utility\n");
217
/* Parse The Command Line Parameters, And If An Error Exit */
219
if(ParseCommandLine(argc,argv)) {
220
exit(ExitBadParameter);
224
DEBUG_SETOUTPUT(est);
226
DEBUG_BEGIN(5, "DPT Engine");
227
DEBUG_SETLEVEL(DebugToFile);
230
SNI_set_compile_date(&engineSig);
232
printf("%s: V.%d.%c%c %.2d.%.2d.%d\n", engineSig.dsDescription, engineSig.dsVersion,
233
engineSig.dsRevision, engineSig.dsSubRevision, engineSig.dsDay,
234
engineSig.dsMonth, 1980 + engineSig.dsYear);
235
exit(ExitGoodStatus);
238
DEBUG_SETOUTPUT(cerr);
242
/* Check To See If There Is Already An Engine Out There */
244
if (MkLock(NULL) == 1) {
249
"\nThere Appears To Be Another Copy Of dpteng Already Running!\n");
250
exit(ExitDuplicateEngine);
253
/* If The Engine Cannot Be Opened, Print A Message And Exit */
255
i = DPT_StartEngine();
256
if(i != MSG_RTN_COMPLETED)
260
printf("\nStarting the Engine: ");
261
if (i == ERR_OSD_OPEN_ENGINE)
262
printf("Open HBA(s) ");
263
else if (i == ERR_SEMAPHORE_ALLOC)
264
printf("Alloc Semaphore ");
265
else if (i == ERR_CONN_LIST_ALLOC)
266
printf("Alloc Connection List ");
268
printf(" With Unknown Error %x", i);
273
exit(ExitEngOpenFail);
276
/* Initialize The Signaling */
278
memset((void *)&sig,0,sizeof(sig));
281
#if defined ( _DPT_SCO ) || defined ( _DPT_AIX ) || defined( _DPT_BSDI ) || defined(_DPT_FREE_BSD ) || defined(_DPT_LINUX)
282
sig.sa_handler = (void (*)(int))AlarmHandler;
284
#elif defined ( _DPT_SOLARIS )
285
sig.sa_handler = (void (*)(int))AlarmHandler;
287
/* M0001 - Added UnixWare Support */
289
#elif defined ( _DPT_UNIXWARE )
290
sig.sa_handler = (void (*)(int))AlarmHandler;
292
/* M0001 - Added UnixWare DGUX */
293
#elif defined ( _DPT_DGUX )
294
sig.sa_handler = (void (*)_PROTO_ARGS((int)))AlarmHandler;
296
#elif defined ( SNI_MIPS )
297
sig.sa_handler = (void (*)())AlarmHandler;
299
#error Define this for your OS
304
#if defined(_DPT_SCO) || defined(_DPT_BSDI) || defined(_DPT_FREE_BSD) || defined(_DPT_LINUX) || defined (_DPT_SOLARIS)
305
// ignore sighup, sigterm will come later after a few seconds
306
signal(SIGHUP, (void (*) (int)) DptSignalIgnore);
307
signal(SIGTERM, (void (*) (int)) DptSignalIgnore);
308
signal(SIGCHLD, (void (*) (int)) DptSignalIgnore);
310
#error Define me. These are shutdown signals to ignore so the SOC logger
311
// can write its final heartbeat on a shutdown
314
#endif //#ifdef NEW_LOGGER
316
/* If The Signaling Could Not Be Set Up, Print An Error And Exit */
318
if(sigaction(SIGALRM,&sig,0) == -1)
321
printf("\nSignaling Could Not Be Set Up\n");
323
exit(ExitSignalFail);
326
/* if no debug mode selected, start engine as daemon (like inetd) */
327
/* i.e. fork son proc and create new session id. - michiz */
328
if (!Verbose && !EataHex && !EataInfo && !DebugEngMsg) {
330
if ((i = fork()) != 0) {
340
/* New option -stop to kill a hanged up engine */
343
struct msqid_ds CtlBuf;
344
MsqID = msgget(DPT_EngineKey, MSG_ALLRD | MSG_ALLWR);
346
msgctl(MsqID, IPC_STAT, &CtlBuf);
347
// Stop engine only, if no dptmgr still running
348
if ( CtlBuf.msg_lspid && CtlBuf.msg_lrpid &&
349
(getpgid(CtlBuf.msg_lspid) != -1) &&
350
(getpgid(CtlBuf.msg_lrpid) != -1))
351
printf("You must stop dptmgr first\n");
353
i = MessageDPTEngine(DPT_EngineKey, MsqID, ENGMSG_CLOSE, 2,1);
355
msgctl(MsqID, IPC_RMID, &CtlBuf);
357
printf("dpteng successfully stopped\n");
361
exit(ExitGoodStatus);
364
/* Check To See If There Is Already An Engine Out There */
366
MsqID = CheckForEngine(DPT_EngineKey,1,2);
373
"\nThere Appears To Be Another Copy Of dpteng Already Running!\n");
375
exit(ExitDuplicateEngine);
378
/* Get The Process ID To Use As The Unique Caller ID */
382
/* Try To Create The Unique Message Que Of This ID */
384
MsqID = msgget(DPT_EngineKey,IPC_CREAT | IPC_EXCL | MSG_ALLRD | MSG_ALLWR);
386
/* If We Could Not Allocate The Message Que, Print A Message And Exit */
391
printf("\nThe Message Queue Could Not Be Allocated\n");
393
exit(ExitMsqAllocFail);
396
/* Set Up The Function To Call When The Program Terminates Normally */
398
atexit(ProgramUnload);
400
/* Loop Forever Waiting For A Header Message To Come In. Once A Header */
401
/* Message Is Received, We Will Attach To The Shared Memory Segment */
402
/* That Is Passed In The Header. This Memory Is The In And Out Buffers */
406
printf("\ndpteng Is Ready.\n");
410
// At the top of the loop, we will pull off and process all turnaround messages on the queue since
411
// they don't have to be sent down to the engine
413
while(Rtnval = msgrcv(MsqID,(struct msgbuf *)&HdrBuff, MsgDataSize, DPT_TurnAroundKey,IPC_NOWAIT) != -1)
415
Done = ProcessTurnAroundMessage(&HdrBuff);
419
// If Done is set, there are no more clients, so let's
420
// check for any messages in the queue before we exit. It
421
// is possible that someone is trying to load and we don't
422
// want to pull the rug out from under him
426
Rtnval = msgrcv(MsqID,(struct msgbuf *)&HdrBuff,
427
MsgDataSize, -DPT_EngineKey,IPC_NOWAIT);
429
// If the call failed, were OUT-O-HERE
435
printf("\n : No Clients, Engine Unloads");
441
// There was a message on the queue so continue processing
447
// Done is not set, so wait for a message to come in
450
while(Rtnval = msgrcv(MsqID,(struct msgbuf *)&HdrBuff,
451
MsgDataSize, -DPT_EngineKey,0) == -1)
454
/* If The Message Failed, And The Reason Was Not An Interrupt, Exit */
461
/* If The Message Received OK Go Process It */
466
// Check to make sure this guy is still out there before processing the message
467
// if not, throw away the message
469
if(kill(HdrBuff.callerID,0) != 0)
473
printf("\n : Message received for PID %d : no process found, discarding",
479
/* If This Is A Turnarround Message, Process it */
481
if((HdrBuff.engineTag == HdrBuff.callerID)&&
482
(HdrBuff.engineTag == HdrBuff.targetTag))
484
Done = ProcessTurnAroundMessage(&HdrBuff);
488
/* Attach To The Shared Memory */
490
toEng_P = (uCHAR *)shmat((int)HdrBuff.BufferID,0,0);
492
/* Make Sure That We Could Attach */
494
if((int)toEng_P != -1)
496
fromEng_P = toEng_P + HdrBuff.FromEngBuffOffset;
498
/* M0000 : New Verbose Statements */
501
FormatTimeString(TimeString,time(0));
502
printf("\nEngine Calls : %s DPT_CallEngine",TimeString);
504
"\n EngTag = %x, Event = %x, Target = %x",
505
HdrBuff.engineTag,HdrBuff.engEvent,HdrBuff.targetTag);
507
"\n Offset = %x fromEng_P = %x toEng_P = %x",
508
HdrBuff.FromEngBuffOffset, fromEng_P, toEng_P);
510
"\n EngTag = %x, Event = %x, Target = %x",
511
HdrBuff.engineTag,HdrBuff.engEvent,HdrBuff.targetTag);
516
/* All Went Well With The Receive, So Call The Engine */
518
HdrBuff.result = DPT_Engine( HdrBuff.engineTag,
525
// Detach from the memory segment
527
shmdt((char *)toEng_P);
530
// Check to make sure this guy is still out there before returning the message
531
// if not, throw away the message
533
if(kill(HdrBuff.callerID,0) != 0)
537
printf("\n : Returning message for PID %d : no process found, discarding",
543
/* Set Up The Proper Message Type In The Buffer Headers */
545
HdrBuff.MsgID = HdrBuff.callerID;
546
HdrBuff.callerID = DPT_EngineKey;
547
Rtnval = msgsnd(MsqID,(struct msgbuf *)&HdrBuff,MsgDataSize,0);
549
/* If We Had An Error Sending, Print A Message And Exit */
555
FormatTimeString(TimeString,time(0));
557
"\n%s Error Sending A Message In The Engine : %d\n",
562
exit(ExitMsgSendFail);
566
else printf("\nError Trying To Attach To The Memory");
570
/* If We Had An Error Receiving, Print A Message And Exit */
575
FormatTimeString(TimeString,time(0));
577
"\n%s Error Receiving A Message In The Engine : %d\n",
582
exit(ExitMsgReceiveFail);
586
} //main(int argc, char *argv[])
588
/*-------------------------------------------------------------------------*/
589
/* Function ProcessTurnAroundMessage */
590
/*-------------------------------------------------------------------------*/
591
/* The Parameters Passed To This Function Are : */
592
/* HdrBuff_P : Pointer to a received message header buffer */
597
/*-------------------------------------------------------------------------*/
599
int ProcessTurnAroundMessage(MsgHdr *HdrBuff_P)
604
switch(HdrBuff_P->engEvent)
607
// For An Open, Bump the Number Of Clients
613
FormatTimeString(TimeString,time(0));
614
printf("\nEngine Calls : %s DPT_OpenEngine", TimeString);
621
// For a close, Decrement The Number Of Clients, And If This Was The
622
// Last Client And The No Kill Is Not Set, Set Up To Exit
627
FormatTimeString(TimeString,time(0));
628
printf("\nEngine Calls : %s DPT_CloseEngine", TimeString);
631
if(NumOpenClients > 0)
635
if(NumOpenClients <= 0)
645
// For An Echo, All That Is Needed Is The Return Message
650
FormatTimeString(TimeString,time(0));
651
printf( "\nEngine Calls : %s Engine Echo Message", TimeString);
656
} //switch(HdrBuff_P->engEvent)
659
// Make sure this guy is still out there before putting the message back on the queue
661
if(kill(HdrBuff_P->callerID,0) == 0)
665
// Set Up And Return The Message
667
HdrBuff_P->MsgID = HdrBuff_P->callerID;
668
HdrBuff_P->callerID = P_ID;
669
Rtnval = msgsnd(MsqID,(struct msgbuf *)HdrBuff_P,MsgDataSize,0);
672
// If We Had An Error Sending, Print A Message And Exit
678
FormatTimeString(TimeString,time(0));
679
printf( "\n%s Error Sending A Message In The Engine : %d\n", TimeString,errno);
683
exit(ExitMsgSendFail);
686
} //if(kill(HdrBuff_P->callerID,0) == 0)
690
printf("\n : Returning message for PID %d : no process found, discarding",
691
HdrBuff_P->callerID);
697
} //int ProcessTurnAroundMessage(MsgHdr *HdrBuff_P)
703
/*-------------------------------------------------------------------------*/
704
/* Function ProgramUnload */
705
/*-------------------------------------------------------------------------*/
706
/* There Are No Parameters Passed To This Function */
708
/* This Function Is Called On Normal Program Termination. It Makes A Close */
709
/* Call To The Engine And Frees Up The Message Queue That Was Allocated */
712
/*-------------------------------------------------------------------------*/
714
void ProgramUnload(void)
717
/* On The Way Out, Close The Engine, Free Up The Message Que And Buffers */
721
msgctl(MsqID,IPC_RMID,&CtlBuf);
724
/*-------------------------------------------------------------------------*/
725
/* Function AlarmHandler */
726
/*-------------------------------------------------------------------------*/
727
/* There Are No Parameters Passed To This Function */
729
/* This Function Is Called When The Alarm Signal Goes Off. Currently It */
733
/*-------------------------------------------------------------------------*/
735
void AlarmHandler(void)
737
EngineMessageTimeout = 1;
740
/*-------------------------------------------------------------------------*/
741
/* Function ParseCommandLine */
742
/*-------------------------------------------------------------------------*/
743
/* The Parameters Passed To This Function Are : */
744
/* argc : Standard "C" Number Of Arguments Passed Into Main */
745
/* argv : Standard "C" Argument List Passed into Main */
747
/* This Function Parses The Passed In Command Line And Sets Up The System */
750
/* Return : 0 For All Is Well, 1 For Exit Program */
751
/*-------------------------------------------------------------------------*/
753
uSHORT ParseCommandLine(int argc,char *argv[])
759
/* Parse The Command Line Options */
764
/* Loop Through All Parameters Passed In */
766
for(i = 1; i < argc; ++i)
771
/* Pull Out The Parameter And Convert It To Upper Case */
773
strcpy(pram,argv[i]);
776
/* Loop Through Our List To See If It Is In There */
778
for(j = 0; option[j].text != NULL; ++j)
780
if(strncmp(pram + 1, option[j].text, option[j].len) == 0)
783
/* We Found It, So Take The Appropriate Action */
785
switch(option[j].num)
788
/* ?,HELP : Display The Help Menu */
796
/* VERBOSE : Turn On The Verbose Option */
802
/* EATAHEX : Turn On The EATA Packet Hex Print Option */
808
/* EATAINFO : Turn On The EATA InfoPrint Option */
814
/* NOKILL : Turn On The No Kill Feature */
821
/* DEMO : Do not open Adaptor for demo mode */
827
/* STOP : Halt idling engines via shmem */
833
/* MSG : Debug Engine message calls */
839
/* SIG : Print Signature and Exit */
845
/* FDEBUG : Print Debug Output to File */
849
DebugToFile = atoi(argv[i]);
850
if (DebugToFile <= 0)
859
/* Bad Option, So Print Error, Display The Help Screen And Exit */
861
if((option[j].text == NULL)||(Invalid))
863
printf("\nError : Invalid Parameter %s : Program Terminated!!\n\n",
872
/*-------------------------------------------------------------------------*/
873
/* Function DisplayHelp */
874
/*-------------------------------------------------------------------------*/
875
/* There Are No Parameters Passed Into This Function */
877
/* This Function Displays The Help Options */
880
/*-------------------------------------------------------------------------*/
883
void DisplayHelp(void)
885
printf("Usage: engine [-options]\n");
889
" -verbose : Display All Connection And Message Information\n");
891
" -eatahex : Display Hex Dump Of EATA Packet\n");
893
" -eatainfo : Display EATA Packet Info\n");
895
" -nokill : Engine Will Not Unload When Not In Use\n");
897
" -demo : Engine Will Run in Demo Mode\n");
899
" -stop : Engine Will Stop Another That Is Not Yet Terminated\n");
901
" -msg : Display Engine Message Calls\n");
903
" -sig : Display Engine Signature and Exit\n");
905
" -fdebug <level> : Internal Debug to '/tmp/dpteng_dbg.log' <level>: 1..10\n");
906
printf(" -help or ? : Display Help Screen\n");
910
void DisplayHelp(void)
912
printf("The Pramaters For This Program Are :\n");
914
" /VERBOSE : Display All Connection And Message Information\n");
916
" /EATAHEX : Display Hex Dump Of EATA Packet\n");
918
" /EATAINFO : Display EATA Packet Info\n");
920
" /NOKILL : Engine Will Not Unload When Not In Use\n");
921
printf(" /HELP or /? : Display Help Screen\n");
923
#endif // SINIX_ADDON
934
/*-------------------------------------------------------------------------*/
935
/* Function DptSignalIgnore */
936
/*-------------------------------------------------------------------------*/
937
/* There Are No Parameters Passed Into This Function */
939
/* This Function is used to ignore the first shutdown signal */
942
/*-------------------------------------------------------------------------*/
944
void DptSignalIgnore(int nothing)
950
printf("Engine ignoring signal: %d\n", nothing);
955
exit(ExitGoodStatus);