vshost-util-vserver

Build script and sources for util-vserver.
git clone https://ccx.te2000.cz/git/vshost-util-vserver
Log | Files | Refs

vps.c (5846B)


      1 // $Id$    --*- c -*--
      2 
      3 // Copyright (C) 2004 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
      4 //  
      5 // This program is free software; you can redistribute it and/or modify
      6 // it under the terms of the GNU General Public License as published by
      7 // the Free Software Foundation; version 2 of the License.
      8 //  
      9 // This program is distributed in the hope that it will be useful,
     10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
     11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12 // GNU General Public License for more details.
     13 //  
     14 // You should have received a copy of the GNU General Public License
     15 // along with this program; if not, write to the Free Software
     16 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
     17 
     18 
     19 #ifdef HAVE_CONFIG_H
     20 #  include <config.h>
     21 #endif
     22 
     23 #include "util.h"
     24 #include "pathconfig.h"
     25 
     26 #include <lib/vserver.h>
     27 #include <lib/fmt.h>
     28 #include <assert.h>
     29 #include <fcntl.h>
     30 #include <signal.h>
     31 #include <errno.h>
     32 
     33 #define ENSC_WRAPPERS_VSERVER	1
     34 #define ENSC_WRAPPERS_STDLIB	1
     35 #define ENSC_WRAPPERS_UNISTD	1
     36 #define ENSC_WRAPPERS_FCNTL	1
     37 #include <wrappers.h>
     38 
     39 #define CTXNR_WIDTH	5
     40 #define HUNK_SIZE	0x4000
     41 #define CONTEXT_WIDTH	20
     42 #define CONTEXT_PLACE	"                    "
     43 
     44 int wrapper_exit_code = 254;
     45 
     46 struct ContextMapping {
     47     xid_t		ctx;
     48     char const *	id;
     49 };
     50 
     51 static struct ContextMapping		*mapping    = 0;
     52 static size_t				mapping_len = 0;
     53 
     54 
     55 static void
     56 showHelp(int fd, char const *cmd, int res)
     57 {
     58   WRITE_MSG(fd, "Usage:  ");
     59   WRITE_STR(fd, cmd);
     60   WRITE_MSG(fd,
     61 	    " <ps-opts>*\n\n"
     62 	    "Please report bugs to " PACKAGE_BUGREPORT "\n");
     63   exit(res);
     64 }
     65 
     66 static void
     67 showVersion()
     68 {
     69   WRITE_MSG(1,
     70 	    "vps " VERSION " -- shows processes in vserver-contexts\n"
     71 	    "This program is part of " PACKAGE_STRING "\n\n"
     72 	    "Copyright (C) 2004 Enrico Scholz\n"
     73 	    VERSION_COPYRIGHT_DISCLAIMER);
     74   exit(0);
     75 }
     76 
     77 
     78 static size_t
     79 writeContextInfo(xid_t ctx, char const *name)
     80 {
     81   size_t	l1  = name==0 ? 0 : strlen(name);
     82   size_t	res = CTXNR_WIDTH + 1;
     83   
     84   if (ctx==VC_NOCTX) {
     85     if (3<CTXNR_WIDTH) Vwrite(1, CONTEXT_PLACE, CTXNR_WIDTH-3);
     86     Vwrite(1, "ERR ", 4);
     87   }
     88   else {
     89     char	buf[sizeof(ctx)*3+1];
     90     size_t	l = utilvserver_fmt_ulong(buf, ctx);
     91 
     92     if (l<CTXNR_WIDTH) Vwrite(1, CONTEXT_PLACE, CTXNR_WIDTH-l);
     93     Vwrite(1, buf, l);
     94     Vwrite(1, " ", 1);
     95   }
     96 
     97   if (l1!=0) {
     98     assert(name!=0);
     99     Vwrite(1, name, l1);
    100   }
    101 
    102   return res+l1;
    103 }
    104 
    105 static xid_t
    106 extractCtx(char *pid_str)
    107 {
    108   pid_t		pid;
    109   
    110   while (*pid_str==' ') ++pid_str;
    111   pid = atoi(pid_str);
    112 
    113   return vc_get_task_xid(pid);
    114 }
    115 
    116 static char const *
    117 resolveCtx(xid_t ctx)
    118 {
    119   char const *	res;
    120   size_t	i;
    121 
    122   for (i=0; i<mapping_len; ++i)
    123     if (mapping[i].ctx==ctx) return mapping[i].id;
    124 
    125   ++mapping_len;
    126   mapping = Erealloc(mapping, mapping_len * sizeof(mapping[0]));
    127   
    128   if (ctx==0)      res = strdup("MAIN");
    129   else if (ctx==1) res = strdup("ALL_PROC");
    130   else {
    131     vcCfgStyle	style = vcCFG_AUTO;
    132     char	*tmp  = vc_getVserverByCtx(ctx, &style,0);
    133     if (tmp) res = vc_getVserverName(tmp, style);
    134     else     res = 0;
    135     free(tmp);
    136   }
    137 
    138   mapping[mapping_len-1].ctx = ctx;
    139   mapping[mapping_len-1].id  = res;
    140   return res;
    141 }
    142 
    143 static char *
    144 readOutput(int fd, size_t *total_len)
    145 {
    146   size_t	len  = 2*HUNK_SIZE;
    147   char		*buf = Emalloc(len+1);
    148   size_t	offset = 0;
    149 
    150   for (;;) {
    151     size_t	l;
    152 
    153     while (offset >= len) {
    154       len += HUNK_SIZE;
    155       buf  = Erealloc(buf, len+1);
    156     }
    157     
    158     l = Eread(fd, buf+offset, len - offset);
    159     if (l==0) break;
    160 
    161     offset += l;
    162   }
    163 
    164   buf[offset] = '\0';
    165 
    166   if (total_len)
    167     *total_len = offset;
    168 
    169   return buf;
    170 }
    171 
    172 static void
    173 processOutput(char *data, size_t len)
    174 {
    175   size_t	pid_end;
    176   char *	eol_pos = strchr(data, '\n');
    177   char *	pos;
    178 
    179   if (eol_pos==0) eol_pos  = data + len;
    180   else            *eol_pos = '\0';
    181   
    182   pos = strstr(data, "PID");
    183   if (pos==0) {
    184     WRITE_MSG(2, "Failed to parse ps-output\n");
    185     exit(wrapper_exit_code);
    186   }
    187 
    188   pid_end = pos-data + 4;
    189 
    190   Vwrite(1, data, pid_end);
    191   Vwrite(1, "CONTEXT" CONTEXT_PLACE, CONTEXT_WIDTH);
    192   Vwrite(1, data+pid_end, eol_pos-(data+pid_end));
    193   Vwrite(1, "\n", 1);
    194 
    195   len -= eol_pos-data;
    196   data = eol_pos+1;
    197   
    198   while (len > 1) {
    199     char const	*vserver_name = 0;
    200     xid_t	ctx;
    201     size_t	l;
    202 
    203     --len;
    204     eol_pos = strchr(data, '\n');
    205     
    206     if (eol_pos==0) eol_pos  = data + len;
    207 
    208     ctx          = extractCtx(data + pid_end - 6);
    209     vserver_name = resolveCtx(ctx);
    210 
    211     Vwrite(1, data, pid_end);
    212     l = writeContextInfo(ctx, vserver_name);
    213     if (l<CONTEXT_WIDTH) Vwrite(1, CONTEXT_PLACE, CONTEXT_WIDTH-l);
    214     else                 Vwrite(1, " ", 1);
    215     Vwrite(1, data+pid_end, eol_pos-(data+pid_end));
    216     Vwrite(1, "\n", 1);
    217     
    218     len -= eol_pos-data;
    219     data = eol_pos+1;
    220   }
    221 }
    222 
    223 int main(int argc, char *argv[])
    224 {
    225   int		p[2];
    226   pid_t		pid;
    227   char *	data;
    228   size_t	len;
    229   char const *	errptr;
    230 
    231   if (argc>1) {
    232     if (strcmp(argv[1], "--help")   ==0) showHelp(1, argv[0], 0);
    233     if (strcmp(argv[1], "--version")==0) showVersion();
    234   }
    235 
    236   signal(SIGCHLD, SIG_DFL);
    237 
    238   if (!switchToWatchXid(&errptr)) {
    239     perror(errptr);
    240     exit(wrapper_exit_code);
    241   }
    242 
    243   if (access("/proc/uptime",R_OK)==-1 && errno==ENOENT)
    244     WRITE_MSG(2,
    245 	      "WARNING: can not access /proc/uptime. Usually, this is caused by\n"
    246 	      "         procfs-security. Please read the FAQ for more details\n"
    247 	      "         http://linux-vserver.org/Proc-Security\n");
    248 
    249   Epipe(p);
    250   pid = Efork();
    251 
    252   if (pid==0) {
    253     int		fd = Eopen("/dev/null", O_RDONLY, 0);
    254     Edup2(fd,   0);
    255     Edup2(p[1], 1);
    256     Eclose(p[0]);
    257     Eclose(p[1]);
    258     Eclose(fd);
    259 
    260     argv[0] = "ps";
    261 
    262     Eexecv(PS_PROG, argv);
    263   }
    264 
    265   Eclose(p[1]);
    266   data = readOutput(p[0], &len);
    267   Eclose(p[0]);
    268   
    269   processOutput(data, len);
    270   vc_exitLikeProcess(pid, wrapper_exit_code);
    271 }