PERFORCE change 213989 for review
Brooks Davis
brooks at FreeBSD.org
Fri Jul 6 18:24:06 UTC 2012
http://p4web.freebsd.org/@@213989?ac=10
Change 213989 by brooks at brooks_ecr_current on 2012/07/06 18:23:32
Checkpoint with text based file browser support and basic rendering
including file names and placeholders for icons.
Affected files ...
.. //depot/projects/ctsrd/beribsd/src/ctsrd/browser/browser.c#2 edit
Differences ...
==== //depot/projects/ctsrd/beribsd/src/ctsrd/browser/browser.c#2 (text+ko) ====
@@ -31,13 +31,17 @@
#include <sys/types.h>
#include <sys/param.h>
+#include <sys/stat.h>
#include <sys/wait.h>
+#include <ctype.h>
#include <de4tc.h>
+#include <dirent.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <libutil.h>
+#include <magic.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -47,11 +51,42 @@
#define BASEIMG "/usr/share/images/browser.png"
-#define black fb_colour(0, 0, 0)
-#define white fb_colour(0xff, 0xff, 0xff);
-#define red fb_colour(0xff, 0, 0)
-#define green fb_colour(0, 0xff, 0)
-#define blue fb_colour(0, 0, 0xff)
+#define vwhite(v) fb_colour((v), (v), (v))
+#define vred(v) fb_colour((v), 0, 0)
+#define vgreen(v) fb_colour(0, (v), 0)
+#define vblue(v) fb_colour(0, 0, (v))
+#define black vwhite(0)
+#define white vwhite(0xFF)
+#define red vred(0xFF)
+#define green vgreen(0xFF)
+#define blue vblue(0xFF)
+
+/*
+ * Each file is displayed in a 266x40 box:
+ * +--------------------------------------------------------------------------+
+ * | 4 pixel border |
+ * |4 +------+ 4+----------------------------------------------------------+ |
+ * |p |32x32 | p| Text in 16x32 characters | |
+ * |x |icon | x| | |
+ * | +------+ +----------------------------------------------------------+ |
+ * | 4 pixel border |
+ * +--------------------------------------------------------------------------+
+ * |----------------------------------(800/3 = 266) pixels--------------------|
+ */
+#define FROW 41
+#define NCOL 3
+#define NROW 10
+#define NSLOTS (NCOL * NROW)
+#define CWIDTH 266
+#define RHEIGHT 40
+#define ICON_WH 32
+#define BORDER 4
+#define CHAR_HEIGHT 32
+#define CHAR_WIDTH 16
+#define TEXT_OFFSET (BORDER + ICON_WH + BORDER)
+#define _TEXTSPACE (CWIDTH - (TEXT_OFFSET + BORDER))
+#define TEXTSPACE (_TEXTSPACE - _TEXTSPACE % CHAR_WIDTH)
+
/* Beginning and ending colums of each sandbox type's name */
#define SB_IMG_SPACING 20
@@ -66,6 +101,9 @@
#define SB_MINROW (fb_height - 39)
#define SB_MAXROW (fb_height - 1)
+/* Start offsets for browser columns */
+const int colstart[] = {0, 267, 534};
+
enum _sbtype {
SB_NONE = 1,
SB_CAPSICUM,
@@ -83,20 +121,55 @@
{ 0, 0, 0 }
};
-static u_int32_t *image;
+static u_int32_t *bgimage;
+static magic_t magic;
static void
usage(void)
{
- printf("usage: browser\n");
+ printf("usage: browser <dir> <tty>\n");
+ printf(" browser -T <dir>\n");
exit(1);
}
static void
+init_tty(char *tty_name) {
+ int tty;
+ char *devpath;
+
+ if (tty_name[0] != '/')
+ asprintf(&devpath, "/dev/%s", tty_name);
+ else
+ devpath = tty_name;
+ if ((tty = open(devpath, O_RDWR)) < 0) {
+ syslog(LOG_ALERT, "open failed with %s", strerror(errno));
+ err(1, "open(%s)", devpath);
+ }
+ if (login_tty(tty) < 0) {
+ syslog(LOG_ALERT, "login_tty failed: %s", strerror(errno));
+ err(1, "login_tty()");
+ }
+ if (devpath != tty_name)
+ free(devpath);
+}
+
+static void
+init_magic(void) {
+ magic = magic_open(MAGIC_MIME_TYPE);
+ if (magic == NULL)
+ errx(1, "magic_open()");
+ if (magic_load(magic, NULL) == -1) {
+ warnx("magic_load() %s", magic_error(magic));
+ magic_close(magic);
+ exit(1);
+ }
+}
+
+static void
update_sandbox(enum _sbtype type)
{
- int bcol, ecol, i, j, pixel;
+ int bcol, ecol, i, j, pixel, value;
sbtype = type;
@@ -110,65 +183,282 @@
for (j = SB_MINROW; j < SB_MAXROW; j++) {
for (i = SB_MINCOL; i <= SB_MAXCOL; i++) {
pixel = (j * fb_width) + i;
- /* XXX: messes up anti-aliasing */
- if (image[pixel] != black)
- image[pixel] = (i >= bcol && i <= ecol) ?
- blue : white;
+ if (bgimage[pixel] != black) {
+ /* XXX: Assuming we're either blue or white */
+ value = (bgimage[pixel] >> 8) & 0xFF;
+ if (value == 0) {
+ printf("unexpected zero value, pixel %08x\n",
+ bgimage[pixel]);
+ value = 0xff;
+ }
+ bgimage[pixel] = (i >= bcol && i <= ecol) ?
+ vblue(value) : vwhite(value);
+ }
+ }
+ }
+ fb_post(bgimage);
+}
+
+static const char *
+get_desc(int dfd, struct dirent *entry)
+{
+ int fd, type;
+ const char *desc;
+ struct stat sbuf;
+
+ if (entry->d_type == DT_LNK) {
+ if (fstatat(dfd, entry->d_name, &sbuf, 0) == -1)
+ type = DT_UNKNOWN;
+ else
+ type = IFTODT(sbuf.st_mode);
+ } else
+ type = entry->d_type;
+
+ switch (type) {
+ case DT_UNKNOWN:
+ desc = "unknown";
+ break;
+ case DT_REG:
+ if ((fd = openat(dfd, entry->d_name, O_RDONLY)) == -1)
+ desc = "unknown";
+ else {
+ desc = magic_descriptor(magic, fd);
+ close(fd);
}
+ break;
+ case DT_FIFO:
+ desc = "special/fifo";
+ break;
+ case DT_CHR:
+ desc = "special/character";
+ break;
+ case DT_DIR:
+ desc = "directory";
+ break;
+ case DT_BLK:
+ desc = "special/block";
+ break;
+ case DT_SOCK:
+ desc = "special/socket";
+ break;
+ case DT_WHT:
+ desc = "special/whiteout";
+ break;
+ default:
+ err(1, "Unhandled type %d", type);
}
- fb_post(image);
+
+ return (desc);
}
-static void
-event_loop(void)
+static int
+browsedir(int dfd)
{
- for(;;) {
- sleep(1);
+ int f, i, j, s, nlines;
+ long curloc, nextloc;
+ DIR *dirp;
+ struct dirent *entry, *entry2;
+ u_int32_t iconbuf[ICON_WH*ICON_WH], textbuf[TEXTSPACE*CHAR_HEIGHT];
+ char line[256];
+
+ if ((dirp = fdopendir(dfd)) == NULL)
+ err(1, "fdopendir()");
+
+ for (i = 0; i < 32*32; i++)
+ iconbuf[i] = blue;
+
+ fb_fill_region(black, colstart[0], FROW,
+ colstart[NCOL-1] - colstart[0], NROW * RHEIGHT);
+
+ nlines = NSLOTS - 1;
+ curloc = telldir(dirp);
+ nextloc = 0;
+ i = 0;
+start:
+ seekdir(dirp, curloc);
+ /* telldir() return values are only good once so make a new copy! */
+ curloc = telldir(dirp);
+ s = 0;
+ if (i > 0) {
+ printf("p %20s\n", "previous page");
+ memset(textbuf, 0, sizeof(textbuf));
+ fb_render_text("previous page", 2, white, black, textbuf,
+ TEXTSPACE, CHAR_HEIGHT);
+ fb_post_region(textbuf, colstart[(s/NROW)] + TEXT_OFFSET,
+ FROW + (RHEIGHT * (s % NROW)) + BORDER, TEXTSPACE,
+ CHAR_HEIGHT);
+ fb_post_region(iconbuf, colstart[(s/NROW)] + BORDER,
+ FROW + (RHEIGHT * (s % NROW)) + BORDER, ICON_WH, ICON_WH);
+ s = 1;
+ }
+ entry = NULL; /* XXX: gcc warning */
+ while(s < NSLOTS - 1 && (entry = readdir(dirp)) != NULL) {
+ printf("%2d %20s %s\n", s, entry->d_name, get_desc(dfd, entry));
+ memset(textbuf, 0, sizeof(textbuf));
+ fb_render_text(entry->d_name, 2, white, black, textbuf,
+ TEXTSPACE, CHAR_HEIGHT);
+ fb_post_region(textbuf, colstart[(s/NROW)]+TEXT_OFFSET,
+ FROW + (RHEIGHT * (s % NROW)) + BORDER, TEXTSPACE, CHAR_HEIGHT);
+ fb_post_region(iconbuf, colstart[(s/NROW)] + BORDER,
+ FROW + (RHEIGHT * (s % NROW)) + BORDER, ICON_WH, ICON_WH);
+ s++;
+ }
+
+ nextloc = telldir(dirp);
+ if (s == NSLOTS - 1 && entry != NULL) {
+ /*
+ * If there are at least two more files then we don't want to
+ * display a "next" button and instead want either nothing or
+ * the final entry.
+ */
+ entry = readdir(dirp);
+ if (entry == NULL)
+ nextloc = 0;
+ else {
+ entry2 = readdir(dirp);
+ if (entry2 == NULL) {
+ printf("%2d %20s %s\n", s,
+ entry->d_name,
+ get_desc(dfd, entry));
+ memset(textbuf, 0, sizeof(textbuf));
+ fb_render_text(entry->d_name, 2, white, black,
+ textbuf, TEXTSPACE, CHAR_HEIGHT);
+ fb_post_region(textbuf,
+ colstart[(s/NROW)]+TEXT_OFFSET,
+ FROW + (RHEIGHT * (s % NROW)) + BORDER,
+ TEXTSPACE, CHAR_HEIGHT);
+ fb_post_region(iconbuf,
+ colstart[(s/NROW)] + BORDER,
+ FROW + (RHEIGHT * (s % NROW)) + BORDER,
+ ICON_WH, ICON_WH);
+ s++;
+ } else {
+ printf("n %20s\n", "next page");
+ memset(textbuf, 0, sizeof(textbuf));
+ fb_render_text("next page", 2, white, black,
+ textbuf, TEXTSPACE, CHAR_HEIGHT);
+ fb_post_region(textbuf,
+ colstart[(s/NROW)]+TEXT_OFFSET,
+ FROW + (RHEIGHT * (s % NROW)) + BORDER,
+ TEXTSPACE, CHAR_HEIGHT);
+ fb_post_region(iconbuf,
+ colstart[(s/NROW)] + BORDER,
+ FROW + (RHEIGHT * (s % NROW)) + BORDER,
+ ICON_WH, ICON_WH);
+ }
+ }
+ }
+
+prompt:
+ printf("select a file or directory by number :\n");
+ if (fgets(line, sizeof(line), stdin) == NULL) {
+ if (feof(stdin))
+ return (-1);
+ else
+ errx(1, "fgets(): %s", strerror(ferror(stdin)));
+ }
+ printf("line '%s'\n", line);
+ f = 0; /* XXX: gcc warning*/
+ switch (line[0]) {
+ case '\n':
+ case 'n':
+ /* This leaks an internal struct associted with curloc/ */
+ if (nextloc != 0) {
+ i += s;
+ curloc = nextloc;
+ }
+ goto start;
+ case 'p':
+ i -= s;
+ // XXX previous page
+ break;
+ case 'q':
+ return(-1);
+ default:
+ if (!isnumber(line[0])) {
+ printf("invalid file %s\n", line);
+ goto prompt;
+ }
+ f = atoi(line);
+ if (f < 0 || f >= nlines) {
+ printf("invalid file %s\n", line);
+ goto prompt;
+ }
+ }
+
+ /* Take action on the specified file */
+ seekdir(dirp, curloc);
+ curloc = telldir(dirp);
+ j = 0;
+ while((entry = readdir(dirp)) != NULL) {
+ printf("%s\n", entry->d_name);
+ if (j++ != f)
+ continue;
+ if (entry->d_type == DT_DIR) {
+ if ((dfd = openat(dfd, entry->d_name,
+ O_RDONLY|O_DIRECTORY)) == -1)
+ err(1, "open(%s)", entry->d_name);
+ if (closedir(dirp) == -1)
+ err(1, "closedir()");
+ return (dfd);
+ } else {
+ printf ("opening non-directory not supported\n");
+ goto start;
+ }
}
+
+ if (closedir(dirp) == -1)
+ err(1, "closedir()");
+
+ return (-1);
}
int
main(int argc, char *argv[])
{
- int tty;
- char *devpath;
+ int ch, dfd;
+ int ttyflag = 1;
- syslog(LOG_ALERT, "starting up");
- if (argc != 2)
- usage();
-
- if (argv[1][0] != '/')
- asprintf(&devpath, "/dev/%s", argv[1]);
- else
- devpath = argv[1];
- if ((tty = open(devpath, O_RDWR)) < 0) {
- syslog(LOG_ALERT, "open failed with %s", strerror(errno));
- err(1, "open(%s)", devpath);
+ while ((ch = getopt(argc, argv, "T")) != -1) {
+ switch (ch) {
+ case 'T':
+ ttyflag = 0;
+ break;
+ default:
+ usage();
+ }
}
+ argc -= optind;
+ argv += optind;
- if (login_tty(tty) < 0) {
- syslog(LOG_ALERT, "login_tty failed: %s", strerror(errno));
- err(1, "login_tty()");
- }
- syslog(LOG_ALERT, "tty set up");
+ if (argc <= 0 && argc > 2)
+ usage();
+ if (argc == 2)
+ init_tty(argv[1]);
+ init_magic();
fb_init();
+ fb_load_syscons_font(NULL, "/usr/share/syscons/fonts/iso-8x16.fnt");
- image = malloc(sizeof(u_int32_t) * fb_height * fb_width);
- if (image == NULL)
+ bgimage = malloc(sizeof(u_int32_t) * fb_height * fb_width);
+ if (bgimage == NULL)
err(1, "malloc");
- read_png_file(BASEIMG, image, fb_width, fb_height);
+ read_png_file(BASEIMG, bgimage, fb_width, fb_height);
syslog(LOG_ALERT, "tty set up");
- fb_post(image);
+ fb_post(bgimage);
//fb_fade2on();
fb_fade2text(127);
fb_text_cursor(255, 255);
update_sandbox(SB_NONE);
- event_loop();
+ if ((dfd = open(argv[0], O_RDONLY|O_DIRECTORY)) == -1)
+ err(1, "open(%s)", argv[1]);
+
+ while (dfd != -1)
+ dfd = browsedir(dfd);
return (0);
}
More information about the p4-projects
mailing list