fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / arch / um / drivers / mconsole_user.c
index 11b09a9..75aef6f 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org)
- * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2001 - 2003 Jeff Dike (jdike@addtoit.com)
  * Licensed under the GPL
  */
 
 #include <sys/un.h>
 #include <unistd.h>
 #include "user.h"
+#include "sysdep/ptrace.h"
 #include "mconsole.h"
 #include "umid.h"
+#include "user_util.h"
 
 static struct mconsole_command commands[] = {
-       { "version", mconsole_version, 1 },
-       { "halt", mconsole_halt, 0 },
-       { "reboot", mconsole_reboot, 0 },
-       { "config", mconsole_config, 0 },
-       { "remove", mconsole_remove, 0 },
-       { "sysrq", mconsole_sysrq, 1 },
-       { "help", mconsole_help, 1 },
-       { "cad", mconsole_cad, 1 },
-       { "stop", mconsole_stop, 0 },
-       { "go", mconsole_go, 1 },
+       /* With uts namespaces, uts information becomes process-specific, so
+        * we need a process context.  If we try handling this in interrupt
+        * context, we may hit an exiting process without a valid uts
+        * namespace.
+        */
+       { "version", mconsole_version, MCONSOLE_PROC },
+       { "halt", mconsole_halt, MCONSOLE_PROC },
+       { "reboot", mconsole_reboot, MCONSOLE_PROC },
+       { "config", mconsole_config, MCONSOLE_PROC },
+       { "remove", mconsole_remove, MCONSOLE_PROC },
+       { "sysrq", mconsole_sysrq, MCONSOLE_INTR },
+       { "help", mconsole_help, MCONSOLE_INTR },
+       { "cad", mconsole_cad, MCONSOLE_INTR },
+       { "stop", mconsole_stop, MCONSOLE_PROC },
+       { "go", mconsole_go, MCONSOLE_INTR },
+       { "log", mconsole_log, MCONSOLE_INTR },
+       { "proc", mconsole_proc, MCONSOLE_PROC },
+        { "stack", mconsole_stack, MCONSOLE_INTR },
 };
 
 /* Initialized in mconsole_init, which is an initcall */
@@ -57,14 +67,14 @@ static struct mconsole_command *mconsole_parse(struct mc_request *req)
        struct mconsole_command *cmd;
        int i;
 
-       for(i=0;i<sizeof(commands)/sizeof(commands[0]);i++){
+       for(i = 0; i < ARRAY_SIZE(commands); i++){
                cmd = &commands[i];
                if(!strncmp(req->request.data, cmd->command, 
                            strlen(cmd->command))){
-                       return(cmd);
+                       return cmd;
                }
        }
-       return(NULL);
+       return NULL;
 }
 
 #define MIN(a,b) ((a)<(b) ? (a):(b))
@@ -119,12 +129,16 @@ int mconsole_get_request(int fd, struct mc_request *req)
        return(1);
 }
 
-int mconsole_reply(struct mc_request *req, char *str, int err, int more)
+int mconsole_reply_len(struct mc_request *req, const char *str, int total,
+                      int err, int more)
 {
+       /* XXX This is a stack consumption problem.  It'd be nice to
+        * make it global and serialize access to it, but there are a
+        * ton of callers to this function.
+        */
        struct mconsole_reply reply;
-       int total, len, n;
+       int len, n;
 
-       total = strlen(str);
        do {
                reply.err = err;
 
@@ -139,6 +153,7 @@ int mconsole_reply(struct mc_request *req, char *str, int err, int more)
                memcpy(reply.data, str, len);
                reply.data[len] = '\0';
                total -= len;
+               str += len;
                reply.len = len + 1;
 
                len = sizeof(reply) + reply.len - sizeof(reply.data);
@@ -151,6 +166,12 @@ int mconsole_reply(struct mc_request *req, char *str, int err, int more)
        return(0);
 }
 
+int mconsole_reply(struct mc_request *req, const char *str, int err, int more)
+{
+       return mconsole_reply_len(req, str, strlen(str), err, more);
+}
+
+
 int mconsole_unlink_socket(void)
 {
        unlink(mconsole_socket_name);
@@ -169,9 +190,9 @@ int mconsole_notify(char *sock_name, int type, const void *data, int len)
        if(notify_sock < 0){
                notify_sock = socket(PF_UNIX, SOCK_DGRAM, 0);
                if(notify_sock < 0){
-                       printk("mconsole_notify - socket failed, errno = %d\n",
-                              errno);
                        err = -errno;
+                       printk("mconsole_notify - socket failed, errno = %d\n",
+                              err);
                }
        }
        unlock_notify();
@@ -194,8 +215,8 @@ int mconsole_notify(char *sock_name, int type, const void *data, int len)
        n = sendto(notify_sock, &packet, len, 0, (struct sockaddr *) &target, 
                   sizeof(target));
        if(n < 0){
-               printk("mconsole_notify - sendto failed, errno = %d\n", errno);
                err = -errno;
+               printk("mconsole_notify - sendto failed, errno = %d\n", errno);
        }
        return(err);
 }