/* * Add a \IM. `tags' points to a zero-terminated chain of * zero-terminated strings ("first\0second\0thirdandlast\0\0"). * `text' points to a word list. * * Guarantee on calling sequence: all implicit merges are given * before the explicit ones. */ void index_merge(indexdata *idx, int is_explicit, wchar_t *tags, word *text, filepos *fpos) { indextag *t, *existing; /* * For an implicit merge, we want to remove all emphasis, * because the chances are that the user didn't really want to * index the term as emphasised. */ { word *w; for (w = text; w; w = w->next) { if (w->type == word_Emph) w->type = word_Normal; else if (w->type == word_EmphSpace) w->type = word_WhiteSpace; else if (w->type == word_EmphQuote) w->type = word_Quote; } } /* * FIXME: want to warn on overlapping source sets. */ for (; *tags; tags = uadv(tags)) { t = make_indextag(); t->name = tags; existing = add234(idx->tags, t); if (existing == t) { /* * Duplicate this so we can free it independently. */ t->name = ustrdup(tags); /* * Every tag has an implicit \IM. So if this tag * doesn't exist and we're explicit, then we should * warn (and drop it, since it won't be referenced). */ if (is_explicit) { error(err_nosuchidxtag, fpos, tags); continue; } /* * Otherwise, this is a new tag with an implicit \IM. */ t->implicit_text = text; t->implicit_fpos = *fpos; } else { if (!is_explicit) { /* * An implicit \IM for a tag that's had an implicit * \IM before. FIXME: we should check the text * against the existing text and warn on * differences. And check the tag for case match * against the existing tag, likewise. */ /* * Check the tag against its previous occurrence to * see if the cases match. */ if (ustrcmp(t->name, existing->name)) { error(err_indexcase, fpos, t->name, &existing->implicit_fpos, existing->name); } sfree(t); } else { /* * An explicit \IM added to a valid tag. In * particular, this removes the implicit \IM if * present. */ sfree(t); t = existing; if (t->implicit_text) { free_word_list(t->implicit_text); t->implicit_text = NULL; } if (t->nexplicit >= t->explicit_size) { t->explicit_size = t->nexplicit + 8; t->explicit_texts = sresize(t->explicit_texts, t->explicit_size, word *); t->explicit_fpos = sresize(t->explicit_fpos, t->explicit_size, filepos); } t->explicit_texts[t->nexplicit] = text; t->explicit_fpos[t->nexplicit] = *fpos; t->nexplicit++; } } }
Socket platform_new_connection(SockAddr addr, char *hostname, int port, int privport, int oobinline, int nodelay, int keepalive, Plug plug, Conf *conf) { char *cmd; static const struct socket_function_table socket_fn_table = { sk_localproxy_plug, sk_localproxy_close, sk_localproxy_write, sk_localproxy_write_oob, sk_localproxy_write_eof, sk_localproxy_flush, sk_localproxy_set_frozen, sk_localproxy_socket_error, NULL, /* peer_info */ }; Local_Proxy_Socket ret; int to_cmd_pipe[2], from_cmd_pipe[2], pid; if (conf_get_int(conf, CONF_proxy_type) != PROXY_CMD) return NULL; cmd = format_telnet_command(addr, port, conf); ret = snew(struct Socket_localproxy_tag); ret->fn = &socket_fn_table; ret->plug = plug; ret->error = NULL; ret->outgoingeof = EOF_NO; bufchain_init(&ret->pending_input_data); bufchain_init(&ret->pending_output_data); /* * Create the pipes to the proxy command, and spawn the proxy * command process. */ if (pipe(to_cmd_pipe) < 0 || pipe(from_cmd_pipe) < 0) { ret->error = dupprintf("pipe: %s", strerror(errno)); sfree(cmd); return (Socket)ret; } cloexec(to_cmd_pipe[1]); cloexec(from_cmd_pipe[0]); pid = fork(); if (pid < 0) { ret->error = dupprintf("fork: %s", strerror(errno)); sfree(cmd); return (Socket)ret; } else if (pid == 0) { close(0); close(1); dup2(to_cmd_pipe[0], 0); dup2(from_cmd_pipe[1], 1); close(to_cmd_pipe[0]); close(from_cmd_pipe[1]); noncloexec(0); noncloexec(1); execl("/bin/sh", "sh", "-c", cmd, (void *)NULL); _exit(255); } sfree(cmd); close(to_cmd_pipe[0]); close(from_cmd_pipe[1]); ret->to_cmd = to_cmd_pipe[1]; ret->from_cmd = from_cmd_pipe[0]; if (!localproxy_by_fromfd) localproxy_by_fromfd = newtree234(localproxy_fromfd_cmp); if (!localproxy_by_tofd) localproxy_by_tofd = newtree234(localproxy_tofd_cmp); add234(localproxy_by_fromfd, ret); add234(localproxy_by_tofd, ret); uxsel_set(ret->from_cmd, 1, localproxy_select_result); /* We are responsible for this and don't need it any more */ sk_addr_free(addr); return (Socket) ret; }
static void pty_open_master(Pty pty) { #ifdef BSD_PTYS const char chars1[] = "pqrstuvwxyz"; const char chars2[] = "0123456789abcdef"; const char *p1, *p2; char master_name[20]; struct group *gp; for (p1 = chars1; *p1; p1++) for (p2 = chars2; *p2; p2++) { sprintf(master_name, "/dev/pty%c%c", *p1, *p2); pty->master_fd = open(master_name, O_RDWR); if (pty->master_fd >= 0) { if (geteuid() == 0 || access(master_name, R_OK | W_OK) == 0) { /* * We must also check at this point that we are * able to open the slave side of the pty. We * wouldn't want to allocate the wrong master, * get all the way down to forking, and _then_ * find we're unable to open the slave. */ strcpy(pty->name, master_name); pty->name[5] = 't'; /* /dev/ptyXX -> /dev/ttyXX */ cloexec(pty->master_fd); if (pty_open_slave(pty) >= 0 && access(pty->name, R_OK | W_OK) == 0) goto got_one; if (pty->slave_fd > 0) close(pty->slave_fd); pty->slave_fd = -1; } close(pty->master_fd); } } /* If we get here, we couldn't get a tty at all. */ fprintf(stderr, "pterm: unable to open a pseudo-terminal device\n"); exit(1); got_one: /* We need to chown/chmod the /dev/ttyXX device. */ gp = getgrnam("tty"); chown(pty->name, getuid(), gp ? gp->gr_gid : -1); chmod(pty->name, 0600); #else const int flags = O_RDWR #ifdef O_NOCTTY | O_NOCTTY #endif ; #ifdef HAVE_POSIX_OPENPT #ifdef SET_NONBLOCK_VIA_OPENPT /* * OS X, as of 10.10 at least, doesn't permit me to set O_NONBLOCK * on pty master fds via the usual fcntl mechanism. Fortunately, * it does let me work around this by adding O_NONBLOCK to the * posix_openpt flags parameter, which isn't a documented use of * the API but seems to work. So we'll do that for now. */ pty->master_fd = posix_openpt(flags | O_NONBLOCK); #else pty->master_fd = posix_openpt(flags); #endif if (pty->master_fd < 0) { perror("posix_openpt"); exit(1); } #else pty->master_fd = open("/dev/ptmx", flags); if (pty->master_fd < 0) { perror("/dev/ptmx: open"); exit(1); } #endif if (grantpt(pty->master_fd) < 0) { perror("grantpt"); exit(1); } if (unlockpt(pty->master_fd) < 0) { perror("unlockpt"); exit(1); } cloexec(pty->master_fd); pty->name[FILENAME_MAX-1] = '\0'; strncpy(pty->name, ptsname(pty->master_fd), FILENAME_MAX-1); #endif #ifndef SET_NONBLOCK_VIA_OPENPT nonblock(pty->master_fd); #endif if (!ptys_by_fd) ptys_by_fd = newtree234(pty_compare_by_fd); add234(ptys_by_fd, pty); }
char *winsock_error_string(int error) { const char prefix[] = "Network error: "; struct errstring *es; /* * Error codes we know about and have historically had reasonably * sensible error messages for. */ switch (error) { case WSAEACCES: return "Network error: Permission denied"; case WSAEADDRINUSE: return "Network error: Address already in use"; case WSAEADDRNOTAVAIL: return "Network error: Cannot assign requested address"; case WSAEAFNOSUPPORT: return "Network error: Address family not supported by protocol family"; case WSAEALREADY: return "Network error: Operation already in progress"; case WSAECONNABORTED: return "Network error: Software caused connection abort"; case WSAECONNREFUSED: return "Network error: Connection refused"; case WSAECONNRESET: return "Network error: Connection reset by peer"; case WSAEDESTADDRREQ: return "Network error: Destination address required"; case WSAEFAULT: return "Network error: Bad address"; case WSAEHOSTDOWN: return "Network error: Host is down"; case WSAEHOSTUNREACH: return "Network error: No route to host"; case WSAEINPROGRESS: return "Network error: Operation now in progress"; case WSAEINTR: return "Network error: Interrupted function call"; case WSAEINVAL: return "Network error: Invalid argument"; case WSAEISCONN: return "Network error: Socket is already connected"; case WSAEMFILE: return "Network error: Too many open files"; case WSAEMSGSIZE: return "Network error: Message too long"; case WSAENETDOWN: return "Network error: Network is down"; case WSAENETRESET: return "Network error: Network dropped connection on reset"; case WSAENETUNREACH: return "Network error: Network is unreachable"; case WSAENOBUFS: return "Network error: No buffer space available"; case WSAENOPROTOOPT: return "Network error: Bad protocol option"; case WSAENOTCONN: return "Network error: Socket is not connected"; case WSAENOTSOCK: return "Network error: Socket operation on non-socket"; case WSAEOPNOTSUPP: return "Network error: Operation not supported"; case WSAEPFNOSUPPORT: return "Network error: Protocol family not supported"; case WSAEPROCLIM: return "Network error: Too many processes"; case WSAEPROTONOSUPPORT: return "Network error: Protocol not supported"; case WSAEPROTOTYPE: return "Network error: Protocol wrong type for socket"; case WSAESHUTDOWN: return "Network error: Cannot send after socket shutdown"; case WSAESOCKTNOSUPPORT: return "Network error: Socket type not supported"; case WSAETIMEDOUT: return "Network error: Connection timed out"; case WSAEWOULDBLOCK: return "Network error: Resource temporarily unavailable"; case WSAEDISCON: return "Network error: Graceful shutdown in progress"; } /* * Generic code to handle any other error. * * Slightly nasty hack here: we want to return a static string * which the caller will never have to worry about freeing, but on * the other hand if we call FormatMessage to get it then it will * want to either allocate a buffer or write into one we own. * * So what we do is to maintain a tree234 of error strings we've * already used. New ones are allocated from the heap, but then * put in this tree and kept forever. */ if (!errstrings) errstrings = newtree234(errstring_compare); es = find234(errstrings, &error, errstring_find); if (!es) { int bufsize, bufused; es = snew(struct errstring); es->error = error; /* maximum size for FormatMessage is 64K */ bufsize = 65535 + sizeof(prefix); es->text = snewn(bufsize, char); strcpy(es->text, prefix); bufused = strlen(es->text); if (!FormatMessage((FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS), NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), es->text + bufused, bufsize - bufused, NULL)) { sprintf(es->text + bufused, "Windows error code %d (and FormatMessage returned %d)", error, GetLastError()); } else { int len = strlen(es->text); if (len > 0 && es->text[len-1] == '\n') es->text[len-1] = '\0'; } es->text = sresize(es->text, strlen(es->text) + 1, char); add234(errstrings, es); }