fiss-minit

A standalone service supervisor based on minit
Log | Files | Refs | README | LICENSE

minit-update.c (5298B)


      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 
     21 static struct process* root;
     22 
     23 static int infd, outfd;
     24 static int maxprocess = -1;
     25 static int processalloc;
     26 
     27 static char buf[BUFLEN + 1];
     28 
     29 static unsigned int verbose;
     30 static int          do_update;
     31 
     32 void feed_struct_to_minit(struct process* data);
     33 
     34 ssize_t read_outfd(void* buf, size_t count);
     35 
     36 void addprocess(struct process* p);
     37 
     38 
     39 void 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
     52 void 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 
     62 void* xmalloc(size_t size) {
     63 	void* ptr = malloc(size);
     64 	if (!ptr) die("malloc() failed\n");
     65 	return ptr;
     66 }
     67 
     68 
     69 void copywrite(const char* service) {
     70 	strncpy(buf + 1, service, BUFLEN);
     71 	buf[BUFLEN] = 0;
     72 	write(infd, buf, strlen(buf));
     73 }
     74 
     75 
     76 int 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 
     88 void 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 
    161 ret:
    162 	if (service) free(service);
    163 	chdir(MINITROOT);
    164 	if (parent) chdir(parent);
    165 }
    166 
    167 
    168 int 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 
    240 ssize_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 
    248 void 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 }