cdesktopenv/cde/programs/dtterm/DtTermLogit.c

428 lines
9.2 KiB
C

/*
* CDE - Common Desktop Environment
*
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
*
* These libraries and programs are free software; you can
* redistribute them and/or modify them under the terms of the GNU
* Lesser General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* These libraries and programs are distributed in the hope that
* they will be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with these libraries and programs; if not, write
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301 USA
*/
/* $TOG: DtTermLogit.c /main/6 1998/07/23 18:08:59 mgreess $ */
/* *
* (c) Copyright 1993, 1994 Hewlett-Packard Company *
* (c) Copyright 1993, 1994 International Business Machines Corp. *
* (c) Copyright 1993, 1994 Sun Microsystems, Inc. *
* (c) Copyright 1993, 1994 Novell, Inc. *
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <time.h>
#include <string.h>
#include <ctype.h>
#include <sys/times.h>
#include <pwd.h>
#include <sys/utsname.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define LOG_HOST "localhost"
#define LOG_ADDR "127.0.0.1"
#define LOG_PORT "4444"
#define WAIT_INTERVAL 5
#define RETRIES 5
/*
#define DEBUG_LOGIT
*/
#ifdef DEBUG_LOGIT
#define logitmain main
#endif /* DEBUG_LOGIT */
#ifdef LOG_USAGE
void LogStart(int noFork, int argc, char **argv);
void LogFinish(int noFork, int sessions);
void LogBumpSessionCount(int count);
static void doLog(int noFork, char *msg);
static void ding(int sig);
static void autoLogFinish();
static time_t startTime;
static char *id = (char *) 0;
static int sessionCount = 0;
static int savedNoFork = 0;
static int sequence = 0;
void
LogBumpSessionCount(int count)
{
sessionCount += count;
}
void
LogStart(int noFork, int argc, char **argv)
{
char buffer[BUFSIZ];
char *c1;
char *c2;
char *tstring;
struct utsname uts;
struct passwd *pw;
int i1;
if (getenv("DTTERM_NOLOG")) {
return;
}
/* save away noFork... */
savedNoFork = noFork;
*buffer = '\0';
(void) strcat(buffer, "START");
(void) strcat(buffer, " USER=\"");
if (c1 = getlogin()) {
(void) strcat(buffer, c1);
} else {
if ((pw = getpwuid(getuid())) && pw->pw_name && *pw->pw_name) {
(void) strcat(buffer, pw->pw_name);
} else {
(void) strcat(buffer, "???");
}
}
(void) strcat(buffer, "\"" );
if (uname(&uts) != -1) {
(void) strcat(buffer, " UNAME=\"");
(void) strcat(buffer, uts.sysname);
(void) strcat(buffer, " ");
(void) strcat(buffer, uts.nodename);
(void) strcat(buffer, " ");
(void) strcat(buffer, uts.release);
(void) strcat(buffer, " ");
(void) strcat(buffer, uts.version);
(void) strcat(buffer, " ");
(void) strcat(buffer, uts.machine);
(void) strcat(buffer, "\"");
}
(void) time(&startTime);
tstring = ctime(&startTime);
/* remove the trailing '\n'... */
tstring[strlen(tstring) - 1] = '\0';
(void) strcat(buffer, " TIME=\"");
(void) strcat(buffer, tstring);
(void) strcat(buffer, "\"");
(void) strcat(buffer, " ARGS=\"");
c1 = buffer + strlen(buffer);
for (i1 = 0; i1 < argc; i1++) {
if (i1 > 0) {
*c1++ = ' ';
}
for (c2 = argv[i1]; *c2; c2++) {
if (iscntrl(*c2)) {
*c1++ = '^';
*c1++ = '@' + *c2;
} else if (isprint(*c2)) {
switch (*c2) {
case '"' :
case '\\' :
case ' ' :
*c1++ = '\\';
*c1++ = *c2;
break;
default:
*c1++ = *c2;
break;
}
} else {
*c1++ = '\\';
*c1++ = '0' + (*c2 / 0100) & 07;
*c1++ = '0' + (*c2 / 0010) & 07;
*c1++ = '0' + (*c2 / 0001) & 07;
}
}
}
*c1++ = '"';
*c1++ = '\0';
(void) doLog(noFork, buffer);
atexit(autoLogFinish);
}
void
LogFinish(int noFork, int sessions)
{
char buffer[BUFSIZ];
char buffer2[BUFSIZ];
time_t now;
long cpuTime;
int i1;
struct tms tms;
long clkTick = 0;
if (getenv("DTTERM_NOLOG")) {
return;
}
*buffer = '\0';
(void) strcat(buffer, "FINISH");
(void) sprintf(buffer2, " SESSIONS=\"%d\"", sessions);
(void) strcat(buffer, buffer2);
(void) time(&now);
(void) sprintf(buffer2, " ELAPSED=\"%ld\"", now - startTime);
(void) strcat(buffer, buffer2);
(void) times(&tms);
clkTick = sysconf(_SC_CLK_TCK);
if (clkTick) {
cpuTime = (tms.tms_utime = tms.tms_stime) / clkTick;
} else {
cpuTime = -1;
}
(void) sprintf(buffer2, " CPU=\"%ld\"", cpuTime);
(void) strcat(buffer, buffer2);
(void) doLog(noFork, buffer);
}
static void
autoLogFinish()
{
(void) LogFinish(savedNoFork, sessionCount);
}
static void
doLog(int noFork, char *msg)
{
char *sbuffer;
char rbuffer[BUFSIZ];
char thisId[BUFSIZ];
static int s = -1;
int i1;
int len;
char *c1;
int retries = RETRIES;
struct hostent *hp;
static struct sockaddr_in myaddr_in;
static struct sockaddr_in servaddr_in;
struct sigaction sa;
struct sigaction oldSa;
time_t now;
pid_t pid;
int doRead;
sbuffer = malloc(2*BUFSIZ);
if (!id) {
(void) time(&now);
(void) sprintf(sbuffer, "%ld.%ld", now, (long)getpid());
id = strdup(sbuffer);
}
/* bump the sequence number before we fork()... */
(void) sequence++;
if (noFork) {
pid = 0;
} else {
pid = fork();
}
if (pid != 0) {
return;
}
if (s < 0) {
(void) memset(&servaddr_in, '\0', sizeof(servaddr_in));
(void) memset(&myaddr_in, '\0', sizeof(myaddr_in));
/* set up the server address... */
servaddr_in.sin_family = AF_INET;
hp = gethostbyname((c1 = getenv("DTTERM_LOG_HOST")) ? c1 : LOG_HOST);
if (hp) {
servaddr_in.sin_addr.s_addr =
((struct in_addr *)(hp->h_addr))->s_addr;
} else {
servaddr_in.sin_addr.s_addr =
inet_addr((c1 = getenv("DTTERM_LOG_ADDR")) ? c1 : LOG_ADDR);
}
servaddr_in.sin_port =
atoi((c1 = getenv("DTTERM_LOG_PORT")) ? c1 : LOG_PORT);
/* create the socket... */
s = socket(AF_INET, SOCK_DGRAM, 0);
if (s < 0) {
if (!noFork) {
(void) _exit(1);
}
return;
}
/* bind to some local address so we can get a reply... */
myaddr_in.sin_family = AF_INET;
myaddr_in.sin_port = 0;
myaddr_in.sin_addr.s_addr = INADDR_ANY;
if (bind(s, &myaddr_in, sizeof(myaddr_in)) == -1) {
if (!noFork) {
(void) _exit(1);
}
(void) close(s);
s = -1;
return;
}
}
if (!noFork) {
#ifdef _NFILE
for (i1 = 0; i1 < _NFILE; i1++) {
#else
for (i1 = 0; i1 < sysconf(_SC_OPEN_MAX); i1++) {
#endif
if (i1 != s) {
(void) close(i1);
}
}
}
(void) sprintf(thisId, "ID=\"%s.%d\"", id, sequence);
(void) sprintf(sbuffer, "%s %s", thisId, msg);
/* set up a signal handler... */
(void) sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sa.sa_handler = ding;
(void) sigaction(SIGALRM, &sa, &oldSa);
/* try to send the message... */
while (retries > 0) {
if (sendto(s, sbuffer, strlen(sbuffer), 0, &servaddr_in,
sizeof(servaddr_in)) < 0) {
if (!noFork) {
(void) _exit(1);
}
(void) close(s);
s = -1;
return;
}
/* set a timeout... */
(void) alarm(WAIT_INTERVAL);
for (doRead = 1; doRead; ) {
if ((len = recv(s, rbuffer, sizeof(rbuffer) -1, 0)) < 0) {
if (errno == EINTR) {
if (--retries < 0) {
/* give up... */
if (!noFork) {
(void) _exit(1);
}
(void) alarm(0);
(void) close(s);
s = -1;
return;
}
/* we need to resend before doing another read... */
doRead = 0;
} else {
/* give up... */
if (!noFork) {
(void) _exit(1);
}
(void) alarm(0);
(void) close(s);
s = -1;
return;
}
} else {
/* got ack... */
(void) alarm(0);
/* null term the string... */
rbuffer[len] = '\0';
/* compare it against the id... */
if (!strncmp(rbuffer, thisId, strlen(thisId))) {
/* match... */
doRead = 0;
retries = 0;
break;
}
/* ignore it and get the next one... */
}
}
}
/* clear the alarm and re-install the old signal handler... */
(void) alarm(0);
(void) sigaction(SIGALRM, &oldSa, (struct sigaction *) 0);
if (!noFork) {
_exit(0);
}
free(sbuffer);
return;
}
static void
ding(int sig)
{
/* since we are using sigaction, we don't need to reinstall
* ourself...
*/
}
#ifdef DEBUG_LOGIT
int
logitmain(int argc, char **argv)
{
int i1;
int noFork = 0;
extern char *optarg;
extern int optind, optopt;
while(EOF != (i1 = getopt(argc, argv, "f"))) {
switch(i1) {
case 'f' :
noFork = 1;
break;
}
}
(void) LogStart(noFork, argc, argv);
(void) sleep(5);
/*
(void) LogFinish(noFork, 123);
*/
}
#endif /* DEBUG_LOGIT */
#endif /* LOG_USAGE */