unix/minit

minit-update.c in master
Repositories | Summary | Log | Files | README | COPYING

minit-update.c (5575B) download


  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
 23static char buf[BUFLEN+1];
 24
 25static unsigned int verbose;
 26static int do_update;
 27
 28void feed_struct_to_minit(struct process *data);
 29
 30ssize_t read_outfd(void *buf, size_t count);
 31
 32void addprocess(struct process *p);
 33
 34
 35void die(const char *msg) {
 36 buffer_putsflush(buffer_2, msg);
 37 _exit(111);
 38}
 39
 40
 41void 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
 48void 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
 58void *xmalloc(size_t size) {
 59 void *ptr=malloc(size);
 60 if (!ptr) die("malloc() failed\n");
 61 return ptr;
 62}
 63
 64
 65void copywrite (const char *service) {
 66  strncpy(buf+1,service,BUFLEN);
 67  buf[BUFLEN]=0;
 68  write(infd,buf,str_len(buf));
 69}
 70
 71
 72int 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    */
 80return 0;   
 81}
 82
 83
 84void 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 
140dirstream=opendir(".");
141if (!dirstream) goto ret;
142
143while ( (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 
161closedir(dirstream);
162
163ret:
164if (service) free(service);
165chdir(MINITROOT);
166if (parent) chdir(parent);
167buffer_flush(buffer_1);
168} 
169
170
171int 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
234return 0; 
235}
236
237
238ssize_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: ");
242return br;
243}
244
245
246void 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}