diff options
Diffstat (limited to 'splash/splash.c')
-rw-r--r-- | splash/splash.c | 656 |
1 files changed, 656 insertions, 0 deletions
diff --git a/splash/splash.c b/splash/splash.c new file mode 100644 index 0000000..1e25e1b --- /dev/null +++ b/splash/splash.c @@ -0,0 +1,656 @@ +/* Splash control program. + * + * (c) 2001, 2002 by Stefan Reinauer <stepan@suse.de> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <libgen.h> +#include <getopt.h> + +#define PROCSPLASH "/proc/splash" +#define SPLASHDSC "/etc/bootsplash/themes/current/config/animations.cfg" +#define BUFSIZE 4096 + +#ifndef FBMNGDEBUG +#define DEBUG(x...) +#else +#define DEBUG(x...) printf(x) +#endif + +long unit = 0; +long version = 1; +long state = -1; +long fgcolor = -1; +long bgcolor = -1; +long tx = -1; +long ty = -1; +long tw = -1; +long th = -1; +long px = 0; +long py = 0; +long pw = 0; +long ph = 0; +long pr = 0; +long pg = 0; +long pb = 0; +long pa = 160; +long pf = 1; +long pc = 0x141464; +long ptl = 0xffff; +long pbr = 0x00; +long ax = 0; +long ay = 0; +long progress = 0; +long overpaintok = 0; +long percent = 0; +long text = 0; +char *jpgfile = 0; +char *silentjpgfile = 0; +char *LOGO_CONSOLE = 0; +char *text_font = 0; + +int boxcount; +unsigned char boxes[12 * 256]; +int sboxcount; +unsigned char sboxes[12 * 256]; + +struct parstab { + char *name; + long *val; + char **str; +} parstab[] = { + {"unit", &unit}, + {"version", &version}, + {"state", &state}, + {"fgcolor", &fgcolor}, + {"bgcolor", &bgcolor}, + + /* v1+ */ + {"tx", &tx}, + {"ty", &ty}, + {"tw", &tw}, + {"th", &th}, + + /* v2+ */ + {"px", &px}, + {"py", &py}, + {"pw", &pw}, + {"ph", &ph}, + {"pr", &pr}, + {"pg", &pg}, + {"pb", &pb}, + {"ax", &ax}, + {"ay", &ay}, + + /* v3+ */ + /* independant */ + {"progress_enable", &progress}, + {"progress_x", &progress}, + {"progress_y", &progress}, + {"progress_width", &progress}, + {"progress_height", &progress}, + {"progress_fgcolor", &progress}, + {"progress_bgcolor", &progress}, + {"text_size", &text}, + {"text_color", &text}, + {"text_x", &text}, + {"text_y", &text}, + {"text_font", (long *)0, &text_font}, + + {"silentjpeg", (long *)0, &silentjpgfile}, + {"percent", &percent}, + {"overpaintok", &overpaintok}, + + {"jpeg", (long *)0, &jpgfile}, + + {"LOGO_CONSOLE", (long *)0, &LOGO_CONSOLE}, + + {(char *)0, (long *)0}, +}; + +void parsebox(char *pl) +{ + int co[4]; + int i, j, c, d=0; + char cols[16]; + unsigned char *bp; + int boxcnt; + int isibox = 0; + int *boxcntp; + unsigned char *boxptr; + char *p = pl + 3; + int noover = 0; + int hidemax = 0; + + boxcntp = &boxcount; + boxptr = boxes; + for (i = 0; i < 4; i++) + { + if (*p != ' ' && *p != '\t' && *p != '=') + { + fprintf(stderr, "syntax error: '%c' %s\n", *p, pl); + exit(1); + } + while(*p == ' ' || *p == '\t' || *p== '=') + p++; + if (i == 0 && !strncmp(p, "silent", 6)) + { + i--; + boxcntp = &sboxcount; + boxptr = sboxes; + p += 6; + continue; + } + if (i == 0 && !strncmp(p, "inter", 5)) + { + i--; + isibox = 1; + p += 5; + continue; + } + if (i == 0 && !strncmp(p, "noover", 6)) + { + i--; + noover = 1; + p += 6; + continue; + } + if (i == 0 && !strncmp(p, "hidemax", 7)) + { + i--; + hidemax = 1; + p += 7; + continue; + } + co[i] = strtol(p, (char **)NULL, 0); + while(*p == 'x' || (*p >= '0' && *p <= '9') || (*p >= 'a' && *p <= 'f') || (*p >= 'A' && *p <= 'F')) + p++; + } + for (i = 0; i < 4; i++) + { + if (*p != ' ' && *p != '\t') + { + fprintf(stderr, "syntax error: %s\n", pl); + exit(1); + } + while(*p == ' ' || *p == '\t') + p++; + if (i == 1 && *p == 0) + break; + if (*p++ != '#') + { + fprintf(stderr, "syntax error: %s\n", pl); + exit(1); + } + for (j = 0; j < 8; j++) + { + c = *p++; + if (c >= '0' && c <= '9') + c -= '0'; + else if (c >= 'a' && c <= 'f') + c -= 'a' - 10; + else if (c >= 'A' && c <= 'F') + c -= 'A' - 10; + else + { + fprintf(stderr, "syntax error: %s\n", pl); + exit(1); + } + if (!(j & 1)) + { + d = c; + continue; + } + c += d << 4; + cols[i * 4 + (j >> 1)] = c; + if (j == 5 && (*p == 0 || *p == ' ' || *p == '\t')) + { + cols[i * 4 + 3] = 255; + break; + } + } + if (*p == 0 && i == 0) + { + i = 1; + break; + } + } + while(*p == ' ' || *p == '\t') + p++; + if (*p) + { + fprintf(stderr, "syntax error: %s\n", pl); + exit(1); + } + boxcnt = *boxcntp; + if (boxcnt >= 254) + { + fprintf(stderr, "too many boxes\n"); + exit(1); + } + bp = boxptr + 12 * boxcnt++; + if (isibox) + co[0] = ~co[0]; + if (i > 1) + { + co[1] = ~co[1]; + boxcnt++; + } + if (noover) + co[2] = ~co[2]; + if (hidemax) + co[3] = ~co[3]; + *bp++ = co[0] & 255; + *bp++ = co[0] >> 8; + *bp++ = co[1] & 255; + *bp++ = co[1] >> 8; + *bp++ = co[2] & 255; + *bp++ = co[2] >> 8; + *bp++ = co[3] & 255; + *bp++ = co[3] >> 8; + for (j = 0; j < i * 4; j++) + *bp++ = cols[j]; + *boxcntp = boxcnt; +} + +void setsplash(char *cfgfile, int filterflag, int verbose_only) +{ + struct stat stb; + char buf[256]; + char *p; + int l, size, fd; + FILE *fp = 0; + FILE *sfp = 0; + struct parstab *pt; + unsigned char *pic; + int silentl = 0; + + if (cfgfile) { + if ((fp = fopen(cfgfile, "r")) == 0) { + perror(cfgfile); + exit(1); + } + while (fgets(buf, sizeof(buf), fp)) { + l = strlen(buf); + if (l == 0) + continue; + if (l == sizeof(buf) - 1) { + fprintf(stderr, "line too long\n"); + exit(1); + } + buf[--l] = 0; + while(l && (buf[l - 1] == ' ' || (buf[l - 1] == '\t'))) + buf[--l] = 0; + for (p = buf; *p == ' ' || *p == '\t'; p++) + ; + if (*p == 0 || *p == '#') + continue; + if (!strncmp(p, "box", 3)) + { + parsebox(p); + continue; + } + for (pt = parstab; pt->name; pt++) { + l = strlen(pt->name); + if (!strncmp(p, pt->name, l) && (p[l] == ' ' || p[l] == '\t' || p[l] == '=')) + break; + } + if (!pt->name) { + fprintf(stderr, "syntax error: %s\n", p); + exit(1); + } + while (p[l] == ' ' || p[l] == '\t') + l++; + if (p[l++] != '=') { + fprintf(stderr, "syntax error: %s\n", p); + exit(1); + } + while (p[l] == ' ' || p[l] == '\t') + l++; + if (pt->val) + *pt->val = strtol(p + l, (char **)NULL, 0); + else + *pt->str = strdup(p + l); + } + fclose(fp); + if (!jpgfile) { + l = strlen(cfgfile); + if (l > 4 && !strcmp(cfgfile + l - 4, ".cfg")) { + jpgfile = strdup(cfgfile); + strcpy(jpgfile + l - 4, ".jpg"); + p=strstr(jpgfile,"config"); + if(p) + strncpy(p, "images", 6); + } + } + + if (tx == 0 && ty == 0 && tw == 0 && th == 0) { + tx=px+8; + ty=py+4; + tw=pw-16; + th=ph-8; + } + + if (jpgfile && (*jpgfile == 0 || tx < 0 || ty < 0 || tw <= 0 || th <= 0)) { + free(jpgfile); + jpgfile = 0; + } + } + + if (verbose_only) + silentjpgfile=NULL; + + + if (silentjpgfile && jpgfile) { + if ((sfp = fopen(silentjpgfile, "r")) == 0) { + perror(silentjpgfile); + exit(1); + } + if (fstat(fileno(sfp), &stb) == -1) { + perror("fstat"); + exit(1); + } + silentl = stb.st_size; + } + + if (jpgfile) { + if ((fp = fopen(jpgfile, "r")) == 0) { + perror(jpgfile); + exit(1); + } + if (fstat(fileno(fp), &stb) == -1) { + perror("fstat"); + exit(1); + } + l = stb.st_size; + pic = calloc(47 + l + silentl + boxcount * 12 + sboxcount * 12, 1); + if (pic == 0) { + fprintf(stderr, "Out of memory.\n"); + exit(1); + } + if (fread(pic + 47 + boxcount * 12, l , 1, fp) != 1) { + perror("fread"); + exit(1); + } + if (silentjpgfile) { + if (fread(pic + 47 + l + boxcount * 12 + sboxcount * 12, silentl , 1, sfp) != 1) { + perror("fread"); + exit(1); + } + fclose(sfp); + if (sboxcount) + memmove(pic + 47 + l + boxcount * 12, sboxes, sboxcount * 12); + silentl += sboxcount * 12; + l += silentl; + } + fclose(fp); + } else { + l = 0; + pic = calloc(47, 1); + if (pic == 0) { + fprintf(stderr, "Out of memory.\n"); + exit(1); + } + } + size = l; + if (version < 1 || version > 3) { + fprintf(stderr, "Illegal version: %ld\n", version); + exit(1); + } + if (version == 1 && unit != 0) { + /* convert to version 2 */ + tx *= 8; + ty *= 16; + tw *= 8; + th *= 16; + px = tx + 10; + py = ty + 10; + pw = tw - 20; + ph = th - 20; + pr = pg = pb = 240; + state = 1; + fgcolor = 0; + bgcolor = 15; + version = 2; + } + if (version == 1) { + /* write version 1 file */ + strcpy(pic, "BOOTSPL1"); + pic[8] = tx; + pic[9] = tx >> 8; + pic[10] = ty; + pic[11] = ty >> 8; + pic[12] = tw; + pic[13] = tw >> 8; + pic[14] = th; + pic[15] = th >> 8; + pic[16] = size; + pic[17] = size >> 8; + pic[18] = size >> 16; + pic[19] = size >> 24; + if (l > 0) + memmove(pic + 20, pic + 47, l); + l += 20; + } else if (version == 2) { + /* write version 2 file */ + strcpy(pic, "BOOTSPL2"); + pic[8] = unit; + pic[9] = state; + pic[10] = fgcolor; + pic[11] = bgcolor; + if (cfgfile && size == 0 && (state != -1 || fgcolor != -1 || bgcolor != -1)) + size = -1; + pic[12] = size; + pic[13] = size >> 8; + pic[14] = size >> 16; + pic[15] = size >> 24; + pic[16] = tx; + pic[17] = tx >> 8; + pic[18] = ty; + pic[19] = ty >> 8; + pic[20] = tw; + pic[21] = tw >> 8; + pic[22] = th; + pic[23] = th >> 8; + pic[24] = px; + pic[25] = px >> 8; + pic[26] = py; + pic[27] = py >> 8; + pic[28] = pw; + pic[29] = pw >> 8; + pic[30] = ph; + pic[31] = ph >> 8; + pic[32] = pr; + pic[33] = pg; + pic[34] = pb; + if (l > 0) + memmove(pic + 35, pic + 47, l); + l += 35; + } else { /* version 3 */ + strcpy(pic, "BOOTSPL3"); + pic[8] = unit; + pic[9] = state; + pic[10] = fgcolor; + pic[11] = bgcolor; + size += boxcount * 12; + if (cfgfile && size == 0 && (state != -1 || fgcolor != -1 || bgcolor != -1)) + size = -1; + pic[12] = size; + pic[13] = size >> 8; + pic[14] = size >> 16; + pic[15] = size >> 24; + pic[16] = tx; + pic[17] = tx >> 8; + pic[18] = ty; + pic[19] = ty >> 8; + pic[20] = tw; + pic[21] = tw >> 8; + pic[22] = th; + pic[23] = th >> 8; + pic[24] = boxcount; + pic[25] = boxcount >> 8; + pic[28] = silentl; + pic[29] = silentl >> 8; + pic[30] = silentl >> 16; + pic[31] = silentl >> 24; + pic[32] = sboxcount; + pic[33] = sboxcount >> 8; + pic[34] = percent; + pic[35] = percent >> 8; + pic[36] = overpaintok; + pic[37] = 0; /* numpalette */ + if (l > 0) + memmove(pic + 38 + boxcount * 12, pic + 47 + boxcount * 12, l); + if (boxcount) + memmove(pic + 38, boxes, boxcount * 12); + l += 38 + boxcount * 12; + } + + if (filterflag) + fd = 1; + else if ((fd = open(PROCSPLASH, O_WRONLY)) == -1) { + perror(PROCSPLASH); + exit(1); + } + if (write(fd, pic, l) != l) { + perror("write"); + exit(1); + } + if (!filterflag) + close(fd); + free(pic); +} + +void spawncommand(unsigned char *command) +{ + DEBUG("splash: Spawning command %s.\n", command); + system(command); +} + +int main(int argc, char *argv[]) +{ + int procsplash, splashdsc, c; + int setflag = 0; + int errflag = 0; + int filterflag = 0; + int verbose_only = 0; + unsigned char *readbuffer; + unsigned char *versiontext, *statustext; + unsigned char *match,*command, *cmp; + unsigned char *tokenize; + + while ((c = getopt(argc, argv, "fsu:n")) != EOF) { + switch (c) { + case 's': + setflag = 1; + break; + case 'f': + filterflag = 1; + break; + case 'u': + unit = atoi(optarg); + break; + case 'n': + verbose_only=1; + break; + case '?': + errflag = 1; + break; + } + } + + if (errflag || (argc != optind + 1 && (argc != optind || !setflag))) { + printf("Usage: %s logstring\n",argv[0]); + printf(" %s -s [-u unit] -n [cfgfile]\n",argv[0]); + return 0; + } + + readbuffer = malloc(BUFSIZE); + + if (!readbuffer) { + DEBUG("splash: Not enough memory.\n"); + return -ENOMEM; + } + + if (!setflag || !filterflag) { + procsplash = open(PROCSPLASH, O_RDONLY); + if (procsplash < 0) { + if (setflag) { + perror(PROCSPLASH); + exit(1); + } + DEBUG("splash: File %s not available.\n",PROCSPLASH); + return 0; + } + + if (read(procsplash, readbuffer, BUFSIZE)<0) { + if (setflag) + perror("read"); + DEBUG("splash: Read error in file %s.\n",PROCSPLASH); + return -EBUSY; + } + close(procsplash); + } + if (setflag) { + if (!filterflag && !strncmp(readbuffer, "Splash screen v0", 16)) { + fprintf(stderr, "Your kernel does not support new-style splash pictures.\n"); + exit(1); + } + setsplash(argc > optind ? argv[optind] : 0, filterflag, verbose_only); + exit(0); + } + + versiontext=strtok(readbuffer,":"); + statustext=strtok(NULL,":"); + if (!statustext || strncmp(" on\n",statustext, 4)) { + DEBUG("splash: Boot splash is off.\n"); + return 0; + } + + memset(readbuffer,0,BUFSIZE); + + splashdsc=open(SPLASHDSC,O_RDONLY); + if (splashdsc<0) { + DEBUG("splash: File %s not available.\n", SPLASHDSC); + return -ENOENT; + } + + if (read(splashdsc, readbuffer, BUFSIZE)<0) { + DEBUG("splash: Read error in file %s.\n",SPLASHDSC); + return -EBUSY; + } + + DEBUG("splash: Looking for match with \"%s\"\n",basename(argv[1])); + + tokenize=readbuffer; + do { + match=strtok(tokenize,":"); + tokenize=NULL; + + command=strtok(NULL,"\n"); + DEBUG("splash: Match=\"%s\"\n",match); + if (match && (cmp=strstr(basename(argv[1]),match)) + && !strncmp(match,cmp,strlen(match)) ) { + + DEBUG("splash: Match found: \"%s\".\n",match); + spawncommand(command); + return 0; + } + + } while (match && command); + + return 0; +} |