X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/9bccf70c0258c7cac2dcb80011b2a964d884c552..91447636331957f3d9b5ca5b508f07c526b0074d:/bsd/kern/kern_proc.c diff --git a/bsd/kern/kern_proc.c b/bsd/kern/kern_proc.c index 97f98cc1d..89a60a915 100644 --- a/bsd/kern/kern_proc.c +++ b/bsd/kern/kern_proc.c @@ -67,11 +67,10 @@ #include #include #include -#include -#include +#include #include #include -#include +#include #include #include #include @@ -79,6 +78,8 @@ #include #include #include +#include +#include /* * Structure associated with user cacheing. @@ -101,6 +102,12 @@ struct pgrphashhead *pgrphashtbl; u_long pgrphash; struct proclist allproc; struct proclist zombproc; +extern struct tty cons; + +/* Name to give to core files */ +__private_extern__ char corefilename[MAXPATHLEN+1] = {"/cores/core.%P"}; + +static void orphanpg(struct pgrp *pg); /* * Initialize global process hashing structures. @@ -148,6 +155,8 @@ chgproccnt(uid, diff) panic("chgproccnt: lost user"); } MALLOC_ZONE(uip, struct uidinfo *, sizeof(*uip), M_PROC, M_WAITOK); + if (uip == NULL) + panic("chgproccnt: M_PROC zone depleted"); LIST_INSERT_HEAD(uipp, uip, ui_hash); uip->ui_uid = uid; uip->ui_proccnt = diff; @@ -171,9 +180,7 @@ inferior(p) * Is p an inferior of t ? */ int -isinferior(p, t) - register struct proc *p; - register struct proc *t; +isinferior(struct proc *p, struct proc *t) { /* if p==t they are not inferior */ @@ -185,6 +192,186 @@ isinferior(p, t) return (1); } +int +proc_isinferior(int pid1, int pid2) +{ + proc_t p; + proc_t t; + + if (((p = pfind(pid1)) != (struct proc *)0 ) && ((t = pfind(pid2)) != (struct proc *)0)) + return (isinferior(p, t)); + return(0); +} + +proc_t +proc_find(int pid) +{ + return(pfind(pid)); +} + +int +proc_rele(__unused proc_t p) +{ + return(0); +} + +proc_t +proc_self() +{ + return(current_proc()); +} + + +int +proc_pid(proc_t p) +{ + return(p->p_pid); +} + +int +proc_ppid(proc_t p) +{ + if (p->p_pptr != (struct proc *)0) + return(p->p_pptr->p_pid); + return(0); +} + +int +proc_selfpid(void) +{ + struct proc *p = current_proc(); + return(p->p_pid); +} + + +int +proc_selfppid(void) +{ + struct proc *p = current_proc(); + if (p->p_pptr) + return(p->p_pptr->p_pid); + else + return(0); +} + +void +proc_name(int pid, char * buf, int size) +{ + struct proc *p; + + if ((p = pfind(pid))!= (struct proc *)0) { + strncpy(buf, &p->p_comm[0], size); + buf[size-1] = 0; + } +} + +void +proc_selfname(char * buf, int size) +{ + struct proc *p; + + if ((p = current_proc())!= (struct proc *)0) { + strncpy(buf, &p->p_comm[0], size); + buf[size-1] = 0; + } +} + +void +proc_signal(int pid, int signum) +{ + proc_t p; + + if ((p = pfind(pid))!= (struct proc *)0) { + psignal(p, signum); + } +} + +int +proc_issignal(int pid, sigset_t mask) +{ + proc_t p; + + if ((p = pfind(pid))!= (struct proc *)0) { + return(proc_pendingsignals(p, mask)); + } + return(0); +} + +int +proc_noremotehang(proc_t p) +{ + int retval = 0; + + if (p) + retval = p->p_flag & P_NOREMOTEHANG; + return(retval? 1: 0); + +} + +int +proc_exiting(proc_t p) +{ + int retval = 0; + + if (p) + retval = p->p_flag & P_WEXIT; + return(retval? 1: 0); +} + + +int +proc_forcequota(proc_t p) +{ + int retval = 0; + + if (p) + retval = p->p_flag & P_FORCEQUOTA; + return(retval? 1: 0); + +} + +int +proc_tbe(proc_t p) +{ + int retval = 0; + + if (p) + retval = p->p_flag & P_TBE; + return(retval? 1: 0); + +} + +int +proc_suser(proc_t p) +{ + return(suser(p->p_ucred, NULL)); + +} + +kauth_cred_t +proc_ucred(proc_t p) +{ + return(p->p_ucred); +} + + +int +proc_is64bit(proc_t p) +{ + return(IS_64BIT_PROCESS(p)); +} + +/* LP64todo - figure out how to identify 64-bit processes if NULL procp */ +int +IS_64BIT_PROCESS(proc_t p) +{ + if (p && (p->p_flag & P_LP64)) + return(1); + else + return(0); +} + + /* * Locate a process by number */ @@ -203,6 +390,21 @@ pfind(pid) return (NULL); } +/* + * Locate a zombie by PID + */ +__private_extern__ struct proc * +pzfind(pid) + register pid_t pid; +{ + register struct proc *p; + + for (p = zombproc.lh_first; p != 0; p = p->p_list.le_next) + if (p->p_pid == pid) + return (p); + return (NULL); +} + /* * Locate a process group by number */ @@ -248,6 +450,8 @@ enterpgrp(p, pgid, mksess) #endif MALLOC_ZONE(pgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP, M_WAITOK); + if (pgrp == NULL) + panic("enterpgrp: M_PGRP zone depleted"); if ((np = pfind(savepid)) == NULL || np != p) { FREE_ZONE(pgrp, sizeof(struct pgrp), M_PGRP); return (ESRCH); @@ -260,6 +464,8 @@ enterpgrp(p, pgid, mksess) */ MALLOC_ZONE(sess, struct session *, sizeof(struct session), M_SESSION, M_WAITOK); + if (sess == NULL) + panic("enterpgrp: M_SESSION zone depleted"); sess->s_leader = p; sess->s_sid = p->p_pid; sess->s_count = 1; @@ -322,13 +528,21 @@ void pgdelete(pgrp) register struct pgrp *pgrp; { + struct tty * ttyp; + int removettypgrp = 0; + ttyp = pgrp->pg_session->s_ttyp; if (pgrp->pg_session->s_ttyp != NULL && - pgrp->pg_session->s_ttyp->t_pgrp == pgrp) + pgrp->pg_session->s_ttyp->t_pgrp == pgrp) { pgrp->pg_session->s_ttyp->t_pgrp = NULL; + removettypgrp = 1; + } LIST_REMOVE(pgrp, pg_hash); - if (--pgrp->pg_session->s_count == 0) + if (--pgrp->pg_session->s_count == 0) { + if (removettypgrp && (ttyp == &cons) && (ttyp->t_session == pgrp->pg_session)) + ttyp->t_session = 0; FREE_ZONE(pgrp->pg_session, sizeof(struct session), M_SESSION); + } FREE_ZONE(pgrp, sizeof *pgrp, M_PGRP); } @@ -340,8 +554,6 @@ sessrele(sess) FREE_ZONE(sess, sizeof (struct session), M_SESSION); } -static void orphanpg(); - /* * Adjust pgrp jobc counters when specified process changes process group. * We count the number of processes in each process group that "qualify" @@ -353,10 +565,7 @@ static void orphanpg(); * entering == 1 => p is entering specified group. */ void -fixjobc(p, pgrp, entering) - register struct proc *p; - register struct pgrp *pgrp; - int entering; +fixjobc(struct proc *p, struct pgrp *pgrp, int entering) { register struct pgrp *hispgrp; register struct session *mysession = pgrp->pg_session; @@ -366,11 +575,12 @@ fixjobc(p, pgrp, entering) * group; if so, adjust count for p's process group. */ if ((hispgrp = p->p_pptr->p_pgrp) != pgrp && - hispgrp->pg_session == mysession) + hispgrp->pg_session == mysession) { if (entering) pgrp->pg_jobc++; else if (--pgrp->pg_jobc == 0) orphanpg(pgrp); + } /* * Check this process' children to see whether they qualify @@ -380,11 +590,12 @@ fixjobc(p, pgrp, entering) for (p = p->p_children.lh_first; p != 0; p = p->p_sibling.le_next) if ((hispgrp = p->p_pgrp) != pgrp && hispgrp->pg_session == mysession && - p->p_stat != SZOMB) + p->p_stat != SZOMB) { if (entering) hispgrp->pg_jobc++; else if (--hispgrp->pg_jobc == 0) orphanpg(hispgrp); + } } /* @@ -393,8 +604,7 @@ fixjobc(p, pgrp, entering) * hang-up all process in that group. */ static void -orphanpg(pg) - struct pgrp *pg; +orphanpg(struct pgrp *pg) { register struct proc *p; @@ -412,15 +622,17 @@ orphanpg(pg) } #ifdef DEBUG +void pgrpdump(void); /* forward declare here (called from debugger) */ + void -pgrpdump() +pgrpdump(void) { - register struct pgrp *pgrp; - register struct proc *p; - register i; + struct pgrp *pgrp; + struct proc *p; + u_long i; for (i = 0; i <= pgrphash; i++) { - if (pgrp = pgrphashtbl[i].lh_first) { + if ((pgrp = pgrphashtbl[i].lh_first) != NULL) { printf("\tindx %d\n", i); for (; pgrp != 0; pgrp = pgrp->pg_hash.le_next) { printf("\tpgrp 0x%08x, pgid %d, sess %p, sesscnt %d, mem %p\n", @@ -438,7 +650,84 @@ pgrpdump() } #endif /* DEBUG */ -struct proc * current_proc_EXTERNAL() +/* XXX should be __private_extern__ */ +int +proc_is_classic(struct proc *p) +{ + return (p->p_flag & P_CLASSIC) ? 1 : 0; +} + +/* XXX Why does this function exist? Need to kill it off... */ +struct proc * +current_proc_EXTERNAL(void) { return (current_proc()); } + +/* + * proc_core_name(name, uid, pid) + * Expand the name described in corefilename, using name, uid, and pid. + * corefilename is a printf-like string, with three format specifiers: + * %N name of process ("name") + * %P process id (pid) + * %U user id (uid) + * For example, "%N.core" is the default; they can be disabled completely + * by using "/dev/null", or all core files can be stored in "/cores/%U/%N-%P". + * This is controlled by the sysctl variable kern.corefile (see above). + */ +__private_extern__ char * +proc_core_name(const char *name, uid_t uid, pid_t pid) +{ + const char *format, *appendstr; + char *temp; + char id_buf[11]; /* Buffer for pid/uid -- max 4B */ + size_t i, l, n; + + format = corefilename; + MALLOC(temp, char *, MAXPATHLEN, M_TEMP, M_NOWAIT | M_ZERO); + if (temp == NULL) + return (NULL); + for (i = 0, n = 0; n < MAXPATHLEN && format[i]; i++) { + switch (format[i]) { + case '%': /* Format character */ + i++; + switch (format[i]) { + case '%': + appendstr = "%"; + break; + case 'N': /* process name */ + appendstr = name; + break; + case 'P': /* process id */ + sprintf(id_buf, "%u", pid); + appendstr = id_buf; + break; + case 'U': /* user id */ + sprintf(id_buf, "%u", uid); + appendstr = id_buf; + break; + default: + appendstr = ""; + log(LOG_ERR, + "Unknown format character %c in `%s'\n", + format[i], format); + } + l = strlen(appendstr); + if ((n + l) >= MAXPATHLEN) + goto toolong; + bcopy(appendstr, temp + n, l); + n += l; + break; + default: + temp[n++] = format[i]; + } + } + if (format[i] != '\0') + goto toolong; + return (temp); +toolong: + log(LOG_ERR, "pid %ld (%s), uid (%lu): corename is too long\n", + (long)pid, name, (u_long)uid); + FREE(temp, M_TEMP); + return (NULL); +}