unix/fiss-minit

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

minit-update.c (5298B) download


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