/**************************************************************** * * * Copyright 2001, 2011 Fidelity Information Services, Inc * * * * This source code contains the intellectual property * * of its copyright holder(s), and is made available * * under a license. If you do not know the terms of * * the license, please stop and do not read further. * * * ****************************************************************/ #include "mdef.h" #include "gtm_string.h" #include "gtm_stdlib.h" #include "gtm_unistd.h" #include #include "rtnhdr.h" #include "startup.h" #include "gtm_startup.h" #include "stack_frame.h" #include "job_addr.h" #include "compiler.h" #include "indir_enum.h" #include "error.h" #include "util.h" #include "cli.h" #include "job.h" #include "gcall.h" #include "jobchild_init.h" #include "lv_val.h" /* needed for "callg.h" */ #include "callg.h" #include "invocation_mode.h" #include "gtmci.h" #include "send_msg.h" #define FILE_NAME_SIZE 255 GBLREF stack_frame *frame_pointer; GBLREF uint4 process_id; error_def (ERR_RUNPARAMERR); error_def (ERR_TEXT); error_def(ERR_SYSCALL); LITDEF char interactive_mode_buf[] = "INTERACTIVE"; LITDEF char other_mode_buf[] = "OTHER"; CONDITION_HANDLER(job_init_ch) { START_CH; PRN_ERROR; NEXTCH; } /* * --------------------------------------------------------- * Child process test and initialization. * If this copy of GTM is a child process, * then initialize the child. * --------------------------------------------------------- */ void jobchild_init(void) { unsigned int status; job_params_type jparms; unsigned char *transfer_addr; /* Transfer data */ rhdtyp *base_addr; unsigned short i, arg_len; char run_file_name[FILE_NAME_SIZE + 2], *c; gcall_args job_arglist; mval job_args[MAX_ACTUALS]; DCL_THREADGBL_ACCESS; SETUP_THREADGBL_ACCESS; ESTABLISH(job_init_ch); /* * Check if environment variable ppid - job parent pid * exists. If it does not, we are a regular gtm process, * else, we are a child process of a job command. */ if ((c = GETENV(CHILD_FLAG_ENV)) && strlen(c)) { /* We are a Jobbed process Get Job parameters and set up environment to run the Job command */ /* Clear the environment variable so that subsequent child mumps processes can start normal initialization. */ if (PUTENV(CLEAR_CHILD_FLAG_ENV)) { util_out_print("Unable to clear gtmj0 process !UL exiting.", TRUE, process_id); rts_error(VARLSTCNT(1) errno); } /* read parameters into parameter structure */ ojchildparms(&jparms, &job_arglist, job_args); /* Execute the command to be run before executing the actual M routine */ if (jparms.startup.len) { if (0 != SYSTEM(jparms.startup.addr)) { rts_error(VARLSTCNT(4) ERR_TEXT, 2, LEN_AND_LIT("STARTUP command failed")); } } /* Set up job's input, output and error files. Redirect them, if necessary. */ /* It is needed since the middle process would not have always done this(under jobpid == TRUE cases) */ if (!(status = ojchildioset(&jparms))) rts_error(VARLSTCNT(4) ERR_TEXT, 2, LEN_AND_LIT("Failed to set STDIN/OUT/ERR for the job")); job_addr(&jparms.routine, &jparms.label, jparms.offset, (char **)&base_addr, (char **)&transfer_addr); /* Set process priority */ if (jparms.baspri) { /* send message to system log if nice fails */ if (-1 == nice((int)jparms.baspri)) send_msg(VARLSTCNT(8) ERR_SYSCALL, 5, LEN_AND_LIT("nice"), CALLFROM, errno); } /* Set up $ZMODE to "OTHER" */ (TREF(dollar_zmode)).mvtype = MV_STR; (TREF(dollar_zmode)).str.addr = (char *)other_mode_buf; (TREF(dollar_zmode)).str.len = SIZEOF(other_mode_buf) -1; /* Release storage allocated by ojchildparms() */ if (jparms.directory.len) free(jparms.directory.addr); if (jparms.gbldir.len) free(jparms.gbldir.addr); if (jparms.startup.len) free(jparms.startup.addr); if (jparms.input.len) free(jparms.input.addr); if (jparms.output.len) free(jparms.output.addr); if (jparms.error.len) free(jparms.error.addr); if (jparms.routine.len) free(jparms.routine.addr); if (jparms.label.len) free(jparms.label.addr); if (jparms.logfile.len) free(jparms.logfile.addr); } else { /* If we are not a child, setup a dummy mumps routine */ if (MUMPS_RUN == invocation_mode) { mstr routine, label; int offset; arg_len = FILE_NAME_SIZE; if (!cli_get_str("INFILE", run_file_name, &arg_len)) rts_error(VARLSTCNT(1) ERR_RUNPARAMERR); lref_parse((uchar_ptr_t)run_file_name, &routine, &label, &offset); job_addr(&routine, &label, offset, (char **)&base_addr, (char **)&transfer_addr); } else if (MUMPS_CALLIN & invocation_mode) /* call-in mode */ { base_addr = make_cimode(); transfer_addr = PTEXT_ADR(base_addr); } else /* direct mode */ { base_addr = make_dmode(); transfer_addr = PTEXT_ADR(base_addr); } job_arglist.callargs = 0; /* Set up $ZMODE to "INTERACTIVE" */ (TREF(dollar_zmode)).mvtype = MV_STR; (TREF(dollar_zmode)).str.addr = (char *)interactive_mode_buf; (TREF(dollar_zmode)).str.len = SIZEOF(interactive_mode_buf) -1; } gtm_init_env(base_addr, transfer_addr); if (MUMPS_CALLIN & invocation_mode) { SET_CI_ENV(ci_ret_code_exit); } if (job_arglist.callargs) { callg((INTPTR_T (*)(intszofptr_t cnt, ...))push_parm, (gparam_list *)&job_arglist); frame_pointer->type |= SFT_EXTFUN; } REVERT; }