]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/kern/kern_proc.c
xnu-517.9.5.tar.gz
[apple/xnu.git] / bsd / kern / kern_proc.c
index e040cd76eab9a2fb5b0ce67870276eef936b539e..2a46362175cde005fe03f67f8aee7009da31d10d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -79,6 +79,7 @@
 #include <sys/ioctl.h>
 #include <sys/tty.h>
 #include <sys/signalvar.h>
+#include <sys/syslog.h>
 
 /*
  * Structure associated with user cacheing.
@@ -102,6 +103,11 @@ u_long pgrphash;
 struct proclist allproc;
 struct proclist zombproc;
 
+/* 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.
  */
@@ -167,6 +173,21 @@ inferior(p)
                        return (0);
        return (1);
 }
+/*
+ * Is p an inferior of t ?
+ */
+int
+isinferior(struct proc *p, register struct proc *t)
+{
+
+       /* if p==t they are not inferior */
+       if (p == t)
+               return(0);
+       for (; p != t; p = p->p_pptr)
+               if (p->p_pid == 0)
+                       return (0);
+       return (1);
+}
 
 /*
  * Locate a process by number
@@ -186,6 +207,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
  */
@@ -231,8 +267,10 @@ enterpgrp(p, pgid, mksess)
 #endif
                MALLOC_ZONE(pgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP,
                    M_WAITOK);
-               if ((np = pfind(savepid)) == NULL || np != p)
+               if ((np = pfind(savepid)) == NULL || np != p) {
+                       FREE_ZONE(pgrp, sizeof(struct pgrp), M_PGRP);
                        return (ESRCH);
+               }
                if (mksess) {
                        register struct session *sess;
 
@@ -242,6 +280,7 @@ enterpgrp(p, pgid, mksess)
                        MALLOC_ZONE(sess, struct session *,
                                sizeof(struct session), M_SESSION, M_WAITOK);
                        sess->s_leader = p;
+                       sess->s_sid = p->p_pid;
                        sess->s_count = 1;
                        sess->s_ttyvp = NULL;
                        sess->s_ttyp = NULL;
@@ -320,8 +359,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"
@@ -333,10 +370,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;
@@ -346,11 +380,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
@@ -360,12 +395,13 @@ 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);
 }
+}
 
 /* 
  * A process group has become orphaned;
@@ -373,8 +409,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;
 
@@ -418,7 +453,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);
+}