aboutsummaryrefslogtreecommitdiffstats
path: root/splash/splash.c
diff options
context:
space:
mode:
Diffstat (limited to 'splash/splash.c')
-rw-r--r--splash/splash.c656
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;
+}