minit

A small yet feature-complete init (http://fefe.de/minit/)
Log | Files | Refs | README | LICENSE

minit-update.c (5575B)


      1 #include <errno.h>
      2 #include <dirent.h>
      3 #include <fcntl.h>
      4 #include <sys/file.h>
      5 #include <sys/types.h>
      6 #include <sys/stat.h>
      7 #include <unistd.h>
      8 #include <stdlib.h>
      9 #include <string.h>
     10 
     11 #include <libowfat/str.h>
     12 #include <libowfat/buffer.h>
     13 
     14 #include "minit.h"
     15 
     16 #define USAGE "Usage: minit-update [ -v [ -u ] ]\n"
     17 #define BUFLEN 1500
     18 
     19 /*
     20  increases file size by almost 4k
     21 #define WITH_STRERROR */
     22 
     23 static char buf[BUFLEN+1];
     24 
     25 static unsigned int verbose;
     26 static int do_update;
     27 
     28 void feed_struct_to_minit(struct process *data);
     29 
     30 ssize_t read_outfd(void *buf, size_t count);
     31 
     32 void addprocess(struct process *p);
     33 
     34 
     35 void die(const char *msg) {
     36  buffer_putsflush(buffer_2, msg);
     37  _exit(111);
     38 }
     39 
     40 
     41 void buffer_putsnlflush(buffer *b, const char *msg) {
     42  buffer_puts(b, msg);
     43  buffer_putflush(b, "\n",1);
     44 }
     45 
     46 
     47 #ifdef WITH_STRERROR
     48 void buffer_puts_strerror(const char *msg) {
     49  buffer_puts(buffer_2, "minit-update: ");
     50  buffer_puts(buffer_2, msg);
     51  buffer_putsnlflush(buffer_2, strerror(errno));
     52 }
     53 #else
     54 #define buffer_puts_strerror(a) buffer_putsflush(buffer_2, a)
     55 #endif 
     56 
     57 
     58 void *xmalloc(size_t size) {
     59  void *ptr=malloc(size);
     60  if (!ptr) die("malloc() failed\n");
     61  return ptr;
     62 }
     63 
     64 
     65 void copywrite (const char *service) {
     66   strncpy(buf+1,service,BUFLEN);
     67   buf[BUFLEN]=0;
     68   write(infd,buf,str_len(buf));
     69 }
     70 
     71 
     72 int read_reply_from_minit(void) {
     73   if (read_outfd(buf,BUFLEN)==1) {
     74      if (buf[0]=='1') return 1;
     75      if (buf[0]=='0') buffer_puts(buffer_2,"expected '1' from minit, got '0' - minit too old?\n");
     76   }
     77     /* XXX: Uuuh. Should this be checked? 
     78      else buffer_putsflush(buffer_2, "minit response not understood\n");
     79     */
     80 return 0;   
     81 }
     82 
     83 
     84 void find_service(int subdir, char *name, char *parent) {
     85  struct stat statbuf;
     86  char *service=0;
     87  DIR *dirstream=0;
     88  struct dirent *dir;
     89 
     90  if (chdir(name)) return;
     91 
     92  if (parent) {
     93   service=xmalloc(str_len(parent) + str_len(name) + 2 );
     94   strcpy(service, parent);
     95   strcat(service, "/");
     96   strcat(service, name);
     97  } else {
     98     if (subdir) {
     99      service=xmalloc(str_len(name)+1);
    100      strcpy(service, name);
    101     }
    102  }
    103 #if 0 
    104  buffer_putsnlflush(buffer_1,service);
    105 #endif
    106 
    107  if (service) { /* request and read a "struct process" from minit */
    108   struct process tmp;
    109 #if 0
    110   int j;
    111   for (j=0; j<=maxprocess; ++j) { /* skip duplicates */
    112    if(!strcmp(root[j].name,service)) return 0;
    113   }
    114 #endif
    115 
    116   if (verbose) {
    117     buffer_puts(buffer_1, "minit-update: status for ");
    118     buffer_puts(buffer_1, service);
    119   }
    120 
    121   buf[0]='D';
    122   copywrite(service);
    123   
    124   switch (read_outfd(&tmp,sizeof(tmp))) {
    125    case sizeof(tmp): 
    126      tmp.name=strdup(service);
    127      addprocess(&tmp);
    128      if (verbose) buffer_puts(buffer_1, " saved.\n");
    129      break;
    130    case 1:
    131      if (verbose) buffer_puts(buffer_1, " failed - minit has no information on this service\n");
    132    #if 0  
    133     break;
    134    default:
    135      buffer_puts(buffer_1, " failed - read incomplete structure!\n");
    136    #endif 
    137   }
    138  }
    139  
    140 dirstream=opendir(".");
    141 if (!dirstream) goto ret;
    142 
    143 while ( (dir=readdir(dirstream))){
    144   if (dir->d_name[0]!='.') {
    145       if(!lstat(dir->d_name, &statbuf)) {
    146         if (S_ISDIR(statbuf.st_mode)) {
    147             find_service(1, dir->d_name, service);
    148 #if 0   
    149         } else {
    150            buffer_putsnlflush(buffer_1,dir->d_name);
    151 #endif
    152         }
    153       } else {
    154         buffer_puts(buffer_2, dir->d_name);
    155         buffer_puts(buffer_2, ": cannot stat\n");
    156         buffer_puts_strerror("lstat() failed: ");
    157       }
    158   }
    159 } /* while */
    160  
    161 closedir(dirstream);
    162 
    163 ret:
    164 if (service) free(service);
    165 chdir(MINITROOT);
    166 if (parent) chdir(parent);
    167 buffer_flush(buffer_1);
    168 } 
    169 
    170 
    171 int main(int argc, char **argv) {
    172  int i;
    173 
    174  if (argc < 2) die(USAGE);
    175 
    176  while (argc>1) {
    177    argc--;
    178    if (argv[argc][0]=='-') {
    179      switch(argv[argc][1]) {
    180        case 'v': verbose++; break;
    181        case 'u': do_update=1; break;
    182        default:
    183         buffer_puts(buffer_2,"minit-update: Unknown Option: ");          
    184 	buffer_putsnlflush(buffer_2,argv[argc]);
    185      } 
    186    } else die(USAGE);
    187  }
    188 
    189  infd=open(MINITROOT "/in",O_WRONLY);
    190  outfd=open(MINITROOT "/out",O_RDONLY);
    191  
    192  if (infd<0 || outfd<0) die("could not open " MINITROOT "/in or " MINITROOT "/out\n");
    193 
    194  while (lockf(infd,F_TLOCK,1)) {
    195     buffer_puts_strerror("could not acquire lock: ");
    196     sleep(1);
    197  }
    198 
    199  find_service(0,MINITROOT,0);
    200 
    201  if (maxprocess == -1) 
    202     die("Could not extract running services from minit\n");
    203  
    204  if (verbose) buffer_putsflush(buffer_1, "minit-update: telling minit to execve itself\n");
    205  
    206  if (!do_update) {
    207    buffer_putsflush(buffer_2, "Test mode: No update done.\n");
    208    return 0;
    209  }
    210 
    211  write(infd,"update",6);
    212  sleep(1);
    213 
    214  for (i=0; i<=maxprocess; i++) {
    215     if (verbose) {
    216       buffer_puts(buffer_1, "minit-update: restoring status for ");
    217       buffer_putsnlflush(buffer_1, root[i].name);
    218     }  
    219  
    220     buf[0]='U';
    221     copywrite(root[i].name);
    222    
    223     read_reply_from_minit();
    224    
    225     write(infd,&root[i],sizeof (struct process));
    226    
    227     if (read_reply_from_minit() && verbose) {
    228       buffer_puts(buffer_1, "minit-update: restored service ");
    229       buffer_putsnlflush(buffer_1, root[i].name);
    230     }
    231         
    232  } /* for() */
    233 
    234 return 0; 
    235 }
    236 
    237 
    238 ssize_t read_outfd(void *buf, size_t count) {
    239  ssize_t br=read(outfd,buf,count);
    240 
    241  if (br<0) buffer_puts_strerror("Error reading from outfd: ");
    242 return br;
    243 }
    244 
    245 
    246 void addprocess(struct process *p) {
    247   if (maxprocess+1>=processalloc) {
    248     struct process *fump;
    249     processalloc+=8;
    250     if ((fump=(struct process *)realloc(root,processalloc*sizeof(struct process)))==0) die("realloc() failed\n ");
    251     root=fump;
    252   }
    253   memmove(&root[++maxprocess],p,sizeof(struct process));
    254 }