/* ** SETPROCTITLE -- set process title for ps ** ** Parameters: ** fmt -- a printf style format string. ** a, b, c -- possible parameters to fmt. ** ** Returns: ** none. ** ** Side Effects: ** Clobbers argv of our main procedure so ps(1) will ** display the title. */ #include #include #include #include #include #include #include #include #include #include "../config.h" #ifdef HAVE_GRP_H #include #endif #ifdef HAVE_SYS_FILIO_H #include #endif #ifdef HAVE_STDARG_H #include #else #ifdef HAVE_VARARGS_H #include #endif #endif #ifdef __STDC__ #ifndef __P #define __P(x) x #endif #else #ifndef __P #define __P(x) () #endif #endif /* __STDC__ */ #define SPT_NONE 0 /* don't use it at all */ #define SPT_REUSEARGV 1 /* cover argv with title information */ #define SPT_BUILTIN 2 /* use libc builtin */ #define SPT_PSTAT 3 /* use pstat(PSTAT_SETCMD, ...) */ #define SPT_PSSTRINGS 4 /* use PS_STRINGS->... */ #define SPT_CHANGEARGV 7 /* write our own strings into argv[] */ #define SPACELEFT(buf, ptr) (sizeof buf - ((ptr) - buf)) #ifdef __FreeBSD__ # define SPT_TYPE SPT_BUILTIN #endif #ifdef __Linux__ # define SPT_TYPE SPT_REUSEARGV #endif #ifndef SPT_TYPE # define SPT_TYPE SPT_REUSEARGV #endif /* ! SPT_TYPE */ #define MAXLINE 2048 #if SPT_TYPE != SPT_NONE && SPT_TYPE != SPT_BUILTIN # if SPT_TYPE == SPT_PSTAT # include # endif /* SPT_TYPE == SPT_PSTAT */ # if SPT_TYPE == SPT_PSSTRINGS # include # include # ifndef PS_STRINGS /* hmmmm.... apparently not available after all */ # undef SPT_TYPE # define SPT_TYPE SPT_REUSEARGV # else /* ! PS_STRINGS */ # ifndef NKPDE /* FreeBSD 2.0 */ # define NKPDE 63 typedef unsigned int *pt_entry_t; # endif /* ! NKPDE */ # endif /* ! PS_STRINGS */ # endif /* SPT_TYPE == SPT_PSSTRINGS */ # if SPT_TYPE == SPT_PSSTRINGS || SPT_TYPE == SPT_CHANGEARGV # define SETPROC_STATIC static # else /* SPT_TYPE == SPT_PSSTRINGS || SPT_TYPE == SPT_CHANGEARGV */ # define SETPROC_STATIC # endif /* SPT_TYPE == SPT_PSSTRINGS || SPT_TYPE == SPT_CHANGEARGV */ # ifndef SPT_PADCHAR # define SPT_PADCHAR ' ' # endif /* ! SPT_PADCHAR */ #endif /* SPT_TYPE != SPT_NONE && SPT_TYPE != SPT_BUILTIN */ #ifndef SPT_BUFSIZE # define SPT_BUFSIZE MAXLINE #endif /* ! SPT_BUFSIZE */ #if _FFR_SPT_ALIGN /* ** It looks like the Compaq Tru64 5.1A now aligns argv and envp to ** 64 bit alignment, so unless each piece of argv and envp is a multiple ** of 8 bytes (including terminating NULL), initsetproctitle() won't use ** any of the space beyond argv[0]. Be sure to set SPT_ALIGN_SIZE if ** you use this FFR. */ # ifdef SPT_ALIGN_SIZE # define SPT_ALIGN(x, align) (((((x) + SPT_ALIGN_SIZE) >> (align)) << (align)) - 1) # else /* SPT_ALIGN_SIZE */ # define SPT_ALIGN(x, align) (x) # endif /* SPT_ALIGN_SIZE */ #else /* _FFR_SPT_ALIGN */ # define SPT_ALIGN(x, align) (x) #endif /* _FFR_SPT_ALIGN */ /* ** Pointers for setproctitle. ** This allows "ps" listings to give more useful information. */ static char **Argv = NULL; /* pointer to argument vector */ static char *LastArgv = NULL; /* end of argv */ #if SPT_TYPE != SPT_BUILTIN void setproctitle (const char *, ...); #endif /* SPT_TYPE != SPT_BUILTIN */ void initsetproctitle(argc, argv, envp) int argc; char **argv; char **envp; { register int i; int align; extern char **environ; /* ** Move the environment so setproctitle can use the space at ** the top of memory. */ if (envp != NULL) { for (i = 0; envp[i] != NULL; i++) continue; environ = (char **) malloc(sizeof (char *) * (i + 1)); for (i = 0; envp[i] != NULL; i++) environ[i] = strdup(envp[i]); environ[i] = NULL; } /* ** Save start and extent of argv for setproctitle. */ Argv = argv; /* ** Determine how much space we can use for setproctitle. ** Use all contiguous argv and envp pointers starting at argv[0] */ align = -1; #if _FFR_SPT_ALIGN # ifdef SPT_ALIGN_SIZE for (i = SPT_ALIGN_SIZE; i > 0; i >>= 1) align++; # endif /* SPT_ALIGN_SIZE */ #endif /* _FFR_SPT_ALIGN */ for (i = 0; i < argc; i++) { if (i == 0 || LastArgv + 1 == argv[i]) LastArgv = argv[i] + SPT_ALIGN(strlen(argv[i]), align); } for (i = 0; LastArgv != NULL && envp != NULL && envp[i] != NULL; i++) { if (LastArgv + 1 == envp[i]) LastArgv = envp[i] + SPT_ALIGN(strlen(envp[i]), align); } } #if SPT_TYPE != SPT_BUILTIN void setproctitle(const char *fmt, ...) { # if SPT_TYPE != SPT_NONE register int i; register char *p; static char buf[SPT_BUFSIZE]; va_list ap; # if SPT_TYPE == SPT_PSTAT union pstun pst; # endif /* SPT_TYPE == SPT_PSTAT */ p = buf; /* print sendmail: heading for grep */ (void) strncpy(p, "pppserver: ", SPACELEFT(buf, p)); p += strlen(p); /* print the argument string */ va_start(ap, fmt); (void) vsnprintf(p, SPACELEFT(buf, p), fmt, ap); va_end(ap); i = (int) strlen(buf); if (i < 0) return; # if SPT_TYPE == SPT_PSTAT pst.pst_command = buf; pstat(PSTAT_SETCMD, pst, i, 0, 0); # endif /* SPT_TYPE == SPT_PSTAT */ # if SPT_TYPE == SPT_PSSTRINGS PS_STRINGS->ps_nargvstr = 1; PS_STRINGS->ps_argvstr = buf; # endif /* SPT_TYPE == SPT_PSSTRINGS */ # if SPT_TYPE == SPT_REUSEARGV if (LastArgv == NULL) return; if (i > LastArgv - Argv[0] - 2) { i = LastArgv - Argv[0] - 2; buf[i] = '\0'; } memset (Argv[0], '\0', LastArgv - Argv[0] - 2); (void) strncpy(Argv[0], buf, i); Argv[1] = NULL; # endif /* SPT_TYPE == SPT_REUSEARGV */ # if SPT_TYPE == SPT_CHANGEARGV Argv[0] = buf; Argv[1] = 0; # endif /* SPT_TYPE == SPT_CHANGEARGV */ # endif /* SPT_TYPE != SPT_NONE */ } #endif /* SPT_TYPE != SPT_BUILTIN */ #ifndef HAVE_OPENPTY #define TTY_LETTERS "pqrstuvwxyzPQRST" int openpty(amaster, aslave, name, termp, winp) int *amaster, *aslave; char *name; struct termios *termp; struct winsize *winp; { char line[] = "/dev/ptyXX"; register const char *cp1, *cp2; register int master, slave, ttygid; struct group *gr; if ((gr = getgrnam("tty")) != NULL) ttygid = gr->gr_gid; else ttygid = -1; for (cp1 = TTY_LETTERS; *cp1; cp1++) { line[8] = *cp1; for (cp2 = "0123456789abcdef"; *cp2; cp2++) { line[9] = *cp2; line[5] = 'p'; if ((master = open(line, O_RDWR, 0)) == -1) { if (errno == ENOENT) return (-1); /* out of ptys */ } else { line[5] = 't'; (void) chown(line, getuid(), ttygid); (void) chmod(line, S_IRUSR|S_IWUSR|S_IWGRP); /* which is BSD only (void) revoke(line); */ if ((slave = open(line, O_RDWR, 0)) != -1) { *amaster = master; *aslave = slave; if (name) strcpy(name, line); if (termp) (void) tcsetattr(slave, TCSAFLUSH, termp); if (winp) (void) ioctl(slave, TIOCSWINSZ, (char *)winp); return (0); } (void) close(master); } } } errno = ENOENT; /* out of ptys */ return (-1); } #endif