--- globus_2_4_3_adv2003_fix892_fix956/gatekeeper/source/globus_gatekeeper.c Wed Jul 23 17:56:46 2003 +++ globus_2_4_3_adv2003_fix892_fix956_more/gatekeeper/source/globus_gatekeeper.c Tue Jan 20 17:04:24 2004 @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -188,6 +189,7 @@ #define notice2(i,a,b) {sprintf(tmpbuf, a,b); notice(i,tmpbuf);} #define notice3(i,a,b,c) {sprintf(tmpbuf, a,b,c); notice(i,tmpbuf);} #define notice4(i,a,b,c,d) {sprintf(tmpbuf, a,b,c,d); notice(i,tmpbuf);} +#define notice5(i,a,b,c,d,e) {sprintf(tmpbuf, a,b,c,d,e); notice(i,tmpbuf);} #define failure2(t,a,b) {sprintf(tmpbuf, a,b); failure(t,tmpbuf);} #define failure3(t,a,b,c) {sprintf(tmpbuf, a,b,c); failure(t,tmpbuf);} #define failure4(t,a,b,c,d) {sprintf(tmpbuf, a,b,c,d); failure(t,tmpbuf);} @@ -203,6 +205,10 @@ static FILE * usrlog_fp; static char * logfile = LOGFILE; +static char * acctfile; +static volatile int logrotate; +static pid_t gatekeeper_pid; +static unsigned reqnr; static char test_dat_file[1024]; static int gatekeeper_test; static int gatekeeper_uid; @@ -350,6 +356,105 @@ } /* reaper() */ /****************************************************************************** +Function: rotatelog() +Description: Handle a SIGUSR1: set a flag indicating the logfile should be + rotated by the main loop. +Parameters: +Returns: +******************************************************************************/ +static void +rotatelog(int s) +{ + logrotate = 1; +} + +/****************************************************************************** +Function: new_acct_file() +Description: Rotate old and open new job accounting file. +Parameters: +Returns: +******************************************************************************/ +static void +new_acct_file(void) +{ + static int acct_fd = -1; + + if (acct_fd >= 0) + { + if (strcmp(acctfile, logfile) != 0) + { + static int seqnr; + char *acctpath = genfilename(gatekeeperhome, acctfile, NULL); + char *oldpath = malloc(strlen(acctpath) + 64); + time_t clock = time((time_t *) 0); + struct tm *tmp = localtime(&clock); + int ret; + + sprintf(oldpath, "%s.%04d%02d%02d%02d%02d%02d.%d", acctpath, + tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday, + tmp->tm_hour, tmp->tm_min, tmp->tm_sec, seqnr++); + + if ((ret = rename(acctpath, oldpath)) != 0) + { + notice4(LOG_ERR, "ERROR: cannot rename %s to %s: %s", + acctpath, oldpath, strerror(errno)); + } + else + { + notice2(0, "renamed accounting file %s", oldpath); + } + + free(acctpath); + free(oldpath); + + if (ret) { + return; + } + } + + close(acct_fd); + acct_fd = -1; + } + + if (!acctfile) + { + acctfile = logfile; + } + + if (acctfile && *acctfile) + { + const char *acct_fd_var = "GATEKEEPER_ACCT_FD"; + char *acctpath = genfilename(gatekeeperhome, acctfile, NULL); + + acct_fd = open(acctpath, O_WRONLY | O_APPEND | O_CREAT, 0644); + + if (acct_fd < 0) + { + notice3(LOG_ERR, "ERROR: cannot open accounting file '%s': %s", + acctpath, strerror(errno)); + + unsetenv(acct_fd_var); + } + else + { + /* + * Now inform JM via environment. + */ + + char buf[32]; + + sprintf(buf, "%d", acct_fd); + + setenv(acct_fd_var, buf, 1); + + notice4(0, "%s=%s (%s)", acct_fd_var, buf, acctpath); + } + + free(acctpath); + } +} + +/****************************************************************************** Function: genfilename() Description: generate an absolute file name given a starting prefix, a relative or absolute path, and a sufix @@ -443,6 +548,8 @@ exit (1); } + gatekeeper_pid = getpid(); + gatekeeper_uid = getuid(); if (gatekeeper_uid == 0) { @@ -607,6 +714,12 @@ logfile = argv[i+1]; i++; } + else if ((strcmp(argv[i], "-acctfile") == 0) + && (i + 1 < argc)) + { + acctfile = argv[i+1]; + i++; + } else if ((strcmp(argv[i], "-home") == 0) && (i + 1 < argc)) { @@ -753,7 +866,7 @@ fprintf(stderr, "Usage: %s %s %s %s %s %s %s %s %s %s\n ", argv[0], "{-conf parmfile [-test]} | {[-d[ebug] [-inetd | -f] [-p[ort] port] ", - "[-home path] [-l[ogfile] logfile] [-e path] ", + "[-home path] [-l[ogfile] logfile] [-acctfile acctfile] [-e path] ", "[-grid_services file] ", "[-globusid globusid] [-gridmap file] [-globuspwd file]", "[-x509_cert_dir path] [-x509_cert_file file]", @@ -884,15 +997,25 @@ act.sa_flags = 0; sigaction(SIGTERM, &act, NULL); } + act.sa_handler = rotatelog; + sigemptyset(&act.sa_mask); + sigaddset(&act.sa_mask, SIGUSR1); + act.sa_flags = 0; + sigaction(SIGUSR1, &act, NULL); } if (run_from_inetd) { logging_phase2(); dup2(2,1); /* point stdout at log as well */ - setbuf(stdout,NULL); } + /* + * Always make stdout unbuffered: otherwise the fclose(stdout) + * in doit() will flush any buffered output again and again! + */ + setbuf(stdout,NULL); + /* Get the GSS credential for the accepter * If not run_from_inetd we can prompt here. * If we are running as a deamon, and should not @@ -986,6 +1109,7 @@ free(globusid); } + new_acct_file(); if (run_from_inetd) { @@ -1003,10 +1127,12 @@ if (fork()) exit(0); + gatekeeper_pid = getpid(); + if (!logging_usrlog) { (void) close(2); /* close stderr as well */ - (void) open ("/dev/null",0); + (void) open("/dev/null",O_WRONLY); } (void) close(0); @@ -1063,6 +1189,7 @@ while (1) { connection_fd = net_accept(listener_fd); + reqnr++; pid = fork(); @@ -1846,6 +1973,31 @@ setenv("GRID_AUTH_METHOD","TO_FILLED_IN_LATER",1); /* + * Cook up a unique ID such that we can link the GSI info logged by + * the Gatekeeper to the batch system info logged by the Job Manager. + */ + { + time_t clock; + struct tm * tmp; + const char * gk_jm_id_var = "GATEKEEPER_JM_ID"; + char gatekeeper_jm_id[64]; + + time(&clock); + tmp = localtime(&clock); + + sprintf(gatekeeper_jm_id, "%04d-%02d-%02d.%02d:%02d:%02d.%010u.%010u", + tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday, + tmp->tm_hour, tmp->tm_min, tmp->tm_sec, + gatekeeper_pid & 0xFFFFFFFF, reqnr & 0xFFFFFFFF); + + setenv(gk_jm_id_var, gatekeeper_jm_id, 1); + setenv("GATEKEEPER_PEER", peernum, 1); + + notice5(0, "%s %s for %s on %s", gk_jm_id_var, gatekeeper_jm_id, + client_name, peernum); + } + + /* * Become the appropriate user */ if (gatekeeper_uid == 0) @@ -2074,18 +2226,87 @@ fromlen = sizeof(from); gotit = 0; + while (!gotit) { - skt2 = accept(skt, (struct sockaddr *) &from, &fromlen); - if (skt2 == -1) - { - if (errno == EINTR) - continue; - else - error_check(skt2, "net_accept accept"); - } - else - gotit = 1; + fd_set fdset; + struct timeval timeout; + int n; + + FD_ZERO(&fdset); + FD_SET(skt, &fdset); + timeout.tv_sec = 60; + timeout.tv_usec = 0; + + n = select(skt + 1, &fdset, (fd_set *) 0, &fdset, &timeout); + + if (n < 0 && errno != EINTR) + { + error_check(n, "net_accept select"); + } + else if (n > 0) + { + skt2 = accept(skt, (struct sockaddr *) &from, &fromlen); + + if (skt2 == -1) + { + if (errno != EINTR && errno != EAGAIN && errno != EWOULDBLOCK) + { + error_check(skt2, "net_accept accept"); + } + } + else + gotit = 1; + } + + if (logrotate) + { + time_t clock = time((time_t *) 0); + struct tm *tmp = localtime(&clock); + char buf[128]; + + sprintf(buf, "logfile rotating at %04d-%02d-%02d %02d:%02d:%02d", + tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday, + tmp->tm_hour, tmp->tm_min, tmp->tm_sec); + + notice2(LOG_INFO, "%s", buf); + + if (logging_usrlog) + { + static int seqnr; + char *logpath = genfilename(gatekeeperhome, logfile, NULL); + char *oldpath = malloc(strlen(logpath) + 64); + + sprintf(oldpath, "%s.%04d%02d%02d%02d%02d%02d.%d", logpath, + tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday, + tmp->tm_hour, tmp->tm_min, tmp->tm_sec, seqnr++); + + if (rename(logpath, oldpath) != 0) + { + notice4(LOG_ERR, "ERROR: cannot rename %s to %s: %s", + logpath, oldpath, strerror(errno)); + } + else if (logging_startup() != 0) + { + failure(FAILED_SERVER, "Logging restart failure"); + } + else + { + logging_phase2(); + fclose(stdout); + (void) dup2(2, 1); /* point stdout to stderr */ + *stdout = *fdopen(1, "w"); + notice2(LOG_INFO, "Continuing from %s", oldpath); + } + + free(logpath); + free(oldpath); + } + + new_acct_file(); + + logrotate = 0; + } } return(skt2); @@ -2105,10 +2326,15 @@ { netlen_t sinlen; struct sockaddr_in sin; + long flags; *skt = socket(AF_INET, SOCK_STREAM, 0); error_check(*skt,"net_setup_anon_listener socket"); + flags = fcntl(*skt, F_GETFL, 0); + flags |= O_NONBLOCK; + fcntl(*skt, F_SETFL, flags); + sin.sin_family = AF_INET; sin.sin_addr.s_addr = INADDR_ANY; sin.sin_port = htons(*port); @@ -2144,13 +2370,16 @@ } else { - /* - * By default open syslogfile. - * All messages will have GRAM gatekeeper and include the PID. - * The messages will be treated like any other system daemon. - */ - logging_syslog = 1; - openlog("GRAM gatekeeper", LOG_PID, LOG_DAEMON); + if (!logging_syslog) + { + /* + * By default open syslogfile if it is not open already. + * All messages will have GRAM gatekeeper and include the PID. + * The messages will be treated like any other system daemon. + */ + logging_syslog = 1; + openlog("GRAM gatekeeper", LOG_PID, LOG_DAEMON); + } if (strlen(logfile) > 0) { @@ -2159,7 +2388,20 @@ * Open the user specified logfile */ + if (logging_usrlog) + { + /* close previous logfile, if any */ + + if (usrlog_fp) + { + fclose(usrlog_fp); + } + + logging_usrlog = 0; + } + logfilename = genfilename(gatekeeperhome, logfile, NULL); + if ((usrlog_fp = fopen(logfilename, "a")) == NULL) { fprintf(stderr, "Cannot open logfile %s: %s\n", @@ -2168,6 +2410,7 @@ return(1); } + free(logfilename); logging_usrlog = 1; } @@ -2186,25 +2429,37 @@ { if (logging_usrlog) -{ - /* - * set stderr to the log file, to catch all fprintf(stderr,... - * and catch some from gram_k5, and job_manager - * But if testing gatekeeper, write to stderr instead. - */ - - if (!gatekeeper_test) { - (void) fflush(usrlog_fp); - (void) dup2(fileno(usrlog_fp),2); - (void) fclose(usrlog_fp); + { + /* + * set stderr to the log file, to catch all fprintf(stderr,... + * and catch some from gram_k5, and job_manager + * But if testing gatekeeper, write to stderr instead. + */ + + if (!gatekeeper_test && usrlog_fp) { + int tmpfd = dup(fileno(usrlog_fp)); /* save copy of logfile fd */ + + fflush(stderr); + + if (usrlog_fp != stderr) + { + fclose(usrlog_fp); /* this may still close fd 2! */ + } + + fclose(stderr); + + dup2(tmpfd, 2); /* reconnect fd 2 to logfile */ + close(tmpfd); + + *stderr = *fdopen(2, "w"); /* reinitialize stderr */ + } + usrlog_fp = stderr; + + /* + * Set output to non-buffered mode + */ + setbuf(stderr, NULL); } - usrlog_fp = stderr; - - /* - * Set output to non-buffered mode - */ - setbuf(stderr, NULL); -} return(0); } /* logging_phase2() */