/* ioctl routine */ int vinumioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td) { unsigned int objno; int error = 0; struct sd *sd; struct plex *plex; struct volume *vol; unsigned int index; /* for transferring config info */ unsigned int sdno; /* for transferring config info */ int fe; /* free list element number */ struct _ioctl_reply *ioctl_reply = (struct _ioctl_reply *) data; /* struct to return */ /* First, decide what we're looking at */ switch (DEVTYPE(dev)) { case VINUM_SUPERDEV_TYPE: /* ordinary super device */ ioctl_reply = (struct _ioctl_reply *) data; /* save the address to reply to */ switch (cmd) { #ifdef VINUMDEBUG case VINUM_DEBUG: if (((struct debuginfo *) data)->changeit) /* change debug settings */ debug = (((struct debuginfo *) data)->param); else { if (debug & DEBUG_REMOTEGDB) boothowto |= RB_GDB; /* serial debug line */ else boothowto &= ~RB_GDB; /* local ddb */ Debugger("vinum debug"); } ioctl_reply = (struct _ioctl_reply *) data; /* reinstate the address to reply to */ ioctl_reply->error = 0; return 0; #endif case VINUM_CREATE: /* create a vinum object */ error = lock_config(); /* get the config for us alone */ if (error) /* can't do it, */ return error; /* give up */ error = setjmp(command_fail); /* come back here on error */ if (error == 0) /* first time, */ ioctl_reply->error = parse_user_config((char *) data, /* update the config */ &keyword_set); else if (ioctl_reply->error == 0) { /* longjmp, but no error status */ ioctl_reply->error = EINVAL; /* note that something's up */ ioctl_reply->msg[0] = '\0'; /* no message? */ } unlock_config(); return 0; /* must be 0 to return the real error info */ case VINUM_GETCONFIG: /* get the configuration information */ bcopy(&vinum_conf, data, sizeof(vinum_conf)); return 0; /* start configuring the subsystem */ case VINUM_STARTCONFIG: return start_config(*(int *) data); /* just lock it. Parameter is 'force' */ /* * Move the individual parts of the config to user space. * * Specify the index of the object in the first word of data, * and return the object there */ case VINUM_DRIVECONFIG: index = *(int *) data; /* get the index */ if (index >= (unsigned) vinum_conf.drives_allocated) /* can't do it */ return ENXIO; /* bang */ bcopy(&DRIVE[index], data, sizeof(struct _drive)); /* copy the config item out */ return 0; case VINUM_SDCONFIG: index = *(int *) data; /* get the index */ if (index >= (unsigned) vinum_conf.subdisks_allocated) /* can't do it */ return ENXIO; /* bang */ bcopy(&SD[index], data, sizeof(struct _sd)); /* copy the config item out */ return 0; case VINUM_PLEXCONFIG: index = *(int *) data; /* get the index */ if (index >= (unsigned) vinum_conf.plexes_allocated) /* can't do it */ return ENXIO; /* bang */ bcopy(&PLEX[index], data, sizeof(struct _plex)); /* copy the config item out */ return 0; case VINUM_VOLCONFIG: index = *(int *) data; /* get the index */ if (index >= (unsigned) vinum_conf.volumes_allocated) /* can't do it */ return ENXIO; /* bang */ bcopy(&VOL[index], data, sizeof(struct _volume)); /* copy the config item out */ return 0; case VINUM_PLEXSDCONFIG: index = *(int *) data; /* get the plex index */ sdno = ((int *) data)[1]; /* and the sd index */ if ((index >= (unsigned) vinum_conf.plexes_allocated) /* plex doesn't exist */ ||(sdno >= PLEX[index].subdisks)) /* or it doesn't have this many subdisks */ return ENXIO; /* bang */ bcopy(&SD[PLEX[index].sdnos[sdno]], /* copy the config item out */ data, sizeof(struct _sd)); return 0; /* * We get called in two places: one from the * userland config routines, which call us * to complete the config and save it. This * call supplies the value 0 as a parameter. * * The other place is from the user "saveconfig" * routine, which can only work if we're *not* * configuring. In this case, supply parameter 1. */ case VINUM_SAVECONFIG: if (VFLAGS & VF_CONFIGURING) { /* must be us, the others are asleep */ if (*(int *) data == 0) /* finish config */ finish_config(1); /* finish the configuration and update it */ else return EBUSY; /* can't do it now */ } save_config(); /* save configuration to disk */ return 0; case VINUM_RELEASECONFIG: /* release the config */ if (VFLAGS & VF_CONFIGURING) { /* must be us, the others are asleep */ finish_config(0); /* finish the configuration, don't change it */ save_config(); /* save configuration to disk */ } else error = EINVAL; /* release what config? */ return error; case VINUM_INIT: ioctl_reply = (struct _ioctl_reply *) data; /* reinstate the address to reply to */ ioctl_reply->error = 0; return 0; case VINUM_RESETCONFIG: if (vinum_inactive(0)) { /* if the volumes are not active */ /* * Note the open count. We may be called from v, so we'll be open. * Keep the count so we don't underflow */ free_vinum(1); /* clean up everything */ log(LOG_NOTICE, "vinum: CONFIGURATION OBLITERATED\n"); ioctl_reply = (struct _ioctl_reply *) data; /* reinstate the address to reply to */ ioctl_reply->error = 0; return 0; } return EBUSY; case VINUM_SETSTATE: setstate((struct vinum_ioctl_msg *) data); /* set an object state */ return 0; /* * Set state by force, without changing * anything else. */ case VINUM_SETSTATE_FORCE: setstate_by_force((struct vinum_ioctl_msg *) data); /* set an object state */ return 0; #ifdef VINUMDEBUG case VINUM_MEMINFO: vinum_meminfo(data); return 0; case VINUM_MALLOCINFO: return vinum_mallocinfo(data); case VINUM_RQINFO: return vinum_rqinfo(data); #endif case VINUM_LABEL: /* label a volume */ ioctl_reply->error = write_volume_label(*(int *) data); /* index of the volume to label */ ioctl_reply->msg[0] = '\0'; /* no message */ return 0; case VINUM_REMOVE: remove((struct vinum_ioctl_msg *) data); /* remove an object */ return 0; case VINUM_GETFREELIST: /* get a drive free list element */ index = *(int *) data; /* get the drive index */ fe = ((int *) data)[1]; /* and the free list element */ if ((index >= (unsigned) vinum_conf.drives_allocated) /* plex doesn't exist */ ||(DRIVE[index].state == drive_unallocated)) return ENODEV; if (fe >= DRIVE[index].freelist_entries) /* no such entry */ return ENOENT; bcopy(&DRIVE[index].freelist[fe], data, sizeof(struct drive_freelist)); return 0; case VINUM_RESETSTATS: resetstats((struct vinum_ioctl_msg *) data); /* reset object stats */ return 0; /* attach an object to a superordinate object */ case VINUM_ATTACH: attachobject((struct vinum_ioctl_msg *) data); return 0; /* detach an object from a superordinate object */ case VINUM_DETACH: detachobject((struct vinum_ioctl_msg *) data); return 0; /* rename an object */ case VINUM_RENAME: renameobject((struct vinum_rename_msg *) data); return 0; /* replace an object */ case VINUM_REPLACE: replaceobject((struct vinum_ioctl_msg *) data); return 0; case VINUM_DAEMON: vinum_daemon(); /* perform the daemon */ return 0; case VINUM_FINDDAEMON: /* check for presence of daemon */ return vinum_finddaemon(); return 0; case VINUM_SETDAEMON: /* set daemon flags */ return vinum_setdaemonopts(*(int *) data); case VINUM_GETDAEMON: /* get daemon flags */ *(int *) data = daemon_options; return 0; case VINUM_PARITYOP: /* check/rebuild RAID-4/5 parity */ parityops((struct vinum_ioctl_msg *) data); return 0; /* move an object */ case VINUM_MOVE: moveobject((struct vinum_ioctl_msg *) data); return 0; default: /* FALLTHROUGH */ break; } case VINUM_DRIVE_TYPE: default: log(LOG_WARNING, "vinumioctl: invalid ioctl from process %d (%s): %lx\n", curthread->td_proc->p_pid, curthread->td_proc->p_comm, cmd); return EINVAL; case VINUM_SD_TYPE: case VINUM_RAWSD_TYPE: objno = Sdno(dev); sd = &SD[objno]; switch (cmd) { case DIOCGDINFO: /* get disk label */ get_volume_label(sd->name, 1, sd->sectors, (struct disklabel *) data); break; /* * We don't have this stuff on hardware, * so just pretend to do it so that * utilities don't get upset. */ case DIOCWDINFO: /* write partition info */ case DIOCSDINFO: /* set partition info */ return 0; /* not a titty */ default: return ENOTTY; /* not my kind of ioctl */ } return 0; /* pretend we did it */ case VINUM_RAWPLEX_TYPE: case VINUM_PLEX_TYPE: objno = Plexno(dev); plex = &PLEX[objno]; switch (cmd) { case DIOCGDINFO: /* get disk label */ get_volume_label(plex->name, 1, plex->length, (struct disklabel *) data); break; /* * We don't have this stuff on hardware, * so just pretend to do it so that * utilities don't get upset. */ case DIOCWDINFO: /* write partition info */ case DIOCSDINFO: /* set partition info */ return 0; /* not a titty */ default: return ENOTTY; /* not my kind of ioctl */ } return 0; /* pretend we did it */ case VINUM_VOLUME_TYPE: objno = Volno(dev); if ((unsigned) objno >= (unsigned) vinum_conf.volumes_allocated) /* not a valid volume */ return ENXIO; vol = &VOL[objno]; if (vol->state != volume_up) /* not up, */ return EIO; /* I/O error */ switch (cmd) { case DIOCGMEDIASIZE: *(off_t *)data = vol->size << DEV_BSHIFT; break; case DIOCGSECTORSIZE: *(u_int *)data = DEV_BSIZE; break; /* * We don't have this stuff on hardware, * so just pretend to do it so that * utilities don't get upset. */ case DIOCWDINFO: /* write partition info */ case DIOCSDINFO: /* set partition info */ return 0; /* not a titty */ case DIOCWLABEL: /* set or reset label writeable */ if ((flag & FWRITE) == 0) /* not writeable? */ return EACCES; /* no, die */ if (*(int *) data != 0) /* set it? */ vol->flags |= VF_WLABEL; /* yes */ else vol->flags &= ~VF_WLABEL; /* no, reset */ break; default: return ENOTTY; /* not my kind of ioctl */ } break; } return 0; /* XXX */ }
int main(int argc, char* argv[]) { printf("START! pid = %d\n", getpid()); if (!system("./restart.rb")) exit(1); if (signal(SIGUSR1, RestartHandler) == SIG_ERR) { fprintf(stderr, "An error occurred while setting a signal handler.\n"); exit(1); } bool fullscreen = true; s_config = new AppConfig(fullscreen, false, 1280, 800); SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK); SDL_Window* displayWindow; SDL_Renderer* displayRenderer; uint32_t flags = SDL_WINDOW_OPENGL | (s_config->fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0); int err = SDL_CreateWindowAndRenderer(s_config->width, s_config->height, flags, &displayWindow, &displayRenderer); if (err == -1 || !displayWindow || !displayRenderer) { fprintf(stderr, "SDL_CreateWindowAndRenderer failed!\n"); } SDL_RendererInfo displayRendererInfo; SDL_GetRendererInfo(displayRenderer, &displayRendererInfo); /* TODO: Check that we have OpenGL */ if ((displayRendererInfo.flags & SDL_RENDERER_ACCELERATED) == 0 || (displayRendererInfo.flags & SDL_RENDERER_TARGETTEXTURE) == 0) { /* TODO: Handle this. We have no render surface and not accelerated. */ fprintf(stderr, "NO RENDERER wtf!\n"); } atexit(SDL_Quit); JOYSTICK_Init(); AppConfig& config = *s_config; config.title = "riftty"; //SDL_WM_SetCaption(config.title.c_str(), config.title.c_str()); //SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); /* // clear glClearColor(s_clearColor.x, s_clearColor.y, s_clearColor.z, s_clearColor.w); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); SDL_GL_SwapWindow(displayWindow); */ RiftSetup(); RenderInit(); win_init(); init_config(); struct passwd *pw = getpwuid(getuid()); const char *homedir = pw->pw_dir; char config_filename[512]; strncpy(config_filename, homedir, 512); strncat(config_filename, "/.riftty", 512); load_config(config_filename); cs_init(); // TODO: code pages do not want // TODO: determine this based on window-size & font-size or vice versa. cfg.rows = 25; cfg.cols = 80; // TODO: load config from /etc/riffty or ~/.rifttyrc finish_config(); win_reconfig(); // TODO: get SHELL from env cs_reconfig(); // TODO: do not want term_init(); term_reset(); term_resize(cfg.rows, cfg.cols); // TODO: int font_width = 10; int font_height = 10; unsigned short term_width = font_width * cfg.cols; unsigned short term_height = font_height * cfg.rows; char login[128]; strncpy(login, getlogin(), 128); const char* login_argv[] = {"login", "-pfl", login, NULL}; unsigned short rows = cfg.rows; unsigned short cols = cfg.cols; winsize ws = {rows, cols, term_width, term_height}; child_create(login_argv, &ws); bool done = false; while (!done) { JOYSTICK_ClearFlags(); SDL_Event event; while (SDL_PollEvent(&event)) { switch (event.type) { case SDL_QUIT: done = true; break; case SDL_MOUSEMOTION: if (event.motion.state & SDL_BUTTON(1)) { // move touch } break; case SDL_MOUSEBUTTONDOWN: if (event.button.button == SDL_BUTTON_LEFT) { // start touch } break; case SDL_MOUSEBUTTONUP: if (event.button.button == SDL_BUTTON_LEFT) { // end touch } break; case SDL_JOYAXISMOTION: JOYSTICK_UpdateMotion(&event.jaxis); break; case SDL_JOYBUTTONDOWN: case SDL_JOYBUTTONUP: JOYSTICK_UpdateButton(&event.jbutton); break; case SDL_KEYDOWN: case SDL_KEYUP: if (ProcessKeyEvent(&event.key)) { done = true; } break; } } if (!done) { if (s_needsRestart) Restart(); unsigned int now = SDL_GetTicks(); // milliseconds float dt = (now - s_ticks) / 1000.0f; // convert to seconds. s_ticks = now; //printf("fps = %.0f\n", 1.0f/dt); Process(dt); Render(dt); } } child_kill(true); win_shutdown(); RiftShutdown(); JOYSTICK_Shutdown(); return 0; }
/* ioctl routine */ int vinumioctl(struct dev_ioctl_args *ap) { cdev_t dev = ap->a_head.a_dev; u_long cmd = ap->a_cmd; caddr_t data = ap->a_data; int error; unsigned int index; /* for transferring config info */ unsigned int sdno; /* for transferring config info */ unsigned int objno; struct volume *vol; struct partinfo *dpart; int fe; /* free list element number */ struct _ioctl_reply *ioctl_reply; /* struct to return */ error = 0; /* First, decide what we're looking at */ switch (DEVTYPE(dev)) { case VINUM_SUPERDEV_TYPE: /* ordinary super device */ ioctl_reply = (struct _ioctl_reply *) data; /* save the address to reply to */ switch (cmd) { #ifdef VINUMDEBUG case VINUM_DEBUG: if (((struct debuginfo *) data)->changeit) /* change debug settings */ debug = (((struct debuginfo *) data)->param); else { if (debug & DEBUG_REMOTEGDB) boothowto |= RB_GDB; /* serial debug line */ else boothowto &= ~RB_GDB; /* local ddb */ Debugger("vinum debug"); } ioctl_reply = (struct _ioctl_reply *) data; /* reinstate the address to reply to */ ioctl_reply->error = 0; break; #endif case VINUM_CREATE: /* create a vinum object */ error = lock_config(); /* get the config for us alone */ if (error) /* can't do it, */ break; error = setjmp(command_fail); /* come back here on error */ if (error == 0) /* first time, */ ioctl_reply->error = parse_user_config((char *) data, /* update the config */ &keyword_set); else if (ioctl_reply->error == 0) { /* longjmp, but no error status */ error = 0; ioctl_reply->error = EINVAL; /* note that something's up */ ioctl_reply->msg[0] = '\0'; /* no message? */ } unlock_config(); break; case VINUM_GETCONFIG: /* get the configuration information */ bcopy(&vinum_conf, data, sizeof(vinum_conf)); break; /* start configuring the subsystem */ case VINUM_STARTCONFIG: error = start_config(*(int *) data); /* just lock it. Parameter is 'force' */ break; case VINUM_DRIVECONFIG: /* * Move the individual parts of the config to user space. * * Specify the index of the object in the first word of data, * and return the object there */ index = *(int *) data; if (index >= (unsigned)vinum_conf.drives_allocated) { error = ENXIO; } else { bcopy(&DRIVE[index], data, sizeof(struct drive)); } break; case VINUM_SDCONFIG: index = *(int *) data; if (index >= (unsigned) vinum_conf.subdisks_allocated) { error = ENXIO; } else { bcopy(&SD[index], data, sizeof(struct sd)); } break; case VINUM_PLEXCONFIG: index = *(int *) data; if (index >= (unsigned) vinum_conf.plexes_allocated) { error = ENXIO; } else { bcopy(&PLEX[index], data, sizeof(struct plex)); } break; case VINUM_VOLCONFIG: index = *(int *) data; if (index >= (unsigned) vinum_conf.volumes_allocated) { error = ENXIO; } else { bcopy(&VOL[index], data, sizeof(struct volume)); } break; case VINUM_PLEXSDCONFIG: index = ((int *)data)[0]; /* get the plex index */ sdno = ((int *)data)[1]; /* and the sd index */ if ((index >= (unsigned) vinum_conf.plexes_allocated) ||(sdno >= PLEX[index].subdisks)) { error = ENXIO; } else { bcopy(&SD[PLEX[index].sdnos[sdno]], data, sizeof(struct sd)); } break; case VINUM_SAVECONFIG: /* * We get called in two places: one from the * userland config routines, which call us * to complete the config and save it. This * call supplies the value 0 as a parameter. * * The other place is from the user "saveconfig" * routine, which can only work if we're *not* * configuring. In this case, supply parameter 1. */ if (VFLAGS & VF_CONFIGURING) { /* must be us, the others are asleep */ if (*(int *) data == 0) /* finish config */ finish_config(1); /* finish the configuration and update it */ else error = EBUSY; } if (error == 0) save_config(); /* save configuration to disk */ break; case VINUM_RELEASECONFIG: /* release the config */ if (VFLAGS & VF_CONFIGURING) { /* must be us, the others are asleep */ finish_config(0); /* finish the configuration, don't change it */ save_config(); /* save configuration to disk */ } else { error = EINVAL; /* release what config? */ } break; case VINUM_INIT: ioctl_reply = (struct _ioctl_reply *) data; /* reinstate the address to reply to */ ioctl_reply->error = 0; break; case VINUM_RESETCONFIG: if (vinum_inactive(0)) { /* if the volumes are not active */ /* * Note the open count. We may be called from v, so we'll be open. * Keep the count so we don't underflow */ free_vinum(1); /* clean up everything */ log(LOG_NOTICE, "vinum: CONFIGURATION OBLITERATED\n"); ioctl_reply = (struct _ioctl_reply *) data; /* reinstate the address to reply to */ ioctl_reply->error = 0; } else { error = EBUSY; } case VINUM_SETSTATE: setstate((struct vinum_ioctl_msg *) data); /* set an object state */ break; /* * Set state by force, without changing * anything else. */ case VINUM_SETSTATE_FORCE: setstate_by_force((struct vinum_ioctl_msg *) data); /* set an object state */ break; #ifdef VINUMDEBUG case VINUM_MEMINFO: vinum_meminfo(data); break; case VINUM_MALLOCINFO: error = vinum_mallocinfo(data); break; case VINUM_RQINFO: error = vinum_rqinfo(data); break; #endif case VINUM_REMOVE: remove((struct vinum_ioctl_msg *) data); /* remove an object */ break; case VINUM_GETFREELIST: /* get a drive free list element */ index = *(int *) data; /* get the drive index */ fe = ((int *) data)[1]; /* and the free list element */ if ((index >= (unsigned) vinum_conf.drives_allocated) /* plex doesn't exist */ ||(DRIVE[index].state == drive_unallocated)) { error = ENODEV; } else if (fe >= DRIVE[index].freelist_entries) { error = ENOENT; } else { bcopy(&DRIVE[index].freelist[fe], data, sizeof(struct drive_freelist)); } break; case VINUM_RESETSTATS: resetstats((struct vinum_ioctl_msg *) data); /* reset object stats */ break; /* attach an object to a superordinate object */ case VINUM_ATTACH: attachobject((struct vinum_ioctl_msg *) data); break; /* detach an object from a superordinate object */ case VINUM_DETACH: detachobject((struct vinum_ioctl_msg *) data); break; /* rename an object */ case VINUM_RENAME: renameobject((struct vinum_rename_msg *) data); break; /* replace an object */ case VINUM_REPLACE: replaceobject((struct vinum_ioctl_msg *) data); break; case VINUM_DAEMON: vinum_daemon(); /* perform the daemon */ break; case VINUM_FINDDAEMON: /* check for presence of daemon */ error = vinum_finddaemon(); break; case VINUM_SETDAEMON: /* set daemon flags */ error = vinum_setdaemonopts(*(int *) data); break; case VINUM_GETDAEMON: /* get daemon flags */ *(int *) data = daemon_options; break; case VINUM_PARITYOP: /* check/rebuild RAID-4/5 parity */ parityops((struct vinum_ioctl_msg *) data); break; /* move an object */ case VINUM_MOVE: moveobject((struct vinum_ioctl_msg *) data); break; default: error = EINVAL; break; } break; case VINUM_LABEL: case VINUM_DRIVE_TYPE: case VINUM_SD_TYPE: case VINUM_RAWSD_TYPE: case VINUM_RAWPLEX_TYPE: case VINUM_PLEX_TYPE: error = EINVAL; break; case VINUM_VOLUME_TYPE: objno = Volno(dev); if ((unsigned)objno >= (unsigned)vinum_conf.volumes_allocated) { error = ENXIO; break; } vol = &VOL[objno]; if (vol->state != volume_up) { error = EIO; break; } switch(cmd) { case DIOCGPART: dpart = (void *)data; bzero(dpart, sizeof(*dpart)); dpart->media_offset = 0; dpart->media_size = (u_int64_t)vol->size * DEV_BSIZE; dpart->media_blocks = vol->size; dpart->media_blksize = DEV_BSIZE; dpart->fstype = FS_BSDFFS; break; default: error = EINVAL; } break; default: error = EINVAL; break; } if (error) { log(LOG_WARNING, "vinumioctl: invalid ioctl from process %d (%s): %lx\n", curproc->p_pid, curproc->p_comm, cmd); } return error; }