static i4 line_get( char *prompt, char *def_line, i4 wild_flag, char *in_line ) { char line[MAXLINE]; char ret = '\n'; char *p; i4 status = EOF; for(;;) { STATUS s; SIprintf(prompt); SIprintf( *def_line ? "(%s): " : ": ", def_line ); /* This is somewhat unusuall but does force the SIflush to work */ SIflush(stdout); s = ocfg_getrec( line, (i4)MAXLINE ); if( s != OK || line[0] == '\033' ) break; if (p = STindex(line, &ret, MAXLINE)) *p = EOS; if( *def_line && !*line ) { STcopy( def_line, in_line ); SIprintf("\t\tDefault value: %s\n",in_line); } else { STcopy(line,in_line); } STzapblank(in_line,in_line); if( !*in_line ) { SIprintf("\t\tValue required, enter <ESC> to exit.\n"); continue; } if(!STbcompare( in_line, 0, "*",0, TRUE ) ) { if( !wild_flag ) { SIprintf("\t\tValue required, enter <ESC> to exit.\n"); continue; } in_line[0] = EOS; } status = OK; break; /* There is valid data */ } /* end of FOR loop */ return status; }
static ConversionResult CM_ConvertUTF16toUTF32 ( const UTF16** sourceStart, const UTF16* sourceEnd, UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) { ConversionResult result = conversionOK; const UTF16* source = *sourceStart; UTF32* target = *targetStart; UTF32 ch, ch2; while (source < sourceEnd) { const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */ ch = *source++; /* If we have a surrogate pair, convert to UTF32 first. */ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) { /* If the 16 bits following the high surrogate are in the source buffer... */ if (source < sourceEnd) { ch2 = *source; /* If it's a low surrogate, convert to UTF32. */ if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) { ch = ((ch - UNI_SUR_HIGH_START) << halfShift) + (ch2 - UNI_SUR_LOW_START) + halfBase; ++source; } else if (flags == strictConversion) { /* it's an unpaired high surrogate */ --source; /* return to the illegal value itself */ result = sourceIllegal; break; } } else { /* We don't have the 16 bits following the high surrogate. */ --source; /* return to the high surrogate */ result = sourceExhausted; break; } } else if (flags == strictConversion) { /* UTF-16 surrogate values are illegal in UTF-32 */ if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) { --source; /* return to the illegal value itself */ result = sourceIllegal; break; } } if (target >= targetEnd) { source = oldSource; /* Back up source pointer! */ result = targetExhausted; break; } *target++ = ch; } *sourceStart = source; *targetStart = target; #ifdef CVTUTF_DEBUG if (result == sourceIllegal) { SIfprintf(stderr, "ConvertUTF16toUTF32 illegal seq 0x%04x,%04x\n", ch, ch2); SIflush(stderr); } #endif return result; }
void main(int argc, char *argv[]) { char buf[ MAXBUF+1 ]; SIflush(stdin); gets(buf); /* SIgetrec(buf, MAXBUF, stdin); */ SIputrec(buf, stdout); }
/* ** Name: log_errmsg - logs a user and VMS error status to errlog.log ** ** Description: ** This routine converts OpenVMS status code to an OpenVMS text ** error message, then puts the specified message with ": status" ** appended and then the VMS error message output to the errlog.log ** ** Inputs: ** usrmsg - user specified error text (24 characters) ** code - VMS status code ** flg - 0 send message to error.log only, ** 1 write to standard out and to errlog.log ** ** Outputs: ** None ** ** Returns: ** void ** ** History: ** 22-nov-1993 (eml) ** Created to allow the use ot ERoptlog to write all error messages. ** 31-jan-1994 (bryanp) ** Even if SYS$GETMSG fails, report the "usrmsg" anyway. */ static void log_errmsg( const char *usrmsg, const unsigned int code, const unsigned int flg ) { static $DESCALLOC( bufadr ); char stsbuf[256]; char msgbuf[256]; unsigned short len; STATUS status; $DESCFILL( bufadr, sizeof( stsbuf ), stsbuf ); status = sys$getmsg( code, &len, &bufadr, 0x0F, NULL ); if ( !(status & 1) ) { /* ** "code" was not a valid VMS message status, or at least not one which ** we could turn into message text. So just format it in hex. Assume ** that the result is exactly eight characters long (does CVlx null ** terminate its output? If so, could set len = STlength(stsbuf);). */ CVlx(code, stsbuf); len = 8; } STcopy( usrmsg, msgbuf ); STcat( msgbuf, ": Status" ); stsbuf[len] = '\0'; ERoptlog( msgbuf, stsbuf ); if ( flg ) { SIprintf( "%s = %s\n", msgbuf, stsbuf ); SIflush( stdout ); } return; }
/* ** Name: PCexec_suid - Execute a command as the ingres user. ** ** Description: ** This procedure works with the Ingres service to run the given ** command as the ingres user. It mimicks the "setuid" bit in UNIX. ** ** Inputs: ** cmdbuf - command to execute as the ingres user ** ** Outputs: ** none ** ** Returns: ** OK ** FAIL ** ** Side Effects: ** none ** ** History: ** 08-jan-1998 (somsa01) ** Created. ** 19-feb-1998 (somsa01) ** We need to pass to the service the current working directory ** as well. (Bug #89006) ** 25-feb-1998 (somsa01) ** We now have an input file for the process' stdin which ** runs through the OpenIngres service. ** 19-jun-1998 (somsa01) ** Use SYSTEM_PRODUCT_NAME for the name of the service. ** 10-jul-1998 (kitch01) ** Bug 91362. If user is 'system' run through OpenIngres service ** despite having access to server shared memory 'system' does not ** have required privilege to access semaphores/mutexes. ** 11-jun-1999 (somsa01) ** If the command is a startup command, then it is always run through ** the Ingres service. ** 03-nov-1999 (somsa01) ** A failure from ControlService() should be treated as a severe ** error which should not let us continue. ** 22-jan-2000 (somsa01) ** Return the exit code of the spawned process. Also, if the ** files exist, truncate them. The service name is now keyed off ** of II_INSTALLATION. ** 05-jun-2000 (somsa01) ** The Ingres installation may be started as the SYSTEM account, ** in which the 'ingres' user will not automatically have access ** to the shared memory segments. Therefore, even if the real ** user is 'ingres', check to see if he has access. ** 24-oct-2000 (somsa01) ** Removed the check on shared memory access. Access to the shared ** memory segment does not necessarily mean that the user running ** the process does not need to run the specified process as the ** Ingres owner. Also, generalized the check of the user with ** IDname_service(). ** 18-dec-2000 (somsa01) ** Modified the cases to run the command "as is" without the Ingres ** service. ** 20-mar-2002 (somsa01) ** If all is well, return the exit code of the child process that ** was executed. ** 29-mar-2002 (somsa01) ** Properly return the child process exit code. ** 11-apr-2003 (somsa01) ** While waiting for "pending" to not be set, give some CPU back ** to the OS. ** 29-Jul-2005 (drivi01) ** Allow user to run the command if he/she owns a shared ** segment and ingres is not running as a service. ** 06-Dec-2006 (drivi01) ** Adding support for Vista, Vista requires "Global\" prefix for ** shared objects as well. Replacing calls to GVosvers with ** GVshobj which returns the prefix to shared objects. ** Added PCadjust_SeDebugPrivilege to allow quering of ** System processes. ** 25-Jul-2007 (drivi01) ** On Vista, PCexec_suid is unable to use SE_DEBUG Privilege ** to query process status and retireve its exit code. ** The routine for monitoring a process and retrieving ** its exit code has been moved to Ingres Service. ** 05-Nov-2009 (wanfr01) b122847 ** Don't do a PCsleep unless you are waiting for more input */ STATUS PCexec_suid(char *cmdbuf) { EX_CONTEXT context; SERVICE_STATUS ssServiceStatus; LPSERVICE_STATUS lpssServiceStatus = &ssServiceStatus; struct SETUID setuid; DWORD ProcID; HANDLE SaveStdout; SECURITY_ATTRIBUTES sa; CHAR szRealUserID[25] = ""; CHAR *pszRealUserID = szRealUserID; CHAR szServiceUserID[25] = ""; CHAR *pszServiceUserID = szServiceUserID; DWORD BytesWritten, BytesRead = 0; CHAR *inst_id; CHAR SetuidShmName[64]; CHAR *temp_loc; CHAR InBuf[256], OutBuf[256]; static CHAR SetuidPipeName[32]; CL_ERR_DESC err_code; CHAR ServiceName[255]; DWORD ExitCode = 0; CHAR tchII_INSTALLATION[3]; BOOL SetuidDbCmd = FALSE, ServiceCommand = FALSE; int i, cmdlen; char *ObjectPrefix; u_i4 drType; SC_HANDLE schSCManager, OpIngSvcHandle; BOOL bServiceStarted = FALSE; if (EXdeclare(ex_handler, &context) != OK) { EXdelete(); PCexit(FAIL); } NMgtAt("II_INSTALLATION", &inst_id); STcopy(inst_id, tchII_INSTALLATION); /* ** See if this is a command that MUST be run through the Ingres ** service. */ cmdlen = (i4)STlength(cmdbuf); for (i = 0; ServiceCommands[i] ; i++) { if (STbcompare( cmdbuf, cmdlen, ServiceCommands[i], (i4)STlength(ServiceCommands[i]), FALSE ) == 0) { ServiceCommand = TRUE; break; } } /* ** If the user is the same as the user who started the Ingres ** service, just spawn the command. */ if (!ServiceCommand) { IDname(&pszRealUserID); if (!IDname_service(&pszServiceUserID) && STcompare(pszServiceUserID, pszRealUserID) == 0 && PCisAdmin()) { /* ** Attempt to just execute the command. */ return( PCcmdline( (LOCATION *) NULL, cmdbuf, PC_WAIT, (LOCATION *) NULL, &err_code) ); } else { /* ** If current user is not the same as service user and ingres is not ** running as a service, check if shared memory segment is owned ** by current user, if user has access to shared segment allow him ** to run the command. */ PTR shmem; SIZE_TYPE allocated_pages=0; STATUS status; if((status = MEget_pages(ME_MSHARED_MASK, 1, "lglkdata.mem", &shmem, &allocated_pages, &err_code)) == OK) { STprintf(ServiceName, "%s_Database_%s", SYSTEM_SERVICE_NAME, tchII_INSTALLATION); if ((schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT)) != NULL) { if ((OpIngSvcHandle = OpenService(schSCManager, ServiceName, SERVICE_QUERY_STATUS)) != NULL) { if (QueryServiceStatus(OpIngSvcHandle,lpssServiceStatus)) { if (ssServiceStatus.dwCurrentState != SERVICE_STOPPED) bServiceStarted = TRUE; } } } if (!bServiceStarted) return(PCcmdline( (LOCATION *) NULL, cmdbuf, PC_WAIT, (LOCATION *) NULL, &err_code) ); } } /* ** See if this command is an Ingres command which needs to interact ** with at least one database. */ for (i = 0; validSetuidDbCmds[i] ; i++) { if (STbcompare( cmdbuf, cmdlen, validSetuidDbCmds[i], (i4)STlength(validSetuidDbCmds[i]), FALSE ) == 0) { SetuidDbCmd = TRUE; break; } } /* ** If the user has access to the Ingres shared memory segment, ** just spawn the command provided that it is not in the ** validSetuidDbCmds list. */ if (!SetuidDbCmd) { PTR shmem; SIZE_TYPE allocated_pages=0; STATUS status; if (((status = MEget_pages(ME_MSHARED_MASK, 1, "lglkdata.mem", &shmem, &allocated_pages, &err_code)) == OK) || (status == ME_NO_SUCH_SEGMENT)) { if (status != ME_NO_SUCH_SEGMENT) MEfree_pages(shmem, allocated_pages, &err_code); return( PCcmdline( (LOCATION *) NULL, cmdbuf, PC_WAIT, (LOCATION *) NULL, &err_code) ); } } } /* ** We must run the command through the Ingres service. */ if ( STstrindex(cmdbuf, "-silent", 0, FALSE ) ) SilentMode = TRUE; iimksec(&sa); GVshobj(&ObjectPrefix); STprintf(SetuidShmName, "%s%sSetuidShm", ObjectPrefix, tchII_INSTALLATION); if ( (SetuidShmHandle = OpenFileMapping(FILE_MAP_READ | FILE_MAP_WRITE, FALSE, SetuidShmName)) == NULL ) { error_exit(GetLastError()); return(FAIL); } if ( (SetuidShmPtr = MapViewOfFile(SetuidShmHandle, FILE_MAP_WRITE | FILE_MAP_READ, 0, 0, sizeof(struct SETUID_SHM))) == NULL ) { error_exit(GetLastError()); return(FAIL); } /* Set up the information to send to the service. */ STcopy(cmdbuf, setuid.cmdline); GetCurrentDirectory(sizeof(setuid.WorkingDirectory), setuid.WorkingDirectory); NMgtAt("II_TEMPORARY", &temp_loc); drType = GetDriveType(NULL); if (drType == DRIVE_REMOTE) { STcopy(temp_loc, setuid.WorkingDirectory); } SaveStdout = GetStdHandle(STD_OUTPUT_HANDLE); CVla(GetCurrentProcessId(), setuid.ClientProcID); STprintf(SetuidPipeName, "\\\\.\\PIPE\\INGRES\\%s\\SETUID", inst_id); /* Set up the stdout file for the command. */ STprintf(OutfileName, "%s\\%sstdout.tmp", temp_loc, setuid.ClientProcID); if ( (OutFile = CreateFile(OutfileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE ) { error_exit(GetLastError()); return(FAIL); } /* Set up the stdin file for the command. */ STprintf(InfileName, "%s\\%sstdin.tmp", temp_loc, setuid.ClientProcID); if ( (InFile = CreateFile(InfileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH, NULL)) == INVALID_HANDLE_VALUE ) { error_exit(GetLastError()); return(FAIL); } /* Wait until the service is ready to process our request. */ while (SetuidShmPtr->pending == TRUE) PCsleep(100); SetuidShmPtr->pending = TRUE; /* Trigger the "setuid" event of the service. */ if ( (schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT)) == NULL) { error_exit(GetLastError()); return(FAIL); } STprintf(ServiceName, "%s_Database_%s", SYSTEM_SERVICE_NAME, tchII_INSTALLATION ); OpIngSvcHandle = OpenService(schSCManager, ServiceName, SERVICE_USER_DEFINED_CONTROL); if (OpIngSvcHandle == NULL) { STprintf(ServiceName, "%s_DBATools_%s", SYSTEM_SERVICE_NAME, tchII_INSTALLATION ); OpIngSvcHandle = OpenService(schSCManager, ServiceName, SERVICE_USER_DEFINED_CONTROL); } if ( OpIngSvcHandle == NULL) { error_exit(GetLastError()); return(FAIL); } if (!ControlService(OpIngSvcHandle, RUN_COMMAND_AS_INGRES, lpssServiceStatus)) { error_exit(GetLastError()); CloseServiceHandle(schSCManager); return(FAIL); } WaitNamedPipe(SetuidPipeName, NMPWAIT_WAIT_FOREVER); /* Send the information to the service. */ if ( (Setuid_Handle = CreateFile(SetuidPipeName, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, &sa, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE ) { error_exit(GetLastError()); return(FAIL); } if (!WriteFile(Setuid_Handle, &setuid, sizeof(struct SETUID), &BytesWritten, NULL)) { error_exit(GetLastError()); return(FAIL); } /* ** Retrieve information back from the service, and then ** disconnect from the pipe. */ if (!ReadFile(Setuid_Handle, &setuid, sizeof(struct SETUID), &BytesRead, NULL)) { error_exit(GetLastError()); return(FAIL); } ProcID = setuid.CreatedProcID; SetuidShmPtr->pending = FALSE; UnmapViewOfFile(SetuidShmPtr); SetuidShmPtr = NULL; CloseHandle(SetuidShmHandle); if ( (ProcID != -1) && (ProcID != -2) ) { /* ** Wait for the "spawned" process to exit, reading its output ** from the stdout file. */ for (;;) { if ( ((!ReadFile(OutFile, OutBuf, sizeof(OutBuf), &BytesRead, NULL) || (BytesRead == 0)) && setuid.ExitCode != STILL_ACTIVE )) break; if ( BytesRead && (!WriteFile(SaveStdout, OutBuf, BytesRead, &BytesWritten, NULL)) && setuid.ExitCode != STILL_ACTIVE) break; else if (BytesRead < sizeof(OutBuf)) PCsleep(200); /* ** Currently, the only DBA program which can require ** user input is verifydb. Therefore, when it spits out ** the appropriate messages asking for user input, get ** it from the end user and pass it along to the spawned ** process. */ if ( (STrstrindex(OutBuf, "S_DU04FF_CONTINUE_PROMPT", 0, FALSE) != NULL) || (STrstrindex(OutBuf, "S_DU0300_PROMPT", 0, FALSE) != NULL) ) { SIflush(stdout); MEfill(sizeof(OutBuf), ' ', &OutBuf); MEfill(sizeof(InBuf), ' ', &InBuf); SIgetrec(InBuf, 255, 0); WriteFile(InFile, InBuf, sizeof(OutBuf), &BytesWritten, NULL); } } ExitCode = setuid.ExitCode; CloseHandle(Setuid_Handle); CloseHandle(InFile); DeleteFile(InfileName); CloseHandle(OutFile); DeleteFile(OutfileName); CloseServiceHandle(OpIngSvcHandle); CloseServiceHandle(schSCManager); return(ExitCode); } else { error_exit(GetLastError()); return(FAIL); } }
/* ** Writes or erases a transaction log and displays a completion thermometer. ** ** 'context' must not be NULL, and defaults for element 0 & 1 of context ** must have been set. */ i4 write_transaction_log(bool create, PM_CONTEXT *context, char *log_dir[], char *log_file[], void (*message)(char *), void (*init_graph)(bool, i4), i4 graph_size, void (*update_graph)()) { # define LG_PAGE_SIZE 2048L # define LG_NUMBER_OF_PAGES 32L /* Number of pages to write at a time */ DI_IO dio[LG_MAX_FILE]; char buf[LG_PAGE_SIZE * LG_NUMBER_OF_PAGES]; char nodename[GL_MAXNAME]; i4 i, j, marker, count, num_logs; i4 num_pages, page, part_size, remainder, loop; CL_ERR_DESC err; char *string; LOCATION loc[LG_MAX_FILE]; char locbuf[MAX_LOC + 1]; char *path[LG_MAX_FILE]; i4 LOinfo_flag; LOINFORMATION loc_info; i8 size; CS_SCB scb; bool size_in_kbytes = FALSE; MEfill( sizeof( scb ), 0, ( PTR ) &scb ); ++graph_size; /* Prepare transaction for log LOCATION(s) */ for (num_logs = 0; num_logs < LG_MAX_FILE; num_logs++) { if (log_dir[num_logs] == 0) break; STcopy( log_dir[num_logs], locbuf ); LOfroms( PATH, locbuf, &loc[num_logs] ); LOfstfile( log_file[num_logs], &loc[num_logs] ); LOtos( &loc[num_logs], &path[num_logs] ); } /* get size (in bytes) of log file to be created or erased */ if( create ) { STATUS status; char *value; bool havevalue = FALSE; status = PMmGet( context, ERx( "$.$.rcp.file.kbytes" ), &value ); if ( status == OK ) { havevalue = TRUE; size_in_kbytes = TRUE; } if ( havevalue == FALSE ) { status = PMmGet( context, ERx( "$.$.rcp.file.size" ), &value ); if ( status == OK ) havevalue = TRUE; } if ( havevalue == FALSE ) { if ( message != NULL ) { char msg[ BIG_ENOUGH ]; STprintf( msg, ERx( "%s %s" ), PMmExpandRequest( context, ERx( "$.$.rcp.file.kbytes" ) ), "not found." ); message( msg ); } return( 0 ); } CVal8( value, &size ); } else { LOinfo_flag = LO_I_SIZE; size = 0; for (i = 0; i < num_logs; i++) { if ( LOinfo( &loc[i], &LOinfo_flag, &loc_info ) != OK ) { if ( message != NULL ) { char msg[ BIG_ENOUGH ]; STprintf( msg, "Unable to get size of transaction log:\n\n\t%s", path[i] ); (*message)( msg ); } return( 0 ); } else size += loc_info.li_size; if ((LOinfo_flag & LO_I_SIZE) == 0) break; } if ( (LOinfo_flag & LO_I_SIZE) == 0 || size == 0L) { STATUS status; char *value; bool havevalue = FALSE; status = PMmGet( context, ERx( "$.$.rcp.file.kbytes" ), &value ); if ( status == OK ) { havevalue = TRUE; size_in_kbytes = TRUE; } if ( havevalue == FALSE ) { status = PMmGet( context, ERx( "$.$.rcp.file.size" ), &value ); if ( status == OK ) havevalue = TRUE; } if ( havevalue == FALSE ) { if ( message != NULL ) { char msg[ BIG_ENOUGH ]; STprintf( msg, ERx( "%s %s." ), PMmExpandRequest( context, ERx( "$.$.rcp.file.kbytes" ) ), "not found." ); message( msg ); } return( 0 ); } CVal8( value, &size ); } } for (i = 0; i < num_logs; i++) { if ( create && LOexist( &loc[i] ) == OK ) { char msg[ BIG_ENOUGH ]; if ( message != NULL ) { STprintf( msg, "%s already exists.", path[i] ); (*message)( msg ); STprintf( msg, "To create a new transaction log, you must first delete all partitions of the old one." ); (*message)( msg ); } return( 0 ); } } if ( CSinitiate( (i4 *) NULL, (char ***) NULL, (CS_CB *) NULL ) != OK ) { if ( message != NULL ) message( "Unable to connect to shared memory" ); return( 0 ); } CSset_sid( &scb ); /* create DI file */ for (i = 0; i < num_logs; i++) { if ( create && DIcreate( &dio[i], log_dir[i], (u_i4)STlength(log_dir[i]), log_file[i], (u_i4)STlength(log_file[i]), (i4)LG_PAGE_SIZE, &err) != OK ) { char msg[ BIG_ENOUGH ]; if ( message != NULL ) { STprintf( msg, "Unable to create transaction log:\n\n\t%s", path[i] ); (*message)( msg ); } return( 0 ); } /* open DI file */ if ( DIopen( &dio[i], log_dir[i], (u_i4)STlength(log_dir[i]), log_file[i], (u_i4)STlength(log_file[i]), (i4)LG_PAGE_SIZE, DI_IO_WRITE, 0, &err) != OK ) { if ( message != NULL ) { char msg[ BIG_ENOUGH ]; STprintf( msg, "Unable to open transaction log:\n\n\t%s", path[i] ); (*message)( msg ); } return( 0 ); } } if ( size_in_kbytes == FALSE ) size = (size + 1023) / 1024; (*init_graph)( create, (i4) size ); num_pages = size / (LG_PAGE_SIZE/1024); part_size = num_pages / num_logs; /* Readjust num_pages to be a multiple of num_logs */ num_pages = part_size * num_logs; loop = part_size / LG_NUMBER_OF_PAGES; remainder = part_size % LG_NUMBER_OF_PAGES; marker = loop / graph_size; /* Fill buffer with zeroes */ MEfill( sizeof( buf ), 0 , buf); for (i = 0; i < num_logs; i++) { if ( create && DIalloc( &dio[i], part_size, &page, &err ) != OK ) { DIdelete( &dio[i], log_dir[i], (u_i4)STlength( log_dir[i] ), log_file[i], (u_i4)STlength( log_file[i] ), &err ); if ( message != NULL ) (*message)( "Unable to allocate space in transaction log file." ); return( 0 ); } } count = 0; for( j = 0; j < loop; j++ ) { i4 n = LG_NUMBER_OF_PAGES; i4 page_no = j * n; for (i = 0; i < num_logs; i++) { if ( DIwrite( &dio[i], &n, page_no, buf, &err ) != OK ) { DIdelete( &dio[i], log_dir[i], (u_i4)STlength(log_dir[i]), log_file[i], (u_i4)STlength(log_file[i]), &err ); if ( message != NULL ) (*message)( "Unable to continue writing transaction log." ); return( 0 ); } } if ( j >= marker && j % marker == 0 && (f4) ((f4) j / (f4) loop) >= ((f4) count + 1) / graph_size ) { ++count; (*update_graph)(); SIflush( stdout ); } } if (remainder) { i4 page_no = loop * LG_NUMBER_OF_PAGES; for (i = 0; i < num_logs; i++) { if ( DIwrite( &dio[i], &remainder, page_no, buf, &err ) != OK ) { DIdelete( &dio[i], log_dir[i], (u_i4)STlength(log_dir[i]), log_file[i], (u_i4)STlength(log_file[i]), &err ); if ( message != NULL ) (*message)( "Unable to continue writing transaction log." ); return( 0 ); } } } for (i = 0; i < num_logs; i++) { if ( DIforce( &dio[i], &err ) != OK ) { DIdelete( &dio[i], log_dir[i], (u_i4)STlength(log_dir[i]), log_file[i], (u_i4)STlength(log_file[i]), &err ); if ( message != NULL ) (*message)( "Unable to force changes to transaction log." ); return( 0 ); } if ( create && DIflush( &dio[i], &err ) != OK ) { DIdelete( &dio[i], log_dir[i], (u_i4)STlength(log_dir[i]), log_file[i], (u_i4)STlength(log_file[i]), &err ); if ( message != NULL ) (*message)( "Unable to flush transaction log to disk." ); return( 0 ); } if( DIclose( &dio[i], &err ) != OK) { DIdelete( &dio[i], log_dir[i], (u_i4)STlength(log_dir[i]), log_file[i], (u_i4)STlength(log_file[i]), &err ); if ( message != NULL ) (*message)( "Unable to finish writing transaction log." ); return( 0 ); } } return( (i4) size ); }
/* A philosopher thread function, called out of CSdispatch */ STATUS philosopher( i4 mode, MY_SCB *scb, i4 *next_mode) { i4 bites = 0; #ifdef EX_DEBUG EX_CONTEXT context; if (EXdeclare(ex_handler, &context) != OK) { /* some exception was raised */ Psem( &SIsem ); SIfprintf( stderr,"Error: unexpected exception in philosopher()..."); Vsem( &SIsem ); EXdelete(); return FAIL; } #endif switch( mode ) { case CS_INITIATE: /* A new philsopher is born */ scb->phil = Threads++; status[scb->phil] = mode; while( bites < NBITES ) { getsticks( scb->phil ); eats( scb->phil ); bites++; freesticks( scb->phil ); thinks( scb->phil ); } /* fall into: */ default: *next_mode = CS_TERMINATE; break; case CS_TERMINATE: if( Noisy ) { # ifdef EX_SIG_DEBUG signal(SIGUSR1, intfunc); if (scb->phil == 1) { SIfprintf(stderr, "Send a signal #%d to process #%d\n", SIGUSR1, getpid()); pause(); } # endif /* EX_SIG_DEBUG */ Psem( &SIsem ); SIfprintf(stderr, "%d (%s) dies, RIP.\n", scb->phil, Names[ scb->phil ] ); if ( status[scb->phil] == mode ) { SIfprintf(stderr, "Oops this philosopher is already dead?\n"); SIfprintf(stderr, "\t\t CS code is non-functional\n"); } Vsem( &SIsem ); } *next_mode = CS_TERMINATE; /* If no more threads, shutdown */ status[scb->phil] = mode; if( --Threads == 0 ) { /* Everyone else should be dead, no semaphore needed. */ SIflush( stderr ); CSterminate( CS_KILL, (i4 *)NULL ); } break; } #ifdef EX_DEBUG EXdelete(); #endif return( OK ); }
/*{ ** Name: RScommit - two-phase commit processing ** ** Description: ** Prepares to commit locally, commits remotely, commits locally. ** Logs each step of the commit so that a reasonable attempt can ** be made to recover if it does not complete. ** ** Inputs: ** target - target database, CDDS and connection number ** row - distribution queue row ** ** Outputs: ** none ** ** Returns: ** OK or Ingres error ** ** Side effects: ** A distributed transaction is committed using incomplete two-phase ** commit (a prepare is only done on the local database, so the target ** database is not aware it is part of a distributed transaction). */ STATUS RScommit( RS_TARGET *target, RS_TRANS_ROW *row) { i4 high = (i4)RSlocal_conn.db_no; SYSTIME now; char timestamp[21]; char timestr[27]; i4 start_entry_no; i4 prepare_entry_no; i4 remote_entry_no; i4 complete_entry_no; RS_TBLDESC *tbl = row->tbl_desc; RS_CONN *local_conn = &RSlocal_conn; RS_CONN *target_conn = &RSconns[target->conn_no]; IIAPI_GETEINFOPARM errParm; IIAPI_STATUS status; if (RStwo_phase) /* two-phase commit is on */ { start_entry_no = RS_2PC_BEGIN; prepare_entry_no = RS_PREP_COMMIT; remote_entry_no = RS_REMOTE_COMMIT; complete_entry_no = RS_2PC_END; } else /* two-phase commit is off */ { start_entry_no = RS_NPC_BEGIN; remote_entry_no = RS_NPC_REM_COMMIT; complete_entry_no = RS_NPC_END; } TMnow(&now); TMstr(&now, timestr); mktimestamp(timestr, timestamp); SIfprintf(RScommit_fp, log_format, start_entry_no, high, low, (i4)target->db_no, tbl->table_owner, tbl->table_name, tbl->table_no, row->rep_key.trans_id, row->rep_key.seq_no, timestamp, "Start of commit"); SIflush(RScommit_fp); if (RStwo_phase) /* only prepare to commit if two-phase is on */ { /* ** Prepare to commit. The high value is %d, The low value is %d */ messageit(5, 1277, high, low); status = IIsw_prepareCommit(&local_conn->tranHandle, &errParm); if (status != IIAPI_ST_SUCCESS) { messageit(1, 1214); IIsw_rollback(&target_conn->tranHandle, &errParm); IIsw_rollback(&local_conn->tranHandle, &errParm); IIsw_releaseXID(&dtrans_id_handle); return (status); } SIfprintf(RScommit_fp, log_format, prepare_entry_no, high, low, (i4)target->db_no, tbl->table_owner, tbl->table_name, tbl->table_no, row->rep_key.trans_id, row->rep_key.seq_no, timestamp, "Prepare to commit"); SIflush(RScommit_fp); } status = IIsw_commit(&target_conn->tranHandle, &errParm); if (status != IIAPI_ST_SUCCESS) { IIsw_rollback(&target_conn->tranHandle, &errParm); if (IIsw_rollback(&local_conn->tranHandle, &errParm) != IIAPI_ST_SUCCESS) { RSdo_recover = TRUE; messageit(1, 1215); messageit(1, 1216); } else { messageit(1, 1215); } IIsw_releaseXID(&dtrans_id_handle); SIfprintf(RScommit_fp, log_format, remote_entry_no, high, low, (i4)target->db_no, tbl->table_owner, tbl->table_name, tbl->table_no, row->rep_key.trans_id, row->rep_key.seq_no, timestamp, "Local rollback"); SIfprintf(RScommit_fp, log_format, complete_entry_no, high, low, (i4)target->db_no, tbl->table_owner, tbl->table_name, tbl->table_no, row->rep_key.trans_id, row->rep_key.seq_no, timestamp, "Commit complete"); SIflush(RScommit_fp); return (status); } SIfprintf(RScommit_fp, log_format, remote_entry_no, high, low, (i4)target->db_no, tbl->table_owner, tbl->table_name, tbl->table_no, row->rep_key.trans_id, row->rep_key.seq_no, timestamp, "Remote commit"); SIflush(RScommit_fp); status = IIsw_commit(&local_conn->tranHandle, &errParm); if (status != IIAPI_ST_SUCCESS) { RSdo_recover = TRUE; IIsw_releaseXID(&dtrans_id_handle); return (status); } IIsw_releaseXID(&dtrans_id_handle); SIfprintf(RScommit_fp, log_format, complete_entry_no, high, low, (i4)target->db_no, tbl->table_owner, tbl->table_name, tbl->table_no, row->rep_key.trans_id, row->rep_key.seq_no, timestamp, "Commit complete"); SIflush(RScommit_fp); return (OK); }
bool r_rep_do() { char *_Retrieving = ERget(F_RW0003_Retrieving_data); LOCATION loc; /* file where the report will be written */ char title[80+1]; /* the help title buffer */ char help_scr[80+1]; /* the help screen buffer */ char pr_title[80+1]; /* print report title */ char file_title[80+1]; /* file report title */ /* ** The following is for scrollable output. */ FUNC_EXTERN BCB *IIUFint_Init(); FUNC_EXTERN bool IIUFmro_MoreOutput(); bool scrl_fl; r_rep_set(&loc); if (St_ing_error != 0) return FALSE; if (!St_silent) { /* give message while waiting for retrieve */ SIprintf(_Retrieving); SIflush(stdout); } if (St_to_term) { if( Warning_count != 0 ) { r_prompt(ERget(S_RW0025_Hit_RETURN_when_done), FALSE); } /* ** If output is the terminal, then initialize forms to do ** scrollable output. */ if (r_init_frms() != OK) { return FALSE; } /* set up the bcb (buffer control block) */ STprintf (title, ERget(S_RW1400_report_title), En_report); En_bcb = IIUFint_Init((char *)NULL, title); if (En_bcb == NULL) /* IIUFint_Init failed */ { return FALSE; } /* initialize bcb */ En_bcb->nxrec = r_scroll; /* routine to handle scrolling */ En_bcb->req_begin = TRUE; En_bcb->req_complete = FALSE; En_bcb->eor_warning = FALSE; LOdelete(&En_bcb->bfloc); /* check directory is writable */ En_bcb->nrecs = 0; En_bcb->mxcol = 0; En_bcb->print_time = FALSE; if (En_bcb->rd_ahead) { MEfree(En_bcb->rd_ahead); En_bcb->rd_ahead = NULL; } /* get first screen to display */ if (!IIUFmro_MoreOutput(En_bcb, En_bcb->mx_rows-2, NULL)) { r_end_frms(); /* suppress message if undocumented flag is used */ if (!St_copyright) { SIprintf(ERget(S_RW0045_No_data_in_table)); } SIflush(stdout); return FALSE; } STcopy (ERx("rwoutput.hlp"), help_scr); STcopy (ERget(S_RW13F1_RW_output_helpfile), title); STcopy (ERget(S_RW1408_print_report_title), pr_title); STcopy (ERget(S_RW1409_file_report_title), file_title); /* If there is nothing to display, then just exit */ if (En_bcb->rows_added != 0) { /* ** If the pagelength is equal to screen display size ** (4 less lines for the report title, status line, ** solid line and menu line in the scrollable output) ** then do NOT scroll keeping the current line visible. ** This is the default behavior. Want to scroll a ** full page at a time. */ if (St_p_length == (En_lines-4)) /* ** page length is the same as window size, so ** want page scrolling */ scrl_fl = FALSE; else /* ** different page size so want to scroll, ** leaving the one line for context. */ scrl_fl = TRUE; if (!IIUFdsp_Display(En_bcb, NULL, help_scr, title, scrl_fl, pr_title, file_title, FALSE)) { return FALSE; } } IIUFdone (En_bcb); } else { while (r_getrow() == OK) { r_nxt_row(); /* process next row */ } return (r_do_end(&loc)); } return TRUE; }
edit() { register char *p; LOCATION t_loc, loc; FILE *fp; char errbuf[ER_MAX_LEN + 1]; char input[MAX_LOC + 1]; char *editfile; char *ingedit; i4 rflag; STATUS status; i4 c; #ifdef CMS i4 Notempty = 1; #endif /* CMS */ GLOBALREF char *IIMOildInitLnDraw; FUNC_EXTERN char *getfilenm(); FUNC_EXTERN char *macro(); if (!Newline) { q_putc(Qryiop, '\n'); Newline = TRUE; } Autoclear = 0; editfile = getfilenm(); rflag = 0; if (*editfile == '\0') { rflag = 1; input[0] = EOS; if ((status = NMloc( TEMP, PATH, (char *)NULL, &t_loc)) || (status = LOuniq( ERx( "query" ), ERx( "edt" ), &t_loc))) { STcopy( ERx( "queryXXX" ), input ); } else { LOcopy( &t_loc, input, &loc ); } status = SIfopen( &loc, ERx( "w" ), (i4)SI_TXT, (i4)SI_MAX_TXT_REC, &fp ); } else { /* use the path and file name the user gave you */ STcopy(editfile, input); if (!(status = LOfroms(PATH & FILENAME, input, &loc))) status = SIfopen( &loc, ERx("w"), (i4)SI_TXT, (i4)SI_MAX_TXT_REC, &fp ); } if (status) { if (status == FAIL) errbuf[0] = '\0'; else ERreport(status, errbuf); putprintf(ERget(F_MO000C_Cant_create_qry_file), input, errbuf); cgprompt(); return(0); } if (q_ropen(Qryiop, 'r') == (struct qbuf *)NULL) /* edit: q_ropen 1 */ ipanic(E_MO0044_1500400); while ((c = (i4)q_getc(Qryiop)) > 0) SIputc((char)c, fp); SIclose(fp); if (Nodayfile >= 0) { putprintf(ERget(F_MO000D_editor_prompt)); SIflush(stdout); } /* ** macro returns NULL if undefined, UTedit uses ** default editor if passed NULL. */ /* Bug 4875 - Use editor defined by environment variable ING_EDIT. If that is not set then use the macro(editor). */ NMgtAt((ERx("ING_EDIT")), &ingedit); if ( ingedit != NULL && *ingedit != EOS ) p = ingedit; else p = macro(ERx("{editor}")); if (status = UTedit(p, &loc)) { ERreport(status, errbuf); putprintf(ERget(F_MO000E_Can_t_start_up_editor), errbuf); cgprompt(); return(0); } if (!rflag) { if (q_ropen(Qryiop, 'a') == (struct qbuf *)NULL) /* edit: q_ropen 2 */ ipanic(E_MO0045_1500401); } else { if (q_ropen(Qryiop, 'w') == (struct qbuf *)NULL) /* edit: q_ropen 3 */ ipanic(E_MO0046_1500402); if (status = SIfopen( &loc, ERx("r"), (i4)SI_TXT, (i4)SI_MAX_TXT_REC, &fp )) #ifdef CMS { Notempty = 0; } #else { ERreport(status, errbuf); /* can't reopen editfile %s: %s\n */ ipanic(E_MO0047_1500403, editfile, errbuf); } #endif /* CMS */ #ifdef CMS if (Notempty) { #endif /* CMS */ Notnull = 0; while ((c = SIgetc(fp)) != EOF) { if (status) { ERreport(status, errbuf); /* Error reading edit file: %s\n */ ipanic(E_MO0048_1500404, errbuf); } Notnull = 1; q_putc(Qryiop, (char)c); } SIclose(fp); if (status = LOpurge(&loc, 0)) { ERreport(status, errbuf); putprintf(ERget(F_MO000F_Cant_delete_file), editfile, errbuf); } #ifdef CMS } /* endif Notempty */ #endif /* CMS */ } #ifndef FT3270 /* Re-Initialize IT line drawing */ { if (Outisterm && IIMOildInitLnDraw != NULL) SIprintf(ERx("%s"), IIMOildInitLnDraw); } #endif cgprompt(); return(0); }
static VOID IILQgtfGcaTraceFile( II_LBQ_CB *IIlbqcb, i4 action ) { IILQ_TRACE *msgtrc = &IIglbcb->iigl_msgtrc; FILE *trace_file = (FILE *)msgtrc->ii_tr_file; char *title = ERx("off"); SYSTIME now; char nowbuf[100]; i4 nowend; /* ** Check to see that we actually need to open ** or close the trace file. */ if ( (action == IITRC_ON && trace_file) || (action == IITRC_OFF && ! trace_file) || (action == IITRC_SWITCH && ! trace_file) ) return; if ( action == IITRC_SWITCH ) title = ERx("switched"); if ( action == IITRC_ON ) { LOCATION trace_loc; STATUS stat; /* ** If trace file name not provided, use default. */ if ( ! msgtrc->ii_tr_fname ) msgtrc->ii_tr_fname = STalloc( GCTRACEFILE ); LOfroms(FILENAME, msgtrc->ii_tr_fname, &trace_loc ); # ifdef hp9_mpe if ( msgtrc->ii_tr_flags & II_TR_APPEND ) stat = SIfopen(&trace_loc, ERx("a"), SI_TXT, 252, &trace_file); else stat = SIfopen(&trace_loc, ERx("w"), SI_TXT, 252, &trace_file); # else if ( msgtrc->ii_tr_flags & II_TR_APPEND ) stat = SIopen(&trace_loc, ERx("a"), &trace_file); else stat = SIopen(&trace_loc, ERx("w"), &trace_file); # endif if (stat != OK) { /* Simplest error path; don't want IIlocerr functionality */ IIUGerr(E_LQ0007_PRINTQRY, 0, 1, msgtrc->ii_tr_fname); /* ** We can't call IILQgstGcaSetTrace() because ** of possible conflicts with the tracing ** semaphore, so just turn off tracing here. */ msgtrc->ii_tr_flags &= ~II_TR_FILE; if ( ! (msgtrc->ii_tr_flags & II_TR_HDLR) ) IIcgct1_set_trace( IIlbqcb->ii_lq_gca, 0, NULL, NULL ); return; } msgtrc->ii_tr_file = (PTR)trace_file; title = ERx("on "); } /* Get time stamp */ TMnow(&now); TMstr(&now, nowbuf); nowend = STlength( nowbuf ); if ( nowbuf[ nowend - 1 ] == '\n' ) nowbuf[ nowend - 1 ] = EOS; SIfprintf( trace_file, ERx("---- printgca = %s session %d (%s) ---\n\n"), title, IIlbqcb->ii_lq_sid, nowbuf ); SIflush( trace_file ); if ( action != IITRC_OFF ) msgtrc->ii_tr_sid = IIlbqcb->ii_lq_sid; else { SIclose( trace_file ); msgtrc->ii_tr_file = NULL; msgtrc->ii_tr_sid = 0; msgtrc->ii_tr_flags |= II_TR_APPEND; /* Don't overwrite if reopened */ } return; } /* IILQgtfGcaTraceFile */
VOID r_rep_load () { char *outname; char *tempname; /* start of routine */ r_open_db(); /* open database. If not there, abort */ STtrmwhite(En_report); /* start object-oriented facility for retrieving reports */ IIOOinit((OO_OBJECT **)NULL); En_rid = -1; /* set up report environment. */ if (St_style==RS_NULL && (St_ispec || r_env_set())) { /* report found. Read in report specifications */ if (!St_silent) { SIprintf(ERget(F_RW0005_Reading_report_spec)); SIflush(stdout); } r_rco_set(); /* read in the RCOMMANDS table into core */ } else { /* no report found. Use report name */ if (St_repspec) { /* error because report does not exist */ r_error(0x3F7, FATAL, En_report, NULL); } En_rtype = RT_DEFAULT; En_ferslv.name = En_report; if ((En_ferslv.name_dest = (char *)FEreqmem((u_i4)Rst4_tag, (u_i4)(FE_MAXNAME+1),TRUE,(STATUS *)NULL)) == NULL) { IIUGbmaBadMemoryAllocation( ERx("r_rep_loadld - name_dest")); } if ((En_ferslv.owner_dest = (char *)FEreqmem((u_i4)Rst4_tag, (u_i4)(FE_MAXNAME+1),TRUE,(STATUS *)NULL)) == NULL) { IIUGbmaBadMemoryAllocation( ERx("r_rep_loadld - owner_dest")); } /* ** If the server supports delimited identifiers, then ** ensure that .DELIMID is enabled since we're doing a report ** based upon a table, and it may require such services. */ if (IIUIdlmcase() != UI_UNDEFCASE) { St_xns_given = TRUE; } } /* ** set up (and maybe prompt for) declared variables */ r_dcl_set(TRUE); if ((En_qlang == FEDMLSQL) && (IIUIdbdata()->firstAutoCom == FALSE)) { IIUIautocommit(UI_AC_OFF); } if( r_sc_qry(Ptr_set_top) == FAIL ) { return; } IIUIdlmcase(); /* Hack for bug 96801 ingcbt198 */ if(!r_chk_dat()) /* check for a valid data relation */ { return; } if( !r_sendqry())/* send the query to the backend */ { return; } if (!r_att_dflt()) /* set up ATT structures for each */ { /* attribute in the data relation */ return; } if (En_rtype == RT_DEFAULT) { /* set up the default report */ if (!St_silent) { SIprintf(ERget(F_RW0006_Setting_up_default)); SIflush(stdout); } /* Set up first column as a sort column */ if (!r_m_dsort()) { r_error(0x416,NONFATAL,NULL); return; } } if (!r_srt_set()) /* set up the SORT data structures */ { /* bad RSORT */ r_error(0x0C, FATAL, NULL); } /* set up the BRK data structures ** for each sort attribute with a ** RACTION tuple defined for it */ if( !r_brk_set()) { return; } /* ** If there is a .PAGEWIDTH command and no -l flag has been specified ** on the commandline, then reset En_lmax. (The -l flag overrides the ** .PAGEWIDTH command). (#129, #588) */ if( STlength(En_pg_width) > 0 && !St_lspec) { /* If the pagewidth value is preceded by * a dollar, evaluate it as a parameter */ r_g_set(En_pg_width); if( r_g_skip() == TK_DOLLAR ) { CMnext(Tokchar); outname = r_g_name(); if( (tempname = r_par_get(outname)) == NULL ) { r_error(0x3F0, FATAL, outname, NULL); } STcopy(tempname, En_pg_width); } /* need to convert to a number and set it to En_lmax */ if (CVan(En_pg_width, &En_lmax) != OK) { /* Unable to convert so ignore input */ r_error(0x403, NONFATAL, outname, NULL); } } if (En_rtype == RT_DEFAULT) { /* set up default report */ r_m_rprt(); } else { Tcmd_tag = FEbegintag(); r_tcmd_set(); /* set up the tcmd data structures */ FEendtag(); } r_lnk_agg(); /* set up the CLR and OP structures for ** fast processing of aggregates. */ return; }
/* append = nonzero to append to output file. ** rederr = nonzero to redirect stderr to error log. */ STATUS PCdospawn(i4 argc, char **argv, bool wait, LOCATION *in_name, LOCATION *out_name, i4 append, i4 rederr, PID *pid) { char buf[64]; char *in_fname; char *out_fname; STATUS PCwait(); TYPESIG (*old_handler)(); int flags = 0; STATUS status; /* Flush the output buffers to make sure all child output ** follows the parent output. The streams may be buffered ** if, for example, they were redirected to a file. */ SIflush(stdout); SIflush(stderr); TRflush(); /* Don't want to mess up a sub-shell's handling of this by leaving ** it something odd. This might be a problem if something is ** run out of a DBMS server and an iislave happens to die while the ** subprocess spawned here is running. The symptom of this not working ** right is ckpdb failing, because the shell's handling of child death ** was messed up by our redirected handling of SIGCHLD. Frankly, that ** smells odd to me, but what the heck... (daveb). */ old_handler = EXsetsig(SIGCHLD, SIG_DFL); if ( (argc < 1) || (argv[0] == NULL)) { PCstatus = PC_SP_CALL; } /* ** If we are using fork() instead of vfork(), we must check ** to see if argument is executable now, because ** PCstatus from child process won't be available ** to parent. We don't know if we are using fork, so ** always check. */ else if (access(argv[0], 01) == BAD_ACCESS) { switch (errno) { case EACCES: /* error occurred because path was inaccessable. */ PCstatus = PC_SP_PERM; break; case EPERM: PCstatus = PC_SP_OWNER; break; case ENOTDIR: /* error occurred path didn't exist */ PCstatus = PC_SP_PATH; break; case ENOENT: /* error occurred path didn't exist */ PCstatus = PC_SP_SUCH; break; } } else if ( (*pid = (PID)PCfork( &PCstatus )) > 0 ) /* parent */ { /* ** (v)fork returns control to parent after exec. ** Calling process can ask PCspawn() to wait for ** the child, wait itself or choose not to wait. */ /* ** in the case of PC_NO_WAIT, we are only waiting for ** the intermediate process, which will also do fork/exec */ PCstatus = PCwait(*pid); } else if ( *pid == 0 ) /* child */ { if ( !wait ) { #if !defined xCL_086_SETPGRP_0_ARGS /* BSD flavour setpgrp */ if (setpgrp(0, getpid()) == -1 ) { status = errno; SIprintf("Can't change process group for spawned process\n"); PCexit(status); } # ifdef TIOCNOTTY /* say goodbye to our control terminal */ if ( (fd = open("/dev/tty", O_RDWR) ) >= 0 ) { ioctl(fd, TIOCNOTTY, (char *) NULL); close(fd); } # endif /* TIOCNOTTY */ #else /* SYSV flavour setpgrp */ if(setpgrp() == -1) /* create new pgrp, lose control terminal */ { status = errno; SIprintf("Can't change process group for spawned process\n"); PCexit(status); } #endif /* fork again, so we can't reacquire a control terminal */ if ( (*pid = PCfork(&status)) < 0 ) { status = errno; SIprintf("Can't fork again for spawned process\n"); PCexit(status); } else if (*pid > 0) { /* intermediate parent */ _exit(OK); } /* reset all the signal handlers to default */ EXsetsig( SIGCHLD, SIG_DFL ); } if (in_name != NULL) { LOtos(in_name, &in_fname); if ( *in_fname && freopen(in_fname, "r", stdin) != stdin ) PCstatus = PC_SP_REOPEN; } if (PCstatus == OK) { if (out_name != NULL) { char *mode = (append != 0) ? ERx("a") : ERx("w"); LOtos(out_name, &out_fname); if ( *out_fname ) { if (freopen(out_fname, mode, stdout) != stdout) { PCstatus = PC_SP_REOPEN; } else if (rederr != 0) { close(2); dup(1); } } } if (PCstatus == OK) { STcopy(argv[0], buf); argv[argc] = '\0'; /* insure argv set up properly */ execvp(buf, argv); /* should never reach here, because we checked first */ PCno_exec(buf); } } /* Should only reach here we had a PC_SP_REOPEN failure */ _exit( FAIL ); } (void) EXsetsig(SIGCHLD, old_handler); return( PCstatus ); }
/* ** Name: main -main routine. ** ** Description: ** This routine is the main control routine for iirundbms. Starting an ** iidbms server consists of: ** 1) Opening and reading the PM data ** 2) Validating server arguments, converting to VMS internal format. ** 3) Creating mailbox for communication with server. ** 4) creating server processing. ** 5) Sending server process its commands. ** 6) Checking whether server startup succeeded or not. ** ** iirundbms command line format is: ** iirundbms <server type> <server flavor> ** where server type is something like "dbms", "recovery", "star", and ** server flavor is something like "public", "nonames", "benchmark". ** ** Inputs: ** argc - number of arguments (should be 1, 2 or 3) ** argv - argument array. ** ** Outputs: ** None ** ** Returns: ** a VMS status code is returned. ** ** History: ** 31-jan-1994 (bryanp) ** Added comment header. ** 21-Jan-1998 (horda03) Bug 68559 ** For GCC servers where a server flavour has been specified, ** command line to start the server must specify the server ** flavour in the form; "-instance=<server_flavor>" in order ** for the GCC to pickup the correct configuration details. ** 22-feb-1998 (chash01) ** RMCMD (Visual DBA backend server) startup takes two VMS CREPRC ** calls, one ihere, one in rmcmd.exe. When RMCMD server starts ** the PID returned by CREPRC in this module is no longer valid. ** WE have to first decode pid in the t_user_data field returned by ** RMCMD server in termination mailbox before print PID and ** server name to terminal. ** 31-Aug-2007 (ashco01) Bug #113490 & Bug #119021. ** Corrected detection of 'instance name' for GCB & GCD. ** 05-Dec-2007 (ashco01) Bug #119561. ** Ensure that all Ingres back-end detached processes define the ** SYS$SCRATCH logical as this is referenced via II_TEMPORARY ** when placing temporary DCL files. ** 10-Dec-2007 (ashco01) Bug #119561 ** Define SYS$SCRATCH within all detached processes. */ main( int argc, char **argv ) { static $DESCALLOC( prcnam ); unsigned int pqlcnt = 0; $DESCALLOC( uicdsc ); char *param; char prcbuf[16]; ACCDEF2 accmsg; unsigned int pid; unsigned short chan; unsigned short term; unsigned int mbxunt; int dviitem; char buf[128], tmp[128]; II_VMS_MASK_LONGWORD efc_state; char *log_start_commands; IOSB iosb; ER_ARGUMENT dummy_arg; i4 i; STATUS status; i4 gcc = 0; i4 gcc_instance = 0; i4 gcb = 0; i4 gcb_instance = 0; i4 gcd = 0; i4 gcd_instance = 0; /* ** setup the type and server_flavor parameters */ if ( argc >= 2 ) { server_type = argv[1]; /* Are we starting a GCB, GCC or GCD ? */ if (STbcompare( server_type, 3, "gcc", 3, TRUE ) == 0) gcc++; if (STbcompare( server_type, 3, "gcb", 3, TRUE ) == 0) gcb++; if (STbcompare( server_type, 3, "gcd", 3, TRUE ) == 0) gcd++; } if ( argc >= 3 ) { server_flavor = argv[2]; /* Need to precede server_flavor with "-instance=" ** if we're starting a GCB, GCC or GCD. */ gcc_instance = gcc; gcb_instance = gcb; gcd_instance = gcd; } /* ** initialize PM routines and setup the default ** search parameters for config.dat */ status = PMinit( ); if (status) { pmerr_func(status, 0, &dummy_arg); return (status); } switch( status = PMload((LOCATION *)NULL, pmerr_func) ) { case OK: /* Loaded sucessfully */ break; case PM_FILE_BAD: /* syntax error */ if (status != FAIL) /* As of Nov 1993, PM.H defines PM_FILE_BAD 1 */ pmerr_func(status, (i4)0, &dummy_arg); return (status); default: /* unable to open file */ if (status != FAIL) /* FAIL is a useless status to report... */ pmerr_func(status, (i4)0, &dummy_arg); return (status); } #ifdef EDBC PMsetDefault( 0, ERx( "ed" ) ); #else PMsetDefault( 0, ERx( "ii" ) ); #endif PMsetDefault( 1, PMhost( ) ); PMsetDefault( 2, server_type ); PMsetDefault( 3, server_flavor ); /* read and process pm parameters */ for ( i = 0; pm_option[i].PM_name != NULL; i++ ) { status = PMget( pm_option[i].PM_name, ¶m ); if ( status != OK ) continue; switch ( pm_option[i].type ) { unsigned int *target; case TYPE_CLRFLG: if ( STbcompare(param, 0, "off", 0, TRUE) != 0 && STbcompare(param, 0, "on", 0, TRUE) != 0 ) { SIprintf("IIRUNDBMS: %s value must be ON or OFF\n", pm_option[i].PM_name); SIflush(stdout); log_errmsg( "Must be ON or OFF", SS$_BADPARAM, 1 ); return (SS$_BADPARAM); } target = (unsigned int *)pm_option[i].target; if ( STbcompare(param, 0, pm_option[i].keyword, 0, TRUE) == 0) *target &= ~(int)pm_option[i].parameter; if ( msg_echo && (STscompare( pm_option[i].PM_name, 0, echo, 0 ) == 0) ) ERoptlog( pm_option[i].PM_name, param ); break; case TYPE_SETFLG: if ( STbcompare(param, 0, "off", 0, TRUE) != 0 && STbcompare(param, 0, "on", 0, TRUE) != 0 ) { SIprintf("IIRUNDBMS: %s value must be ON or OFF\n", pm_option[i].PM_name); SIflush(stdout); log_errmsg( "Must be ON or OFF", SS$_BADPARAM, 1 ); return (SS$_BADPARAM); } target = (unsigned int *)pm_option[i].target; if ( STbcompare(param, 0, pm_option[i].keyword, 0, TRUE) == 0) *target |= (int)pm_option[i].parameter; if ( msg_echo ) ERoptlog( pm_option[i].PM_name, param ); break; case TYPE_INT: target = (unsigned int *)pm_option[i].target; status = CVal( param, target ); if (status) { SIprintf("IIRUNDBMS: %s value must be an integer\n", pm_option[i].PM_name); SIflush(stdout); pmerr_func(status, 0, &dummy_arg); return (SS$_BADPARAM); } if ( msg_echo ) { STprintf( buf, "%d", *target ); ERoptlog( pm_option[i].PM_name, buf ); } break; case TYPE_UIC: { $DESCINIT( uicdsc, param ); status = iics_cvtuic( &uicdsc, (char *)pm_option[i].target ); if ( !(status & 1) ) { log_errmsg( "vms_uic invalid", status, 1 ); return (status); /* B56811 */ } if ( msg_echo ) { if ( *(unsigned int *)(pm_option[i].target) != 0 ) { STprintf( buf, "%s [%o,%o]", param, ((uic >> 16) & 0xffff), (uic & 0xffff) ); ERoptlog( pm_option[i].PM_name, buf ); } } break; } case TYPE_STR: if (STlength(param) > MAX_STRING_OPTION_LENGTH) { SIprintf("IIRUNDBMS: Max length for %s is %d\n", pm_option[i].PM_name, MAX_STRING_OPTION_LENGTH); SIflush(stdout); return (SS$_BADPARAM); } STcopy( param, (char *)pm_option[i].target ); if ( msg_echo ) ERoptlog( pm_option[i].PM_name, param ); break; case TYPE_PQL: /* ** build VMS process quota block */ quota[pqlcnt].name = (char)pm_option[i].parameter; status = CVal( param, "a[pqlcnt].value ); if (status) { SIprintf("IIRUNDBMS: %s value must be an integer\n", pm_option[i].PM_name); SIflush(stdout); pmerr_func(status, 0, &dummy_arg); return (SS$_BADPARAM); } pqlcnt++; if ( msg_echo ) ERoptlog( pm_option[i].PM_name, param ); break; case TYPE_PRIV: { char prvbuf[512]; char *p, *q; i4 j; /* ** Remove white space then ** convert the string to upper case, then ** remove leading and trailing parens */ if (STlength(param) >= sizeof(prvbuf)) { SIprintf("IIRUNDBMS: vms_privileges are too long\n"); SIprintf(" Actual length (%d) exceeds maximum (%d)\n", STlength(param), sizeof(prvbuf)); SIflush(stdout); return (SS$_BADPARAM); } STcopy( param, prvbuf); STtrmwhite( prvbuf ); CVupper( prvbuf ); /* ** Scan the comma seperated privilege list and set the ** privileges for each privileges keywork in the list. */ for ( p = prvbuf; p != 0 && *p != 0; p = q ) { if ( (q = STindex( p, ERx( "," ), 0 )) != NULL ) *q++ = '\0'; else if ( (q = STindex( p, ERx( ")" ), 0 )) != NULL ) *q++ = '\0'; if ( *p == '(' ) p++; for ( j = 0; prv_table[j].prv_name != NULL; j++ ) { if ( STscompare( p, 4, prv_table[j].prv_name, 4 ) == 0 ) { prvadr[0] |= prv_table[j].prv_code_low; prvadr[1] |= prv_table[j].prv_code_hi; if ( msg_echo ) ERoptlog( pm_option[i].PM_name, prv_table[j].prv_name ); break; } } if (prv_table[j].prv_name == NULL) { /* ** We failed to find privilege "p" in our table */ SIprintf("IIRUNDBMS: Syntax error in privilege list\n"); SIprintf(" Error near byte %d of string %s", p - prvbuf, param); SIflush(stdout); ERoptlog("Unrecognized privilege:", p); return (SS$_BADPARAM); } } break; } default: break; } }
i4 main( i4 argc, char **argv ) { STATUS generic_status = OK; CL_ERR_DESC system_status; EX_CONTEXT context; STATUS status; GCC_ERLIST erlist; STATUS (*call_list[7])(); i4 i, call_count; i4 cmd_args = 0; char usage[] = { "Usage: iigcb -from <protocol>" }; char usage1[] = { " -to <protocol> <hostname> < listen_address>" }; #ifdef LNX PCsetpgrp(); #endif MEfill( sizeof( system_status ), 0, (PTR)&system_status ); MEadvise( ME_INGRES_ALLOC ); EXdeclare( GCX_exit_handler, &context ); SIeqinit(); /* ** Parse command line. */ for( i = 1; i < argc; i++ ) if ( ! STcompare( argv[i], "-from" ) ) { if ( ++i >= argc ) { SIfprintf( stderr, "\n%s%s\n\n", usage, usage1 ); SIflush( stderr ); SIstd_write(SI_STD_OUT, "\nFAIL\n"); EXdelete(); PCexit( FAIL ); } STcopy( argv[i], gcb_from_addr.n_sel ); CVupper( gcb_from_addr.n_sel ); ++cmd_args; } else if ( ! STcompare( argv[ i ], "-to" ) ) { if ( (i + 3) >= argc ) { SIfprintf( stderr, "\n%s%s\n\n", usage, usage1 ); SIflush( stderr ); SIstd_write(SI_STD_OUT, "\nFAIL\n"); EXdelete(); PCexit( FAIL ); } STcopy( argv[ ++i ], gcb_to_addr.n_sel ); STcopy( argv[ ++i ], gcb_to_addr.node_id ); STcopy( argv[ ++i ], gcb_to_addr.port_id ); CVupper( gcb_to_addr.n_sel ); ++cmd_args; } if ( cmd_args ) if ( cmd_args == 2 ) gcb_pm_reso.cmd_line = TRUE; else { SIfprintf( stderr, "\n%s%s\n\n", usage, usage1 ); SIflush( stderr ); SIstd_write(SI_STD_OUT, "\nFAIL\n"); EXdelete(); PCexit( FAIL ); } /* ** Perform general initialization. The bridge may be run ** for async lines as a part of Ingres/Net. Otherwise, ** Bridge authorization is required. */ if ( gcb_pm_reso.cmd_line && ! STcasecmp( gcb_from_addr.n_sel, ERx("async") ) ) status = gcc_init( FALSE, CI_INGRES_NET, argc, argv, &generic_status, &system_status ); else { #ifdef CI_INGRES_BRIDGE status = gcc_init( FALSE, CI_INGRES_BRIDGE, argc, argv, &generic_status, &system_status ); #else generic_status = E_GC2A0F_NO_AUTH_BRIDGE; status = FAIL; #endif } if ( status != OK ) { gcc_er_log( &generic_status, &system_status, NULL, NULL ); generic_status = E_GC2A01_INIT_FAIL; gcc_er_log( &generic_status, NULL, NULL, NULL ); SIstd_write(SI_STD_OUT, "\nFAIL\n"); EXdelete(); PCexit( FAIL ); } /* ** Perform standalong Bridge Server initialization. */ IIGCc_global->gcc_flags |= GCC_STANDALONE; gcb_init_mib(); /* ** Initialize the protocol layers. */ call_list[0] = GCcinit; call_list[1] = gcb_alinit; call_list[2] = gcc_pbinit; call_count = 3; if ( gcc_call( &call_count, call_list, &generic_status, &system_status ) != OK ) { gcc_er_log( &generic_status, &system_status, NULL, NULL ); generic_status = E_GC2A01_INIT_FAIL; gcc_er_log( &generic_status, NULL, NULL, NULL ); SIstd_write(SI_STD_OUT, "\nFAIL\n"); } else { { /* ** Obtain and fix up the configuration name, then log it. */ char server_flavor[256], server_type[32]; char *tmpbuf = PMgetDefault(3); if (!STbcompare( tmpbuf, 0, "*", 0, TRUE )) STcopy("(DEFAULT)", server_flavor); else STcopy(tmpbuf, server_flavor); STcopy(PMgetDefault(2), server_type); CVupper(server_type); erlist.gcc_parm_cnt = 2; erlist.gcc_erparm[0].value = server_flavor; erlist.gcc_erparm[0].size = STlength(server_flavor); erlist.gcc_erparm[1].value = server_type; erlist.gcc_erparm[1].size = STlength(server_type); generic_status = E_GC2A10_LOAD_CONFIG; gcc_er_log( &generic_status, (CL_ERR_DESC *)NULL, (GCC_MDE *)NULL, &erlist); } erlist.gcc_parm_cnt = 1; erlist.gcc_erparm[0].size = STlength( IIGCc_rev_lvl ); erlist.gcc_erparm[0].value = IIGCb_rev_lvl; generic_status = E_GC2A03_STARTUP; gcc_er_log( &generic_status, NULL, NULL, &erlist ); /* ** Invoke GCexec to enter the main phase of Protocol bridge ** execution. GCexec does not return until bridge shutdown ** is initiated by invoking GCshut. */ GCexec(); generic_status = E_GC2A04_SHUTDOWN; gcc_er_log( &generic_status, &system_status, NULL, NULL ); } /* ** GCexec has returned. Bridge shutdown is in process. ** Initialize the call list to specify termination rotutines. ** Call in reverse order of initialization but don't call ** termination routines whose initialization routines were ** not called (call_count has the number of successful ** initialization calls). */ call_list[0] = gcb_alterm; call_list[1] = gcc_pbterm; call_list[2] = GCcterm; if ( gcc_call( &call_count, &call_list[ 3 - call_count ], &generic_status, &system_status ) ) gcc_er_log( &generic_status, &system_status, NULL, NULL ); /* ** Do general server termination. */ if ( gcc_term( &generic_status, &system_status ) != OK ) gcc_er_log( &generic_status, &system_status, NULL, NULL ); EXdelete(); PCexit( OK ); } /* end main */