Path: utzoo!attcan!uunet!aplcen!samsung!cs.utexas.edu!rice!uw-beaver!sumax!thebes!happym!irv From: irv@happym.wa.com (Irving Wolfe) Newsgroups: comp.unix.wizards Subject: utmp entry -- we're not doing something right -- can you help? Message-ID: <327@happym.wa.com> Date: 6 Jul 90 18:09:19 GMT Reply-To: irv@happym.wa.com (Irving Wolfe) Distribution: na Organization: Happy Man Corp. Lines: 232 The following program is intended to create a process and re-create it if it dies, as if it had been listed in inittab with respawn set, but later, so that (for example) a privileged process could start up something which would be re-created as often as necessary during a two hour observation period, then after 2 hours kill the "gspawn" process and finally kill the most recent instance of the process gspawn had created. It seems to work, but it doesn't work perfectly in that "ps -f" no longer can find the command string associated with many of the processes that are running on the system and resorts to showing things like "[ ps ]" instead of "ps -fuirv" in the command field. Can anyone explain why, preferably (but not necessarily) with a fix? Thanks! /* gspawn [ -c prog ] tty [ args... ] */ /* vi:se ts=4 wm=0 sw=4: */ #include #include #include #include #include #include #include #define MAXARGS 5 #define ERRTTY "/dev/console" #define DEFAULTARG0 "/bin/true" #define DEFAULTARG2 "9600" char *Argv[MAXARGS] = { DEFAULTARG0, "/dev/null", DEFAULTARG2, (char *)0, }; char *Gettyprog = DEFAULTARG0; char *Tty; int Pid = -1; char *Progname = "gspawn"; /* not entirely portable, but probably more so than varargs :-( */ conerr(msg,a1,a2,a3,a4,a5,a6) char *msg; int a1,a2,a3,a4,a5,a6; { char buf[BUFSIZ]; FILE *f = fopen(ERRTTY, "w"); if (!f) pause(); /* foo */ setbuf(f, NULL); strcat(buf, Progname); sprintf(buf+strlen(buf), msg, a1,a2,a3,a4,a5,a6); strcat(buf,"\r\n"); fputs(buf, f); fclose(f); } usage() { fprintf(stderr, "usage: %s [ -c cmd ] tty [ args ... ]\n", Progname); } char * basename(s) char *s; { char *p = strrchr(s, '/'); if (p) return ++p; return s; } cleanup() { /* the heck with it. */ exit(0); } main(argc, argv) char **argv; { int c; int forks; extern char *optarg; extern int optind; extern int errno; Progname = basename(argv[0]); while ((c = getopt(argc, argv, "c:")) != EOF) switch(c) { case 'c': Argv[0] = optarg; break; default: usage(); exit(1); } if (optind >= argc) { usage(); exit(2); } c = 1; while (optind < argc) Argv[c++] = argv[optind++]; Argv[c] = 0; Tty = Argv[1]; /* if not started by init, daemonize us */ if (getppid() != 1) { Pid = fork(); if (Pid < 0) { perror("fork"); exit(3); } else if (Pid > 0) { exit(0); } else { close(0); close(1); close(2); } } setpgrp(); signal(SIGTERM, cleanup); forks = 0; /* only go away if we're all hosed */ while (forks < 10) { /* fork, make new pgrp, exec cmd */ Pid = fork(); if (Pid == 0) { /* Make an INIT_PROCESS in utmp */ do_utmp(Tty); for (c = 0; c < _NFILE; c++) close(c); setpgrp(); execv(Argv[0], Argv); conerr("Failed miserably"); exit(1); /* STOP IMMEDIATELY */ } else if (Pid < 0) { conerr("couldn't fork in %s\n", argv[0]); ++forks; sleep(200); /* alarm(20); pause(); */ continue; } forks = 0; while ((c=wait((int *)0)) != Pid && (c!= -1 || errno==EINTR)) ; Pid = -1; } } do_utmp(tty) char *tty; { /* diddling /etc/utmp... When a cmd process is created, make utmp */ /* entry for new process. Leave the old one alone so init can find it. */ extern struct utmp *getutent(), *pututline(); register struct utmp *u; struct utmp ut; register FILE *fp; char id[4]; int oldpid = getppid(); int newpid = getpid(); /* Look in "utmp" for our parent's entry. It will be an INIT_PROCESS. */ /* Leave it alone and make a similar entry for us (the child). There */ /* may already be an entry, but it has the wrong pid. */ /* MAGIC RULE: id tags should be e.g. p1, p2, p3 and new ones will */ /* be created: P1, P2, P3. */ /* find parent's line, just remember id */ while ((u = getutent()) != NULL) { if (u->ut_type == INIT_PROCESS && u->ut_pid == oldpid) { strncpy(id, u->ut_id, sizeof(u->ut_id)); break; } } /* look for child's line */ if (u != NULL) { id[0] = 'P'; /* cheat */ } else { /* testing - not run by init */ strcpy(id, "PX"); } setutent(); while ((u = getutent()) != NULL) { if (strncmp(u->ut_id, id, sizeof(u->ut_id)) == 0) break; } /* regardless of whether we found one, fix it up and write it. */ if (u == NULL) u = &ut; strncpy(u->ut_user, "GETTY", sizeof(u->ut_user)); strncpy(u->ut_id, id, sizeof(u->ut_user)); strncpy(u->ut_line, Tty, sizeof(u->ut_line)); u->ut_pid = newpid; u->ut_type = INIT_PROCESS; time(&u->ut_time); pututline(u); /* If we were successful in finding an entry for ourself in the */ /* utmp file, then attempt to append to the end of the wtmp file. */ if (u != NULL && (fp = fopen(WTMP_FILE,"r+")) != NULL) { fseek(fp,0L,2); /* Seek to end of file */ fwrite(u,sizeof(*u),1,fp); fclose(fp); } /* Close the utmp file. */ endutent(); } -- Irving Wolfe Happy Man Corp. irv@happym.wa.com 206/463-9399 ext.101 SOLID VALUE, the investment letter for Benj. Graham's intelligent investors Information (not sample) free: email patty@happym.wa.com with US mail addr.