]> git.saurik.com Git - apple/system_cmds.git/blobdiff - lsmp.tproj/lsmp.c
system_cmds-790.tar.gz
[apple/system_cmds.git] / lsmp.tproj / lsmp.c
index 463c24984f83d33868a41c89e4129013d957c411..2e46f7009d7203b4aaff338d190e51678d05b3e9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002-20014 Apple Inc. All rights reserved.
+ * Copyright (c) 2002-2016 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  *
@@ -27,8 +27,9 @@
 #include <stdlib.h>
 #include <libproc.h>
 #include <TargetConditionals.h>
+#include <errno.h>
 #include "common.h"
-
+#include "json.h"
 
 #if TARGET_OS_EMBEDDED
 #define TASK_FOR_PID_USAGE_MESG "\nPlease check your boot-args to ensure you have access to task_for_pid()."
 #define TASK_FOR_PID_USAGE_MESG ""
 #endif
 
-
 struct prog_configs lsmp_config = {
     .show_all_tasks         = FALSE,
     .show_voucher_details   = FALSE,
     .verbose                = FALSE,
     .pid                    = 0,
+    .json_output            = NULL,
 };
 
-my_per_task_info_t *psettaskinfo;
-mach_msg_type_number_t taskCount;
-
 static void print_usage(char *progname) {
     fprintf(stderr, "Usage: %s -p <pid> [-a|-v|-h] \n", "lsmp");
     fprintf(stderr, "Lists information about mach ports. Please see man page for description of each column.\n");
     fprintf(stderr, "\t-p <pid> :  print all mach ports for process id <pid>. \n");
     fprintf(stderr, "\t-a :  print all mach ports for all processeses. \n");
     fprintf(stderr, "\t-v :  print verbose details for kernel objects.\n");
+    fprintf(stderr, "\t-j <path> :  save output as JSON to <path>.\n");
     fprintf(stderr, "\t-h :  print this help.\n");
     exit(1);
 }
 
