void pluto_init_log(void) { set_alloc_exit_log_func(exit_log); if (log_to_stderr) setbuf(stderr, NULL); if (pluto_log_file != NULL) { pluto_log_fp = fopen(pluto_log_file, log_append ? "a" : "w"); if (pluto_log_fp == NULL) { fprintf(stderr, "Cannot open logfile '%s': %s\n", pluto_log_file, strerror(errno)); } else { /* * buffer by line: * should be faster that no buffering * and yet safe since each message is probably a line. */ setvbuf(pluto_log_fp, NULL, _IOLBF, 0); } } if (log_to_syslog) openlog("pluto", LOG_CONS | LOG_NDELAY | LOG_PID, LOG_AUTHPRIV); CIRCLEQ_INIT(&perpeer_list); }
/* * ypdb_init: init the queues and lists */ void ypdb_init(void) { LIST_INIT(&doms); CIRCLEQ_INIT(&maps); }
/* * ex_screen_copy -- * Copy ex screen. * * PUBLIC: int ex_screen_copy __P((SCR *, SCR *)); */ int ex_screen_copy(SCR *orig, SCR *sp) { EX_PRIVATE *oexp, *nexp; /* Create the private ex structure. */ CALLOC_RET(orig, nexp, EX_PRIVATE *, 1, sizeof(EX_PRIVATE)); sp->ex_private = nexp; /* Initialize queues. */ CIRCLEQ_INIT(&nexp->tq); TAILQ_INIT(&nexp->tagfq); LIST_INIT(&nexp->cscq); if (orig == NULL) { } else { oexp = EXP(orig); if (oexp->lastbcomm != NULL && (nexp->lastbcomm = v_wstrdup(sp, oexp->lastbcomm, STRLEN(oexp->lastbcomm))) == NULL) { msgq(sp, M_SYSERR, NULL); return(1); } if (ex_tag_copy(orig, sp)) return (1); } return (0); }
void init_stmem() { int s = splhigh (); struct mem_node *mem; stmem_total = st_pool_size - sizeof(*mem); mem = (struct mem_node *)st_pool_virt; mem->size = st_pool_size - sizeof(*mem); CIRCLEQ_INIT(&st_list); CIRCLEQ_INIT(&free_list); CIRCLEQ_INSERT_HEAD(&st_list, mem, link); CIRCLEQ_INSERT_HEAD(&free_list, mem, free_link); splx(s); }
int main(int argc, const char *argv[]) { #if 1 CIRCLEQ_HEAD(circleq, _Data) head = CIRCLEQ_HEAD_INITIALIZER(head); #else CIRCLEQ_HEAD(circleq, _Data) head; CIRCLEQ_INIT(&head); #endif exit(EXIT_SUCCESS); }
void init_log(const char *program) { if (log_to_stderr) setbuf(stderr, NULL); if (log_to_syslog) openlog(program, LOG_CONS | LOG_NDELAY | LOG_PID, LOG_AUTHPRIV); CIRCLEQ_INIT(&perpeer_list); }
void pluto_init_log(void) { set_exit_log_func(exit_log); if (log_to_stderr) setbuf(stderr, NULL); if (log_to_syslog) openlog("pluto", LOG_CONS | LOG_NDELAY | LOG_PID, LOG_AUTHPRIV); CIRCLEQ_INIT(&perpeer_list); }
void in_pcbinit(struct inpcbtable *table, int bindhashsize, int connecthashsize) { static ONCE_DECL(control); CIRCLEQ_INIT(&table->inpt_queue); table->inpt_porthashtbl = hashinit(bindhashsize, HASH_LIST, true, &table->inpt_porthash); table->inpt_bindhashtbl = hashinit(bindhashsize, HASH_LIST, true, &table->inpt_bindhash); table->inpt_connecthashtbl = hashinit(connecthashsize, HASH_LIST, true, &table->inpt_connecthash); table->inpt_lastlow = IPPORT_RESERVEDMAX; table->inpt_lastport = (u_int16_t)anonportmax; RUN_ONCE(&control, inpcb_poolinit); }
int load_cve (char *path) { FILE *f = fopen (path, "r"); int i = 0, sz; char line[1024]; if (!f) return 1; CIRCLEQ_INIT (&head); while (!feof (f)) { fgets (line, 1024, f); if (strncmp (line, DELIMITER, 10) == 0) { entry *en = malloc (sizeof (entry)); for (i = 0, sz = 0; i < 20 && !feof (f); i++) { fgets (line, 1024, f); sz += strlen (line); if (strncmp (line, DELIMITER, 10) == 0) { CIRCLEQ_INSERT_HEAD (&head, en, entries); break; } if (line) { en->buf[i] = malloc (strlen (line) + 1); ++en->count; memcpy (en->buf[i], &line, strlen (line) + 1); } } } } fclose (f); return 0; }
int main(int argc, char** argv) { int current_size, queue_size; struct epoll_event e, events[MAX_EVENTS]; int epoll_fd; if (argc < 2) { puts("Usage : %s [size of client queue]", argv[0]); return 0; } current_size = 0; queue_size = argv[1]; CIRCLEQ_INIT(&head); while (1) { } return 0; }
void pluto_init_log(void) { set_alloc_exit_log_func(exit_log); if (log_to_stderr) setbuf(stderr, NULL); if (pluto_log_file != NULL) { pluto_log_fp = fopen(pluto_log_file, "w"); if (pluto_log_fp == NULL) { fprintf(stderr, "Cannot open logfile '%s': %s\n", pluto_log_file, strerror(errno)); } else { setbuf(pluto_log_fp, NULL); } } if (log_to_syslog) openlog("pluto", LOG_CONS | LOG_NDELAY | LOG_PID, LOG_AUTHPRIV); CIRCLEQ_INIT(&perpeer_list); }
int main(int argc, char* argv[]) { int opt, ret; int daemon = 1, lock = 0; int screen_status, aux_pressed, power_pressed, y, x; char *config; FILE *file; struct sockaddr_un addr; struct chain_socket *aux_grabber = 0, *power_grabber = 0; struct input_event input; struct iod_cmd cmd; struct chain_socket *cs; size_t size; y = x = screen_status = aux_pressed = power_pressed = 0; pwd = IOD_PWD; while((opt = getopt(argc, argv, "fd:")) != -1) { switch(opt) { case 'f': daemon = 0; break; case 'd': pwd = optarg; break; default: usage(argv[0]); return 0; } } if(optind == argc) { usage(argv[0]); return 0; } config = argv[optind]; if(mkdir(pwd, 0777) == -1 && errno != EEXIST) { perror("Failed to create working dir"); return 7; } if(daemon) { int tmp = fork(); if(tmp < 0) { perror("Failed to fork process"); return 1; } if(tmp > 0) { return 0; } setsid(); close(0); close(1); close(2); tmp = open("/dev/null", O_RDWR); dup(tmp); dup(tmp); chdir(pwd); if((tmp = open("pid", O_WRONLY|O_CREAT, 755)) < 0) { perror("Failed to open pidfile"); return 2; } pid_t pid = getpid(); char buf[10]; int count = sprintf(buf, "%i", pid); write(tmp, &buf, count*sizeof(char)); if(lockf(tmp, F_TLOCK, -count*sizeof(char)) < 0) { perror("Daemon already running"); return 3; } } if(!(file = fopen(config, "r"))) { perror("Failed to open config file"); return 4; } if((size = getline(&screen_dev, &size, file)) == -1) { fprintf(stderr, "Failed to read screen config\n"); return 5; } screen_dev[size-1] = 0; if((screen_fd = open(screen_dev, O_RDONLY)) == -1) { perror("Failed to open screen socket"); return 6; } if((size = getline(&aux_dev, &size, file)) == -1) { fprintf(stderr, "Failed to read aux config\n"); return 7; } aux_dev[size-1] = 0; if((aux_fd = open(aux_dev, O_RDONLY)) == -1) { perror("Failed to open aux socket"); return 8; } if((size = getline(&power_dev, &size, file)) == -1) { fprintf(stderr, "Failed to read power config\n"); return 9; } power_dev[size-1] = 0; fclose(file); if((power_fd = open(power_dev, O_RDONLY)) == -1) { perror("Failed to open power socket"); return 10; } DEBUG(print_info(screen_fd)); DEBUG(print_info(aux_fd)); DEBUG(print_info(power_fd)); if((ret = open_socket(&sock, &addr))) return ret; pfds_cap = 10; pfds = malloc(pfds_cap*sizeof(struct pollfd)); pfds[0].fd = screen_fd; pfds[0].events = POLLIN; pfds[1].fd = aux_fd; pfds[1].events = POLLIN; pfds[2].fd = power_fd; pfds[2].events = POLLIN; pfds[3].fd = sock; pfds[3].events = POLLIN; client_count = 0; CIRCLEQ_INIT(&client_list); signal(SIGINT, signal_handler); DEBUG(printf("Ready\n")); while(1) { poll(pfds, client_count+4, -1); if(pfds[0].revents & POLLHUP || pfds[0].revents & POLLERR) { DEBUG(printf("pollhup/err on screen socket\n")); close(screen_fd); if((screen_fd = open(screen_dev, O_RDONLY)) < 0) { perror("Failed to open screen socket"); screen_fd = 0; cleanup(); return 6; } } else if(pfds[0].revents & POLLIN) { read(screen_fd, &input, sizeof(struct input_event)); if(lock) continue; switch(input.type) { case EV_KEY: switch(input.code) { case BTN_TOUCH: switch(input.value) { case 0: screen_status = 0; break; case 1: screen_status = 1; break; } break; } break; case EV_ABS: switch(input.code) { case ABS_X: y = input.value-MIN_PIXEL; break; case ABS_Y: x = input.value-MIN_PIXEL; break; case ABS_PRESSURE: break; } break; case EV_SYN: switch(input.code) { case SYN_REPORT: switch(screen_status) { case 0: DEBUG(printf("Touchscreen released (%i,%i)\n", y, x)); send_client_cord(IOD_EVENT_RELEASED, y, x, 0); break; case 1: DEBUG(printf("Touchscreen pressed (%i,%i)\n", y, x)); send_client_cord(IOD_EVENT_PRESSED, y, x, 0); screen_status = 2; break; case 2: send_client_cord(IOD_EVENT_MOVED, y, x, 0); break; } break; } break; } } else if(pfds[1].revents & POLLHUP || pfds[1].revents & POLLERR) { DEBUG(printf("pollhup/err on aux socket\n")); close(aux_fd); if((aux_fd = open(aux_dev, O_RDONLY)) == -1) { perror("Failed to open aux socket"); aux_fd = 0; cleanup(); return 8; } } else if(pfds[1].revents & POLLIN) { read(aux_fd, &input, sizeof(struct input_event)); switch(input.type) { case EV_KEY: switch(input.code) { case KEY_PHONE: aux_pressed = input.value; break; } break; case EV_SYN: switch(input.code) { case SYN_REPORT: DEBUG(printf("AUX %s\n", aux_pressed ? "pressed" : "released")); cs = aux_grabber ? aux_grabber : 0; send_client_status(IOD_EVENT_AUX, aux_pressed, cs); break; } break; } } else if(pfds[2].revents & POLLHUP || pfds[2].revents & POLLERR) { DEBUG(printf("pollhup/err on power socket\n")); close(power_fd); if((power_fd = open(power_dev, O_RDONLY)) == -1) { perror("Failed to open power socket"); power_fd = 0; cleanup(); return 10; } } else if(pfds[2].revents & POLLIN) { read(power_fd, &input, sizeof(struct input_event)); switch(input.type) { case EV_KEY: switch(input.code) { case KEY_POWER: power_pressed = input.value; break; } break; case EV_PWR: break; case EV_SYN: switch(input.code) { case SYN_REPORT: DEBUG(printf("Power %s\n", power_pressed ? "pressed" : "released")); cs = power_grabber ? power_grabber : 0; send_client_status(IOD_EVENT_POWER, power_pressed, cs); break; } break; } } else if(pfds[3].revents & POLLHUP || pfds[3].revents & POLLERR) { DEBUG(printf("pollhup/err on socket\n")); close(sock); if((ret = open_socket(&sock, &addr))) { sock = 0; cleanup(); return ret; } } else if(pfds[3].revents & POLLIN) { int client; if((client = accept(sock, 0, 0)) == -1) { DEBUG(perror("Failed to accept client")); continue; } cs = client_list.cqh_first; add_client(client); if(cs != (void*)&client_list) send_client_status(IOD_EVENT_DEACTIVATED, 0, cs); else send_client_status(IOD_EVENT_ACTIVATED, 0, 0); } else { int x; for(x=4; x<client_count+4; x++) if(pfds[x].revents & POLLHUP || pfds[x].revents & POLLERR) { DEBUG(printf("pollhup/pollerr on client socket [%i]\n", pfds[x].fd)); cs = find_client(&x, 0); remove: if(cs == aux_grabber) { DEBUG(printf("AUX ungrabbed [%i] %i\n", cs->sock, cs->pid)); aux_grabber = 0; } if(cs == power_grabber) { DEBUG(printf("Power ungrabbed [%i] %i\n", cs->sock, cs->pid)); power_grabber = 0; } if(cs->lock) { DEBUG(printf("Screen unlocked [%i] %i\n", cs->sock, cs->pid)); lock = 0; } if(rem_client(x, cs)) send_client_status(IOD_EVENT_ACTIVATED, 0, 0); break; } else if(pfds[x].revents & POLLIN) { if(recv_client(pfds[x].fd, &cmd)) break; switch(cmd.cmd) { case IOD_CMD_REGISTER: register_client(x, cmd.pid); break; case IOD_CMD_REMOVE: if((cs = find_client(&x, cmd.pid))) { if(cs->sock == pfds[x].fd) goto remove; else { DEBUG(printf("Client remove [%i] %i\n", cs->sock, cs->pid)); send_client_status( IOD_EVENT_REMOVED, 0, cs); } } break; case IOD_CMD_SWITCH: cs = client_list.cqh_first; if(switch_client(cmd.value, x, cmd.pid)) send_client_status( IOD_EVENT_DEACTIVATED, 0, cs); break; case IOD_CMD_LOCK: cs = find_client(&x, 0); if(!lock || cs->lock) { lock = cs->lock = cmd.value; DEBUG(printf("Screen %s [%i] %i\n", lock ? "locked" : "unlocked", x, cs->pid)); send_client_status( IOD_EVENT_LOCK, IOD_SUCCESS_MASK, cs); } else send_client_status( IOD_EVENT_LOCK, 0, cs); break; case IOD_CMD_HIDE: hide_client(x, cmd.pid, cmd.value & ~IOD_HIDE_MASK, cmd.value & IOD_HIDE_MASK); break; case IOD_CMD_ACK: switch(cmd.value) { case IOD_EVENT_DEACTIVATED: cs = client_list.cqh_first; DEBUG(printf("Client switched [%i] %i -> [%i] %i\n", pfds[x].fd, find_client(&x, 0)->pid, cs->sock, cs->pid)); send_client_status( IOD_EVENT_ACTIVATED, 0, 0); break; case IOD_EVENT_REMOVED: cs = find_client(&x, 0); goto remove; default: DEBUG(printf("Client done [%i] %i\n", pfds[x].fd, find_client(&x, 0)->pid)); break; } break; case IOD_CMD_GRAB: cs = find_client(&x, 0); switch(cmd.value & ~IOD_GRAB_MASK) { case IOD_GRAB_AUX: if(!aux_grabber || cs == aux_grabber) { if(cmd.value & IOD_GRAB_MASK) { DEBUG(printf("AUX grabbed [%i] %i\n", cs->sock, cs->pid)); aux_grabber = cs; } else { DEBUG(printf("AUX ungrabbed [%i] %i\n", cs->sock, cs->pid)); aux_grabber = 0; } send_client_status(IOD_EVENT_GRAB, IOD_SUCCESS_MASK|IOD_GRAB_AUX, cs); } else send_client_status(IOD_EVENT_GRAB, IOD_GRAB_AUX, cs); break; case IOD_GRAB_POWER: if(!power_grabber || cs == power_grabber) { if(cmd.value & IOD_GRAB_MASK) { DEBUG(printf("Power grabbed [%i] %i\n", cs->sock, cs->pid)); power_grabber = cs; } else { DEBUG(printf("Power ungrabbed [%i] %i\n", cs->sock, cs->pid)); power_grabber = 0; } send_client_status(IOD_EVENT_GRAB, IOD_SUCCESS_MASK|IOD_GRAB_POWER, cs); } else send_client_status(IOD_EVENT_GRAB, IOD_GRAB_POWER, cs); break; } break; case IOD_CMD_POWERSAVE: DEBUG(printf("Powersave %s broadcast\n", cmd.value ? "on" : "off")); cs = client_list.cqh_first; while(cs != (void*)&client_list) { if(cs->sock != pfds[x].fd) send_client_status( IOD_EVENT_POWERSAVE, cmd.value, cs); cs = cs->chain.cqe_next; } break; default: DEBUG(printf("Unrecognized command 0x%02hhx [%i] %i\n", cmd.cmd, pfds[x].fd, find_client(&x, 0)->pid)); } break; } } } cleanup(); return 0; }
/* * screen_init -- * Do the default initialization of an SCR structure. * * PUBLIC: int screen_init __P((GS *, SCR *, SCR **)); */ int screen_init(GS *gp, SCR *orig, SCR **spp) { SCR *sp; size_t len; *spp = NULL; CALLOC_RET(orig, sp, SCR *, 1, sizeof(SCR)); *spp = sp; /* INITIALIZED AT SCREEN CREATE. */ sp->id = ++gp->id; sp->refcnt = 1; sp->gp = gp; /* All ref the GS structure. */ sp->ccnt = 2; /* Anything > 1 */ /* * XXX * sp->defscroll is initialized by the opts_init() code because * we don't have the option information yet. */ CIRCLEQ_INIT(&sp->tiq); /* PARTIALLY OR COMPLETELY COPIED FROM PREVIOUS SCREEN. */ if (orig == NULL) { sp->searchdir = NOTSET; } else { sp->wp = orig->wp; /* Alternate file name. */ if (orig->alt_name != NULL && (sp->alt_name = strdup(orig->alt_name)) == NULL) goto mem; /* Last executed at buffer. */ if (F_ISSET(orig, SC_AT_SET)) { F_SET(sp, SC_AT_SET); sp->at_lbuf = orig->at_lbuf; } /* Retain searching/substitution information. */ sp->searchdir = orig->searchdir == NOTSET ? NOTSET : FORWARD; if (orig->re != NULL && (sp->re = v_wstrdup(sp, orig->re, orig->re_len)) == NULL) goto mem; sp->re_len = orig->re_len; if (orig->subre != NULL && (sp->subre = v_wstrdup(sp, orig->subre, orig->subre_len)) == NULL) goto mem; sp->subre_len = orig->subre_len; if (orig->repl != NULL && (sp->repl = v_wstrdup(sp, orig->repl, orig->repl_len)) == NULL) goto mem; sp->repl_len = orig->repl_len; if (orig->newl_len) { len = orig->newl_len * sizeof(size_t); MALLOC(sp, sp->newl, size_t *, len); if (sp->newl == NULL) { mem: msgq(orig, M_SYSERR, NULL); goto err; } sp->newl_len = orig->newl_len; sp->newl_cnt = orig->newl_cnt; memcpy(sp->newl, orig->newl, len); } if (opts_copy(orig, sp)) goto err; F_SET(sp, F_ISSET(orig, SC_EX | SC_VI)); }
/* * cut -- * Put a range of lines/columns into a TEXT buffer. * * There are two buffer areas, both found in the global structure. The first * is the linked list of all the buffers the user has named, the second is the * unnamed buffer storage. There is a pointer, too, which is the current * default buffer, i.e. it may point to the unnamed buffer or a named buffer * depending on into what buffer the last text was cut. Logically, in both * delete and yank operations, if the user names a buffer, the text is cut * into it. If it's a delete of information on more than a single line, the * contents of the numbered buffers are rotated up one, the contents of the * buffer named '9' are discarded, and the text is cut into the buffer named * '1'. The text is always cut into the unnamed buffer. * * In all cases, upper-case buffer names are the same as lower-case names, * with the exception that they cause the buffer to be appended to instead * of replaced. Note, however, that if text is appended to a buffer, the * default buffer only contains the appended text, not the entire contents * of the buffer. * * !!! * The contents of the default buffer would disappear after most operations * in historic vi. It's unclear that this is useful, so we don't bother. * * When users explicitly cut text into the numeric buffers, historic vi became * genuinely strange. I've never been able to figure out what was supposed to * happen. It behaved differently if you deleted text than if you yanked text, * and, in the latter case, the text was appended to the buffer instead of * replacing the contents. Hopefully it's not worth getting right, and here * we just treat the numeric buffers like any other named buffer. * * PUBLIC: int cut __P((SCR *, ARG_CHAR_T *, MARK *, MARK *, int)); */ int cut(SCR *sp, ARG_CHAR_T *namep, MARK *fm, MARK *tm, int flags) { CB *cbp; ARG_CHAR_T name = '\0'; db_recno_t lno; int append, copy_one, copy_def; /* * If the user specified a buffer, put it there. (This may require * a copy into the numeric buffers. We do the copy so that we don't * have to reference count and so we don't have to deal with things * like appends to buffers that are used multiple times.) * * Otherwise, if it's supposed to be put in a numeric buffer (usually * a delete) put it there. The rules for putting things in numeric * buffers were historically a little strange. There were three cases. * * 1: Some motions are always line mode motions, which means * that the cut always goes into the numeric buffers. * 2: Some motions aren't line mode motions, e.g. d10w, but * can cross line boundaries. For these commands, if the * cut crosses a line boundary, it goes into the numeric * buffers. This includes most of the commands. * 3: Some motions aren't line mode motions, e.g. d`<char>, * but always go into the numeric buffers, regardless. This * was the commands: % ` / ? ( ) N n { } -- and nvi adds ^A. * * Otherwise, put it in the unnamed buffer. */ append = copy_one = copy_def = 0; if (namep != NULL) { name = *namep; if (LF_ISSET(CUT_NUMREQ) || (LF_ISSET(CUT_NUMOPT) && (LF_ISSET(CUT_LINEMODE) || fm->lno != tm->lno))) { copy_one = 1; cb_rotate(sp); } if ((append = ISUPPER(name)) == 1) { if (!copy_one) copy_def = 1; name = TOLOWER(name); } namecb: CBNAME(sp, cbp, name); } else if (LF_ISSET(CUT_NUMREQ) || (LF_ISSET(CUT_NUMOPT) && (LF_ISSET(CUT_LINEMODE) || fm->lno != tm->lno))) { name = '1'; cb_rotate(sp); goto namecb; } else cbp = &sp->wp->dcb_store; copyloop: /* * If this is a new buffer, create it and add it into the list. * Otherwise, if it's not an append, free its current contents. */ if (cbp == NULL) { CALLOC_RET(sp, cbp, CB *, 1, sizeof(CB)); cbp->name = name; CIRCLEQ_INIT(&cbp->textq); LIST_INSERT_HEAD(&sp->wp->cutq, cbp, q); } else if (!append) {
/* * file_init -- * Start editing a file, based on the FREF structure. If successsful, * let go of any previous file. Don't release the previous file until * absolutely sure we have the new one. * * PUBLIC: int file_init __P((SCR *, FREF *, char *, int)); */ int file_init(SCR *sp, FREF *frp, char *rcv_name, int flags) { EXF *ep; struct stat sb; size_t psize; int fd, exists, open_err, readonly, stolen; char *oname, tname[MAXPATHLEN]; stolen = open_err = readonly = 0; /* * If the file is a recovery file, let the recovery code handle it. * Clear the FR_RECOVER flag first -- the recovery code does set up, * and then calls us! If the recovery call fails, it's probably * because the named file doesn't exist. So, move boldly forward, * presuming that there's an error message the user will get to see. */ if (F_ISSET(frp, FR_RECOVER)) { F_CLR(frp, FR_RECOVER); return (rcv_read(sp, frp)); } /* * Required FRP initialization; the only flag we keep is the * cursor information. */ F_CLR(frp, ~FR_CURSORSET); /* * Scan the user's path to find the file that we're going to * try and open. */ if (file_spath(sp, frp, &sb, &exists)) return (1); /* * Check whether we already have this file opened in some * other screen. */ if (exists) { EXF *exfp; for (exfp = sp->gp->exfq.cqh_first; exfp != (EXF *)&sp->gp->exfq; exfp = exfp->q.cqe_next) { if (exfp->mdev == sb.st_dev && exfp->minode == sb.st_ino && (exfp != sp->ep || exfp->refcnt > 1)) { ep = exfp; goto postinit; } } } /* * Required EXF initialization: * Flush the line caches. * Default recover mail file fd to -1. * Set initial EXF flag bits. */ CALLOC_RET(sp, ep, EXF *, 1, sizeof(EXF)); CIRCLEQ_INIT(&ep->scrq); sp->c_lno = ep->c_nlines = OOBLNO; ep->rcv_fd = ep->fcntl_fd = -1; F_SET(ep, F_FIRSTMODIFY); /* * If no name or backing file, for whatever reason, create a backing * temporary file, saving the temp file name so we can later unlink * it. If the user never named this file, copy the temporary file name * to the real name (we display that until the user renames it). */ oname = frp->name; if (LF_ISSET(FS_OPENERR) || oname == NULL || !exists) { if (opts_empty(sp, O_TMP_DIRECTORY, 0)) goto err; (void)snprintf(tname, sizeof(tname), "%s/vi.XXXXXX", O_STR(sp, O_TMP_DIRECTORY)); if ((fd = mkstemp(tname)) == -1) { msgq(sp, M_SYSERR, "237|Unable to create temporary file"); goto err; } (void)close(fd); if (frp->name == NULL) F_SET(frp, FR_TMPFILE); if ((frp->tname = strdup(tname)) == NULL || (frp->name == NULL && (frp->name = strdup(tname)) == NULL)) { if (frp->tname != NULL) { free(frp->tname); } msgq(sp, M_SYSERR, NULL); (void)unlink(tname); goto err; } oname = frp->tname; psize = 1024; if (!LF_ISSET(FS_OPENERR)) F_SET(frp, FR_NEWFILE); time(&ep->mtime); } else { /* * XXX * A seat of the pants calculation: try to keep the file in * 15 pages or less. Don't use a page size larger than 10K * (vi should have good locality) or smaller than 1K. */ psize = ((sb.st_size / 15) + 1023) / 1024; if (psize > 10) psize = 10; if (psize == 0) psize = 1; psize *= 1024; F_SET(ep, F_DEVSET); ep->mdev = sb.st_dev; ep->minode = sb.st_ino; ep->mtime = sb.st_mtime; if (!S_ISREG(sb.st_mode)) msgq_str(sp, M_ERR, oname, "238|Warning: %s is not a regular file"); } /* Set up recovery. */ if (rcv_name == NULL) { /* ep->rcv_path NULL if rcv_tmp fails */ rcv_tmp(sp, ep, frp->name); } else { if ((ep->rcv_path = strdup(rcv_name)) == NULL) { msgq(sp, M_SYSERR, NULL); goto err; } F_SET(ep, F_MODIFIED); } if (db_setup(sp, ep)) goto err; /* Open a db structure. */ if ((sp->db_error = db_create(&ep->db, 0, 0)) != 0) { msgq(sp, M_DBERR, "db_create"); goto err; } ep->db->set_re_delim(ep->db, '\n'); /* Always set. */ ep->db->set_pagesize(ep->db, psize); ep->db->set_flags(ep->db, DB_RENUMBER | DB_SNAPSHOT); if (rcv_name == NULL) ep->db->set_re_source(ep->db, oname); /* * Don't let db use mmap when using fcntl for locking */ #ifdef HAVE_LOCK_FCNTL #define NOMMAPIFFCNTL DB_NOMMAP #else #define NOMMAPIFFCNTL 0 #endif #define _DB_OPEN_MODE S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH if ((sp->db_error = db_open(ep->db, ep->rcv_path, DB_RECNO, ((rcv_name == 0) ? DB_TRUNCATE : 0) | VI_DB_THREAD | NOMMAPIFFCNTL, _DB_OPEN_MODE)) != 0) { msgq_str(sp, M_DBERR, rcv_name == NULL ? oname : rcv_name, "%s"); /* * !!! * Historically, vi permitted users to edit files that couldn't * be read. This isn't useful for single files from a command * line, but it's quite useful for "vi *.c", since you can skip * past files that you can't read. */ ep->db = NULL; /* Don't close it; it wasn't opened */ if (LF_ISSET(FS_OPENERR)) goto err; open_err = 1; goto oerr; } /* re_source is loaded into the database. * Close it and reopen it in the environment. */ if ((sp->db_error = ep->db->close(ep->db, 0))) { msgq(sp, M_DBERR, "close"); goto err; } if ((sp->db_error = db_create(&ep->db, ep->env, 0)) != 0) { msgq(sp, M_DBERR, "db_create 2"); goto err; } if ((sp->db_error = db_open(ep->db, ep->rcv_path, DB_RECNO, VI_DB_THREAD | NOMMAPIFFCNTL, _DB_OPEN_MODE)) != 0) { msgq_str(sp, M_DBERR, ep->rcv_path, "%s"); goto err; } /* * Do the remaining things that can cause failure of the new file, * mark and logging initialization. */ if (mark_init(sp, ep) || log_init(sp, ep)) goto err; postinit: /* * Set the alternate file name to be the file we're discarding. * * !!! * Temporary files can't become alternate files, so there's no file * name. This matches historical practice, although it could only * happen in historical vi as the result of the initial command, i.e. * if vi was executed without a file name. */ if (LF_ISSET(FS_SETALT)) set_alt_name(sp, sp->frp == NULL || F_ISSET(sp->frp, FR_TMPFILE) ? NULL : sp->frp->name); /* * Close the previous file; if that fails, close the new one and run * for the border. * * !!! * There's a nasty special case. If the user edits a temporary file, * and then does an ":e! %", we need to re-initialize the backing * file, but we can't change the name. (It's worse -- we're dealing * with *names* here, we can't even detect that it happened.) Set a * flag so that the file_end routine ignores the backing information * of the old file if it happens to be the same as the new one. * * !!! * Side-effect: after the call to file_end(), sp->frp may be NULL. */ if (sp->ep != NULL) { F_SET(frp, FR_DONTDELETE); if (file_end(sp, NULL, LF_ISSET(FS_FORCE))) { (void)file_end(sp, ep, 1); goto err; } sp->ep = NULL; F_CLR(frp, FR_DONTDELETE); } /* * Lock the file; if it's a recovery file, it should already be * locked. Note, we acquire the lock after the previous file * has been ended, so that we don't get an "already locked" error * for ":edit!". * * XXX * While the user can't interrupt us between the open and here, * there's a race between the dbopen() and the lock. Not much * we can do about it. * * XXX * We don't make a big deal of not being able to lock the file. As * locking rarely works over NFS, and often fails if the file was * mmap(2)'d, it's far too common to do anything like print an error * message, let alone make the file readonly. At some future time, * when locking is a little more reliable, this should change to be * an error. */ if (rcv_name == NULL && ep->refcnt == 0) { if ((ep->fd = open(oname, O_RDWR)) == -1) goto no_lock; switch (file_lock(sp, oname, &ep->fcntl_fd, ep->fd, 1)) { case LOCK_FAILED: no_lock: F_SET(frp, FR_UNLOCKED); break; case LOCK_UNAVAIL: readonly = 1; msgq_str(sp, M_INFO, oname, "239|%s already locked, session is read-only"); break; case LOCK_SUCCESS: break; } } /* * Historically, the readonly edit option was set per edit buffer in * vi, unless the -R command-line option was specified or the program * was executed as "view". (Well, to be truthful, if the letter 'w' * occurred anywhere in the program name, but let's not get into that.) * So, the persistant readonly state has to be stored in the screen * structure, and the edit option value toggles with the contents of * the edit buffer. If the persistant readonly flag is set, set the * readonly edit option. * * Otherwise, try and figure out if a file is readonly. This is a * dangerous thing to do. The kernel is the only arbiter of whether * or not a file is writeable, and the best that a user program can * do is guess. Obvious loopholes are files that are on a file system * mounted readonly (access catches this one on a few systems), or * alternate protection mechanisms, ACL's for example, that we can't * portably check. Lots of fun, and only here because users whined. * * !!! * Historic vi displayed the readonly message if none of the file * write bits were set, or if an an access(2) call on the path * failed. This seems reasonable. If the file is mode 444, root * users may want to know that the owner of the file did not expect * it to be written. * * Historic vi set the readonly bit if no write bits were set for * a file, even if the access call would have succeeded. This makes * the superuser force the write even when vi expects that it will * succeed. I'm less supportive of this semantic, but it's historic * practice and the conservative approach to vi'ing files as root. * * It would be nice if there was some way to update this when the user * does a "^Z; chmod ...". The problem is that we'd first have to * distinguish between readonly bits set because of file permissions * and those set for other reasons. That's not too hard, but deciding * when to reevaluate the permissions is trickier. An alternative * might be to turn off the readonly bit if the user forces a write * and it succeeds. * * XXX * Access(2) doesn't consider the effective uid/gid values. This * probably isn't a problem for vi when it's running standalone. */ if (readonly || F_ISSET(sp, SC_READONLY) || (!F_ISSET(frp, FR_NEWFILE) && (!(sb.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH)) || access(frp->name, W_OK)))) O_SET(sp, O_READONLY); else O_CLR(sp, O_READONLY); /* Switch... */ ++ep->refcnt; CIRCLEQ_INSERT_HEAD(&ep->scrq, sp, eq); sp->ep = ep; sp->frp = frp; /* Set the initial cursor position, queue initial command. */ file_cinit(sp); /* Report conversion errors again. */ F_CLR(sp, SC_CONV_ERROR); /* Redraw the screen from scratch, schedule a welcome message. */ F_SET(sp, SC_SCR_REFORMAT | SC_STATUS); if (frp->lno == OOBLNO) F_SET(sp, SC_SCR_TOP); /* Append into the chain of file structures. */ if (ep->refcnt == 1) CIRCLEQ_INSERT_TAIL(&sp->gp->exfq, ep, q); return (0); err: if (frp->name != NULL) { free(frp->name); frp->name = NULL; } if (frp->tname != NULL) { (void)unlink(frp->tname); free(frp->tname); frp->tname = NULL; } oerr: if (F_ISSET(ep, F_RCV_ON)) (void)unlink(ep->rcv_path); if (ep->rcv_path != NULL) { free(ep->rcv_path); ep->rcv_path = NULL; } if (ep->db != NULL) { (void)ep->db->close(ep->db, DB_NOSYNC); ep->db = NULL; } free(ep); return (open_err && !LF_ISSET(FS_OPENERR) ? file_init(sp, frp, rcv_name, flags | FS_OPENERR) : 1); }
void InitProcessTables (void) { uint32 t; struct Process *proc; struct Timer *timer; struct ISRHandler *isr_handler; struct Channel *channel; struct Handle *handle; struct Parcel *parcel; KPRINTF ("InitProcessTables()"); for (t=0;t<NIRQ;t++) { LIST_INIT (&isr_handler_list[t]); } for (t=0; t<32; t++) { CIRCLEQ_INIT (&realtime_queue[t]); } LIST_INIT (&stride_queue); LIST_INIT (&free_process_list) for (t=0; t<max_process; t++) { proc = (struct Process *)((uint8 *)process_table + t*PROCESS_SZ); LIST_ADD_TAIL (&free_process_list, proc, free_entry); proc->state = PROC_STATE_UNALLOC; } for (t=0; t<JIFFIES_PER_SECOND; t++) { LIST_INIT(&timing_wheel[t]); } softclock_seconds = hardclock_seconds = 0; softclock_jiffies = hardclock_jiffies = 0; LIST_INIT (&free_timer_list); for (t=0; t < max_timer; t++) { timer = &timer_table[t]; LIST_ADD_TAIL (&free_timer_list, timer, timer_entry); } LIST_INIT (&free_isr_handler_list); for (t=0; t < max_isr_handler; t++) { isr_handler = &isr_handler_table[t]; LIST_ADD_TAIL (&free_isr_handler_list, isr_handler, isr_handler_entry); } LIST_INIT (&free_channel_list); for (t=0; t < max_channel; t++) { channel = &channel_table[t]; LIST_ADD_TAIL (&free_channel_list, channel, link); } LIST_INIT (&free_handle_list); for (t = 0; t < max_handle; t++) { handle = &handle_table[t]; handle->type = HANDLE_TYPE_FREE; handle->pending = 0; handle->owner = NULL; handle->object = NULL; handle->flags = 0; LIST_ADD_TAIL (&free_handle_list, handle, link); } LIST_INIT (&free_parcel_list); for (t=0; t < max_parcel; t++) { parcel = &parcel_table[t]; LIST_ADD_TAIL (&free_parcel_list, parcel, link); } }