+static void print_task_info(my_per_task_info_t *taskinfo, mach_msg_type_number_t taskCount, my_per_task_info_t *psettaskinfo, boolean_t verbose, JSON_t json) {
+    printf("Process (%d) : %s\n", taskinfo->pid, taskinfo->processName);
+    JSON_OBJECT_BEGIN(json);
+    JSON_OBJECT_SET(json, pid, %d, taskinfo->pid);
+    JSON_OBJECT_SET(json, name, "%s", taskinfo->processName);
+    show_task_mach_ports(taskinfo, taskCount, psettaskinfo, json);
+    print_task_exception_info(taskinfo, json);
+    if (verbose) {
+        printf("\n");
+        print_task_threads_special_ports(taskinfo, json);
+    }
+    JSON_OBJECT_END(json);
+}
 
 int main(int argc, char *argv[]) {
     kern_return_t ret;
@@ -66,25 +78,27 @@ int main(int argc, char *argv[]) {
     char *progname = "lsmp";
     int i, option = 0;
     lsmp_config.voucher_detail_length = 128; /* default values for config */
-    
-    while((option = getopt(argc, argv, "hvalp:")) != -1) {
+    my_per_task_info_t *psettaskinfo;
+    mach_msg_type_number_t taskCount;
+
+    while((option = getopt(argc, argv, "hvalp:j:")) != -1) {
                switch(option) {
             case 'a':
                 /* user asked for info on all processes */
                 lsmp_config.pid = 0;
                 lsmp_config.show_all_tasks = 1;
                 break;
-                
+
             case 'l':
                 /* for compatibility with sysdiagnose's usage of -all */
                 lsmp_config.voucher_detail_length = 1024;
                 /* Fall through to 'v' */
-                
+
             case 'v':
                 lsmp_config.show_voucher_details = TRUE;
                 lsmp_config.verbose = TRUE;
                 break;
-                
+
             case 'p':
                 lsmp_config.pid = atoi(optarg);
                 if (lsmp_config.pid == 0) {
@@ -92,28 +106,34 @@ int main(int argc, char *argv[]) {
                     exit(1);
                 }
                 break;
-                
+
+            case 'j':
+                lsmp_config.json_output = JSON_OPEN(optarg);
+                if (lsmp_config.json_output == NULL) {
+                    fprintf(stderr, "Unable to open \"%s\": %s\n", optarg, strerror(errno));
+                    exit(1);
+                }
+                break;
+
             default:
                 fprintf(stderr, "Unknown argument. \n");
                 /* Fall through to 'h' */
-                
+
             case 'h':
                 print_usage(progname);
                 break;
-                
+
         }
     }
     argc -= optind;
     argv += optind;
-    
-    
+
        /* if privileged, get the info for all tasks so we can match ports up */
        if (geteuid() == 0) {
                processor_set_name_array_t psets;
                mach_msg_type_number_t psetCount;
                mach_port_t pset_priv;
-        
-               
+
                ret = host_processor_sets(mach_host_self(), &psets, &psetCount);
                if (ret != KERN_SUCCESS) {
                        fprintf(stderr, "host_processor_sets() failed: %s\n", mach_error_string(ret));
@@ -123,7 +143,7 @@ int main(int argc, char *argv[]) {
                        fprintf(stderr, "Assertion Failure: pset count greater than one (%d)\n", psetCount);
                        exit(1);
                }
-        
+
                /* convert the processor-set-name port to a privileged port */
                ret = host_processor_set_priv(mach_host_self(), psets[0], &pset_priv);
                if (ret != KERN_SUCCESS) {
@@ -132,7 +152,7 @@ int main(int argc, char *argv[]) {
                }
                mach_port_deallocate(mach_task_self(), psets[0]);
                vm_deallocate(mach_task_self(), (vm_address_t)psets, (vm_size_t)psetCount * sizeof(mach_port_t));
-        
+
                /* convert the processor-set-priv to a list of tasks for the processor set */
                ret = processor_set_tasks(pset_priv, &tasks, &taskCount);
                if (ret != KERN_SUCCESS) {
@@ -140,7 +160,22 @@ int main(int argc, char *argv[]) {
                        exit(1);
                }
                mach_port_deallocate(mach_task_self(), pset_priv);
-        
+
+        /* swap my current instances port to be last to collect all threads and exception port info */
+        int myTaskPosition = -1;
+        for (int i = 0; i < taskCount; i++) {
+            if (tasks[i] == mach_task_self()){
+                myTaskPosition = i;
+                break;
+            }
+        }
+        if (myTaskPosition >= 0) {
+            mach_port_t swap_holder = MACH_PORT_NULL;
+            swap_holder = tasks[taskCount - 1];
+            tasks[taskCount - 1] = tasks[myTaskPosition];
+            tasks[myTaskPosition] = swap_holder;
+        }
+
        }
        else
        {
@@ -154,58 +189,53 @@ int main(int argc, char *argv[]) {
         taskCount = 1;
         tasks = &aTask;
        }
-    
+
     /* convert each task to structure of pointer for the task info */
     psettaskinfo = allocate_taskinfo_memory(taskCount);
-    
+
     for (i = 0; i < taskCount; i++) {
         ret = collect_per_task_info(&psettaskinfo[i], tasks[i]);
         if (ret != KERN_SUCCESS) {
             printf("Ignoring failure of mach_port_space_info() for task %d for '-all'\n", tasks[i]);
             continue;
         }
-        
+
         if (psettaskinfo[i].pid == lsmp_config.pid)
             taskinfo = &psettaskinfo[i];
-        
+
         ret = KERN_SUCCESS;
     }
-    
-    
+
+    JSON_OBJECT_BEGIN(lsmp_config.json_output);
+    JSON_OBJECT_SET(lsmp_config.json_output, version, "%.1f", 1.0);
+    JSON_KEY(lsmp_config.json_output, processes);
+    JSON_ARRAY_BEGIN(lsmp_config.json_output);
+
     if (lsmp_config.show_all_tasks == FALSE) {
         if (taskinfo == NULL) {
             fprintf(stderr, "Failed to find task ipc information for pid %d\n", lsmp_config.pid);
             exit(1);
         }
-        printf("Process (%d) : %s\n", taskinfo->pid, taskinfo->processName);
-        show_task_mach_ports(taskinfo, taskCount, psettaskinfo);
-        print_task_exception_info(taskinfo);
-        printf("\n");
-        print_task_threads_special_ports(taskinfo);
-
-        
+        print_task_info(taskinfo, taskCount, psettaskinfo, TRUE, lsmp_config.json_output);
     } else {
         for (i=0; i < taskCount; i++) {
             if (psettaskinfo[i].valid != TRUE)
                 continue;
-            printf("Process (%d) : %s\n", psettaskinfo[i].pid, psettaskinfo[i].processName);
-            show_task_mach_ports(&psettaskinfo[i], taskCount, psettaskinfo);
-            print_task_exception_info(&psettaskinfo[i]);
-
-            if (lsmp_config.verbose) {
-                printf("\n");
-                print_task_threads_special_ports(&psettaskinfo[i]);
-            }
-
+            print_task_info(&psettaskinfo[i], taskCount, psettaskinfo, lsmp_config.verbose, lsmp_config.json_output);
             printf("\n\n");
         }
     }
-    
+
+    JSON_ARRAY_END(lsmp_config.json_output);
+    JSON_OBJECT_END(lsmp_config.json_output);
+
        if (taskCount > 1) {
         vm_deallocate(mach_task_self(), (vm_address_t)tasks, (vm_size_t)taskCount * sizeof(mach_port_t));
     }
-    
+
     deallocate_taskinfo_memory(psettaskinfo);
-    
+
+    JSON_CLOSE(lsmp_config.json_output);
+
        return(0);
 }