コード例 #1
0
ファイル: win32.c プロジェクト: CedarLogic/watchman
bool winwatch_root_init(watchman_global_watcher_t watcher, w_root_t *root,
    char **errmsg) {
  struct winwatch_root_state *state;
  WCHAR *wpath;
  int err;
  unused_parameter(watcher);

  state = calloc(1, sizeof(*state));
  if (!state) {
    *errmsg = strdup("out of memory");
    return false;
  }
  root->watch = state;

  wpath = w_utf8_to_win_unc(root->root_path->buf, root->root_path->len);
  if (!wpath) {
    asprintf(errmsg, "failed to convert root path to WCHAR: %s",
        win32_strerror(GetLastError()));
    return false;
  }

  // Create an overlapped handle so that we can avoid blocking forever
  // in ReadDirectoryChangesW
  state->dir_handle = CreateFileW(wpath, GENERIC_READ,
      FILE_SHARE_READ|FILE_SHARE_DELETE|FILE_SHARE_WRITE,
      NULL, OPEN_EXISTING,
      FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OVERLAPPED, NULL);
  if (!state->dir_handle) {
    asprintf(errmsg, "failed to open dir %s: %s",
        root->root_path->buf, win32_strerror(GetLastError()));
    return false;
  }

  state->ping = CreateEvent(NULL, TRUE, FALSE, NULL);
  if (!state->ping) {
    asprintf(errmsg, "failed to create event: %s",
        win32_strerror(GetLastError()));
    return false;
  }
  state->olap = CreateEvent(NULL, TRUE, FALSE, NULL);
  if (!state->olap) {
    asprintf(errmsg, "failed to create event: %s",
        win32_strerror(GetLastError()));
    return false;
  }
  err = pthread_mutex_init(&state->mtx, NULL);
  if (err) {
    asprintf(errmsg, "failed to init mutex: %s",
        strerror(err));
    return false;
  }
  err = pthread_cond_init(&state->cond, NULL);
  if (err) {
    asprintf(errmsg, "failed to init cond: %s",
        strerror(err));
    return false;
  }

  return true;
}
コード例 #2
0
ファイル: stream_win.c プロジェクト: bitemyapp/watchman
// Must be called with the mutex held
static void initiate_write(struct win_handle *h) {
  struct write_buf *wbuf = h->write_head;
  if (h->write_pending || !wbuf) {
    return;
  }

  h->write_head = wbuf->next;
  if (!h->write_head) {
    h->write_tail = NULL;
  }

  h->write_pending = calloc(1, sizeof(*h->write_pending));
  h->write_pending->h = h;
  h->write_pending->wbuf = wbuf;

  if (!WriteFileEx(h->h, wbuf->cursor, wbuf->len, &h->write_pending->olap,
        write_completed)) {
    stream_debug("WriteFileEx: failed %s\n",
        win32_strerror(GetLastError()));
    free(h->write_pending);
    h->write_pending = NULL;
  } else {
    stream_debug("WriteFileEx: queued %d bytes for later\n", wbuf->len);
  }
}
コード例 #3
0
ファイル: stream_win.c プロジェクト: bitemyapp/watchman
static int win_read_blocking(struct win_handle *h, char *buf, int size) {
  int total_read = 0;
  DWORD bytes, err;

  move_from_read_buffer(h, &total_read, &buf, &size);

  if (size == 0) {
    return total_read;
  }

  stream_debug("blocking read of %d bytes\n", (int)size);
  if (ReadFile(h->h, buf, size, &bytes, NULL)) {
    total_read += bytes;
    stream_debug("blocking read provided %d bytes, total=%d\n",
        (int)bytes, total_read);
    return total_read;
  }

  err = GetLastError();

  stream_debug("blocking read failed: %s\n", win32_strerror(err));

  if (total_read) {
    stream_debug("but already got %d bytes from buffer\n", total_read);
    return total_read;
  }

  errno = map_win32_err(err);
  return -1;
}
コード例 #4
0
ファイル: httpd-io.c プロジェクト: Oxyoptia/x3270
/**
 * Return the text for the most recent socket error.
 *
 * @return Error text
 */
static const char *
socket_errtext(void)
{
#if !defined(_WIN32) /*[*/
    return strerror(errno);
#else /*][*/
    return win32_strerror(GetLastError());
#endif /*]*/
}
コード例 #5
0
ファイル: stream_win.c プロジェクト: bitemyapp/watchman
static void CALLBACK write_completed(DWORD err, DWORD bytes,
    LPOVERLAPPED olap) {
  // Reverse engineer our handle from the olap pointer
  struct overlapped_op *op = (void*)olap;
  struct win_handle *h = op->h;
  struct write_buf *wbuf = op->wbuf;

  stream_debug("WriteFileEx: completion callback invoked: bytes=%d %s\n",
      (int)bytes, win32_strerror(err));

  EnterCriticalSection(&h->mtx);
  if (h->write_pending == op) {
    h->write_pending = NULL;
  }

  if (err == 0) {
    wbuf->cursor += bytes;
    wbuf->len -= bytes;

    if (wbuf->len == 0) {
      // Consumed this buffer
      free(wbuf);
    } else {
      w_log(W_LOG_FATAL, "WriteFileEx: short write: %d written, %d remain\n",
          bytes, wbuf->len);
    }
  } else {
    stream_debug("WriteFilex: completion: failed: %s\n",
        win32_strerror(err));
    h->errcode = err;
    h->error_pending = true;
    SetEvent(h->waitable);
  }

  // Send whatever else we have waiting to go
  initiate_write(h);

  LeaveCriticalSection(&h->mtx);

  // Free the prior struct after possibly initiating another write
  // to minimize the change of the same address being reused and
  // confusing the completion status
  free(op);
}
コード例 #6
0
ファイル: stream_win.c プロジェクト: bitemyapp/watchman
static int win_read_non_blocking(struct win_handle *h, char *buf, int size) {
  int total_read = 0;
  char *target;
  DWORD target_space;
  DWORD bytes;

  stream_debug("non_blocking read for %d bytes\n", size);

  move_from_read_buffer(h, &total_read, &buf, &size);

  target = h->read_cursor + h->read_avail;
  target_space = (DWORD)((h->read_buf + sizeof(h->read_buf)) - target);

  stream_debug("initiate read for %d\n", target_space);

  // Create a unique olap for each request
  h->read_pending = calloc(1, sizeof(*h->read_pending));
  if (h->read_avail == 0) {
    ResetEvent(h->waitable);
  }
  h->read_pending->olap.hEvent = h->waitable;
  h->read_pending->h = h;

  if (!ReadFile(h->h, target, target_space, &bytes, &h->read_pending->olap)) {
    DWORD err = GetLastError();

    if (err != ERROR_IO_PENDING) {
      free(h->read_pending);
      h->read_pending = NULL;

      stream_debug("olap read failed immediately: %s\n",
          win32_strerror(err));
    } else {
      stream_debug("olap read queued ok\n");
    }

    stream_debug("returning %d\n", total_read == 0 ? -1 : total_read);

    errno = map_win32_err(err);
    return total_read == 0 ? -1 : total_read;
  }

  stream_debug("olap read succeeded immediately!? bytes=%d\n", (int)bytes);

  // We don't expect this to succeed in the overlapped case,
  // but we can handle the result anyway
  h->read_avail += bytes;
  free(h->read_pending);
  h->read_pending = NULL;

  move_from_read_buffer(h, &total_read, &buf, &size);

  stream_debug("read returning %d\n", total_read);
  return total_read;
}
コード例 #7
0
ファイル: stream_win.c プロジェクト: bitemyapp/watchman
static bool win_read_handle_completion(struct win_handle *h) {
  BOOL olap_res;
  DWORD bytes, err;

  EnterCriticalSection(&h->mtx);
  if (!h->read_pending) {
    LeaveCriticalSection(&h->mtx);
    return false;
  }

  stream_debug("have read_pending, checking status\n");

  // Don't hold the mutex while we're blocked
  LeaveCriticalSection(&h->mtx);
  olap_res = get_overlapped_result_ex(h->h, &h->read_pending->olap, &bytes,
      h->blocking ? INFINITE : 0, true);
  err = GetLastError();
  EnterCriticalSection(&h->mtx);

  if (olap_res) {
    stream_debug("pending read completed, read %d bytes, %s\n",
        (int)bytes, win32_strerror(err));
    h->read_avail += bytes;
    free(h->read_pending);
    h->read_pending = NULL;
  } else {
    stream_debug("pending read failed: %s\n", win32_strerror(err));
    if (err != ERROR_IO_INCOMPLETE) {
      // Failed
      free(h->read_pending);
      h->read_pending = NULL;

      h->errcode = err;
      h->error_pending = true;
    }
  }
  LeaveCriticalSection(&h->mtx);

  return h->read_pending != NULL;
}
コード例 #8
0
ファイル: kernel_routes.c プロジェクト: brabander/olsr
/*
 * Remove a route from the kernel
 * @param destination the route to remove
 * @return negative on error
 */
int
os_route_del_rtentry(const struct rt_entry *rt, int ip_version)
{
  MIB_IPFORWARDROW Row;
  union olsr_ip_addr mask;
  unsigned long Res;
  struct interface *iface = rt->rt_nexthop.interface;

  if (AF_INET != ip_version) {
    /*
     * Not implemented
     */
    return -1;
  }

  OLSR_DEBUG(LOG_NETWORKING, "KERN: Deleting %s\n", olsr_rt_to_string(rt));

  memset(&Row, 0, sizeof(Row));

  Row.dwForwardDest = rt->rt_dst.prefix.v4.s_addr;

  if (!olsr_prefix_to_netmask(&mask, rt->rt_dst.prefix_len)) {
    return -1;
  }
  Row.dwForwardMask = mask.v4.s_addr;
  Row.dwForwardPolicy = 0;
  Row.dwForwardNextHop = rt->rt_nexthop.gateway.v4.s_addr;
  Row.dwForwardIfIndex = iface->if_index;
  // MIB_IPROUTE_TYPE_DIRECT and MIB_IPROUTE_TYPE_INDIRECT
  Row.dwForwardType = (rt->rt_dst.prefix.v4.s_addr == rt->rt_nexthop.gateway.v4.s_addr) ? 3 : 4;
  Row.dwForwardProto = 3;       // MIB_IPPROTO_NETMGMT
  Row.dwForwardAge = INFINITE;
  Row.dwForwardNextHopAS = 0;
  Row.dwForwardMetric1 = olsr_fib_metric(&rt->rt_metric);
  Row.dwForwardMetric2 = -1;
  Row.dwForwardMetric3 = -1;
  Row.dwForwardMetric4 = -1;
  Row.dwForwardMetric5 = -1;

  Res = DeleteIpForwardEntry(&Row);

  if (Res != NO_ERROR) {
    OLSR_WARN(LOG_NETWORKING, "DeleteIpForwardEntry() = %08lx, %s", Res, win32_strerror(Res));

    // XXX - report error in a different way

    errno = Res;

    return -1;
  }
  return 0;
}
コード例 #9
0
ファイル: stream_win.c プロジェクト: bitemyapp/watchman
static int win_write(w_stm_t stm, const void *buf, int size) {
  struct win_handle *h = stm->handle;
  struct write_buf *wbuf;

  EnterCriticalSection(&h->mtx);
  if (h->file_type != FILE_TYPE_PIPE && h->blocking && !h->write_head) {
    DWORD bytes;
    stream_debug("blocking write of %d\n", size);
    if (WriteFile(h->h, buf, size, &bytes, NULL)) {
      LeaveCriticalSection(&h->mtx);
      return bytes;
    }
    h->errcode = GetLastError();
    h->error_pending = true;
    errno = map_win32_err(h->errcode);
    SetEvent(h->waitable);
    stream_debug("write failed: %s\n", win32_strerror(h->errcode));
    LeaveCriticalSection(&h->mtx);
    return -1;
  }

  wbuf = malloc(sizeof(*wbuf) + size - 1);
  if (!wbuf) {
    return -1;
  }
  wbuf->next = NULL;
  wbuf->cursor = wbuf->data;
  wbuf->len = size;
  memcpy(wbuf->data, buf, size);

  if (h->write_tail) {
    h->write_tail->next = wbuf;
  } else {
    h->write_head = wbuf;
  }
  h->write_tail = wbuf;

  if (!h->write_pending) {
    initiate_write(h);
  }

  LeaveCriticalSection(&h->mtx);

  return size;
}
コード例 #10
0
ファイル: trace.c プロジェクト: Oxyoptia/x3270
/*
 * Start up a window to monitor the trace file.
 *
 * @param[in] path	Trace file path.
 */
static void
start_trace_window(const char *path)
{
    STARTUPINFO startupinfo;
    PROCESS_INFORMATION process_information;

    memset(&startupinfo, 0, sizeof(STARTUPINFO));
    startupinfo.cb = sizeof(STARTUPINFO);
    startupinfo.lpTitle = (char *)path;
    memset(&process_information, 0, sizeof(PROCESS_INFORMATION));
    if (CreateProcess(lazyaf("%scatf.exe", instdir),
		lazyaf("\"%scatf.exe\" \"%s\"", instdir, path),
		NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL,
		NULL, &startupinfo, &process_information) == 0) {
	popup_an_error("CreateProcess(%scatf.exe \"%s\") failed: %s", instdir,
		path, win32_strerror(GetLastError()));
    } else {
	tracewindow_handle = process_information.hProcess;
	CloseHandle(process_information.hThread);
    }
}
コード例 #11
0
ファイル: main.c プロジェクト: Jerry-goodboy/watchman
static const char *compute_user_name(void) {
  const char *user = get_env_with_fallback("USER", "LOGNAME", NULL);
#ifdef _WIN32
  static char user_buf[256];
#endif

  if (!user) {
#ifdef _WIN32
    DWORD size = sizeof(user_buf);
    if (GetUserName(user_buf, &size)) {
      user_buf[size] = 0;
      user = user_buf;
    } else {
      w_log(W_LOG_FATAL, "GetUserName failed: %s. I don't know who you are\n",
          win32_strerror(GetLastError()));
    }
#else
    uid_t uid = getuid();
    struct passwd *pw;

    pw = getpwuid(uid);
    if (!pw) {
      w_log(W_LOG_FATAL, "getpwuid(%d) failed: %s. I don't know who you are\n",
          uid, strerror(errno));
    }

    user = pw->pw_name;
#endif

    if (!user) {
      w_log(W_LOG_ERR, "watchman requires that you set $USER in your env\n");
      abort();
    }
  }

  return user;
}
コード例 #12
0
ファイル: main.c プロジェクト: noscripter/watchman
static void setup_sock_name(void)
{
  const char *user = get_env_with_fallback("USER", "LOGNAME", NULL);
#ifdef _WIN32
  char user_buf[256];
#endif

  watchman_tmp_dir = get_env_with_fallback("TMPDIR", "TMP", "/tmp");

  if (!user) {
#ifdef _WIN32
    DWORD size = sizeof(user_buf);
    if (GetUserName(user_buf, &size)) {
      user_buf[size] = 0;
      user = user_buf;
    } else {
      w_log(W_LOG_FATAL, "GetUserName failed: %s. I don't know who you are\n",
          win32_strerror(GetLastError()));
    }
#else
    uid_t uid = getuid();
    struct passwd *pw;

    pw = getpwuid(uid);
    if (!pw) {
      w_log(W_LOG_FATAL, "getpwuid(%d) failed: %s. I don't know who you are\n",
          uid, strerror(errno));
    }

    user = pw->pw_name;
#endif

    if (!user) {
      w_log(W_LOG_ERR, "watchman requires that you set $USER in your env\n");
      abort();
    }
  }

#ifdef _WIN32
  if (!sock_name) {
    asprintf(&sock_name, "\\\\.\\pipe\\watchman-%s", user);
  }
#else
  compute_file_name(&sock_name, user, "sock", "sockname");
#endif
  compute_file_name(&watchman_state_file, user, "state", "statefile");
  compute_file_name(&log_name, user, "log", "logname");
#ifdef USE_GIMLI
  compute_file_name(&pid_file, user, "pid", "pidfile");
#endif

#ifndef _WIN32
  un.sun_family = PF_LOCAL;
  strcpy(un.sun_path, sock_name);

  if (strlen(sock_name) >= sizeof(un.sun_path) - 1) {
    w_log(W_LOG_ERR, "%s: path is too long\n",
        sock_name);
    abort();
  }
#endif
}
コード例 #13
0
ファイル: win32.c プロジェクト: CedarLogic/watchman
static void *readchanges_thread(void *arg) {
  w_root_t *root = arg;
  struct winwatch_root_state *state = root->watch;
  DWORD size = WATCHMAN_BATCH_LIMIT * (sizeof(FILE_NOTIFY_INFORMATION) + 512);
  char *buf;
  DWORD err, filter;
  OVERLAPPED olap;
  BOOL initiate_read = true;
  HANDLE handles[2] = { state->olap, state->ping };
  DWORD bytes;

  w_set_thread_name("readchange %.*s",
      root->root_path->len, root->root_path->buf);

  // Block until winmatch_root_st is waiting for our initialization
  pthread_mutex_lock(&state->mtx);

  filter = FILE_NOTIFY_CHANGE_FILE_NAME|FILE_NOTIFY_CHANGE_DIR_NAME|
    FILE_NOTIFY_CHANGE_ATTRIBUTES|FILE_NOTIFY_CHANGE_SIZE|
    FILE_NOTIFY_CHANGE_LAST_WRITE;

  memset(&olap, 0, sizeof(olap));
  olap.hEvent = state->olap;

  buf = malloc(size);
  if (!buf) {
    w_log(W_LOG_ERR, "failed to allocate %u bytes for dirchanges buf\n", size);
    goto out;
  }

  if (!ReadDirectoryChangesW(state->dir_handle, buf, size,
        TRUE, filter, NULL, &olap, NULL)) {
    err = GetLastError();
    w_log(W_LOG_ERR,
        "ReadDirectoryChangesW: failed, cancel watch. %s\n",
        win32_strerror(err));
    w_root_lock(root);
    w_root_cancel(root);
    w_root_unlock(root);
    goto out;
  }
  // Signal that we are done with init.  We MUST do this AFTER our first
  // successful ReadDirectoryChangesW, otherwise there is a race condition
  // where we'll miss observing the cookie for a query that comes in
  // after we've crawled but before the watch is established.
  w_log(W_LOG_DBG, "ReadDirectoryChangesW signalling as init done");
  pthread_cond_signal(&state->cond);
  pthread_mutex_unlock(&state->mtx);
  initiate_read = false;

  // The state->mutex must not be held when we enter the loop
  while (!root->cancelled) {
    if (initiate_read) {
      if (!ReadDirectoryChangesW(state->dir_handle,
            buf, size, TRUE, filter, NULL, &olap, NULL)) {
        err = GetLastError();
        w_log(W_LOG_ERR,
            "ReadDirectoryChangesW: failed, cancel watch. %s\n",
            win32_strerror(err));
        w_root_lock(root);
        w_root_cancel(root);
        w_root_unlock(root);
        break;
      } else {
        initiate_read = false;
      }
    }

    w_log(W_LOG_DBG, "waiting for change notifications");
    DWORD status = WaitForMultipleObjects(2, handles, FALSE, INFINITE);

    if (status == WAIT_OBJECT_0) {
      bytes = 0;
      if (!GetOverlappedResult(state->dir_handle, &olap,
            &bytes, FALSE)) {
        err = GetLastError();
        w_log(W_LOG_ERR, "overlapped ReadDirectoryChangesW(%s): 0x%x %s\n",
            root->root_path->buf,
            err, win32_strerror(err));

        if (err == ERROR_INVALID_PARAMETER && size > NETWORK_BUF_SIZE) {
          // May be a network buffer related size issue; the docs say that
          // we can hit this when watching a UNC path. Let's downsize and
          // retry the read just one time
          w_log(W_LOG_ERR, "retrying watch for possible network location %s "
              "with smaller buffer\n", root->root_path->buf);
          size = NETWORK_BUF_SIZE;
          initiate_read = true;
          continue;
        }

        if (err == ERROR_NOTIFY_ENUM_DIR) {
          w_root_schedule_recrawl(root, "ERROR_NOTIFY_ENUM_DIR");
        } else {
          w_log(W_LOG_ERR, "Cancelling watch for %s\n",
              root->root_path->buf);
          w_root_lock(root);
          w_root_cancel(root);
          w_root_unlock(root);
          break;
        }
      } else {
        PFILE_NOTIFY_INFORMATION not = (PFILE_NOTIFY_INFORMATION)buf;
        struct winwatch_changed_item *head = NULL, *tail = NULL;
        while (true) {
          struct winwatch_changed_item *item;
          DWORD n_chars;
          w_string_t *name, *full;

          // FileNameLength is in BYTES, but FileName is WCHAR
          n_chars = not->FileNameLength / sizeof(not->FileName[0]);
          name = w_string_new_wchar(not->FileName, n_chars);

          full = w_string_path_cat(root->root_path, name);
          w_string_delref(name);

          if (w_is_ignored(root, full->buf, full->len)) {
            w_string_delref(full);
          } else {
            item = calloc(1, sizeof(*item));
            item->name = full;

            if (tail) {
              tail->next = item;
            } else {
              head = item;
            }
            tail = item;
          }

          // Advance to next item
          if (not->NextEntryOffset == 0) {
            break;
          }
          not = (PFILE_NOTIFY_INFORMATION)(not->NextEntryOffset + (char*)not);
        }

        if (tail) {
          pthread_mutex_lock(&state->mtx);
          if (state->tail) {
            state->tail->next = head;
          } else {
            state->head = head;
          }
          state->tail = tail;
          pthread_mutex_unlock(&state->mtx);
          pthread_cond_signal(&state->cond);
        }
        ResetEvent(state->olap);
        initiate_read = true;
      }
    } else if (status == WAIT_OBJECT_0 + 1) {
      w_log(W_LOG_ERR, "signalled\n");
      break;
    } else {
      w_log(W_LOG_ERR, "impossible wait status=%d\n",
          status);
      break;
    }
  }

  pthread_mutex_lock(&state->mtx);
out:
  // Signal to winwatch_root_start that we're done initializing in
  // the failure path.  We'll also do this after we've completed
  // the run loop in the success path; it's a spurious wakeup but
  // harmless and saves us from adding and setting a control flag
  // in each of the failure `goto` statements. winwatch_root_dtor
  // will `pthread_join` us before `state` is freed.
  pthread_cond_signal(&state->cond);
  pthread_mutex_unlock(&state->mtx);

  if (buf) {
    free(buf);
  }
  w_log(W_LOG_DBG, "done\n");
  w_root_delref(root);
  return NULL;
}
コード例 #14
0
ファイル: gdi_print.c プロジェクト: Oxyoptia/x3270
/*
 * Initalize the named GDI printer. If the name is NULL, use the default
 * printer.
 */
static gdi_status_t
gdi_init(const char *printer_name, unsigned opts, const char **fail)
{
    char *default_printer_name;
    LPDEVMODE devmode;
    HDC dc;
    DOCINFO docinfo;
    DEVNAMES *devnames;
    int rmargin, bmargin; /* right margin, bottom margin */
    int maxphmargin, maxpvmargin;
    int i;
    static char get_fail[1024];
    int fheight, fwidth;

    memset(&pstate.dlg, '\0', sizeof(pstate.dlg));
    pstate.dlg.lStructSize = sizeof(pstate.dlg);
    pstate.dlg.Flags = PD_RETURNDC | PD_NOPAGENUMS | PD_HIDEPRINTTOFILE |
	PD_NOSELECTION;

    if (printer_name == NULL || !*printer_name) {
	default_printer_name = get_default_printer_name(get_fail,
		sizeof(get_fail));
	if (default_printer_name == NULL) {
	    *fail = get_fail;
	    goto failed;
	}
	printer_name = default_printer_name;
    }
    if (!get_printer_device(printer_name, &pstate.dlg.hDevNames,
		&pstate.dlg.hDevMode)) {
	snprintf(get_fail, sizeof(get_fail),
		"GetPrinter(%s) failed: %s",
		printer_name, win32_strerror(GetLastError()));
	*fail = get_fail;
	goto failed;
    }
    if (uparm.orientation) {
	devmode = (LPDEVMODE)GlobalLock(pstate.dlg.hDevMode);
	devmode->dmFields |= DM_ORIENTATION;
	devmode->dmOrientation = uparm.orientation;
	GlobalUnlock(devmode);
    }

    if (opts & FPS_NO_DIALOG) {
	/* They don't want the print dialog. Allocate a DC for it. */
	devmode = (LPDEVMODE)GlobalLock(pstate.dlg.hDevMode);
	pstate.dlg.hDC = CreateDC("WINSPOOL", printer_name, NULL, devmode);
	GlobalUnlock(devmode);
	if (pstate.dlg.hDC == NULL) {
	    snprintf(get_fail, sizeof(get_fail), "Cannot create DC for "
		    "printer '%s'", printer_name);
	    *fail = get_fail;
	    goto failed;
	}
    } else {
	if (default_printer_name != NULL) {
	    Free(default_printer_name);
	    default_printer_name = NULL;
	}

	/* Pop up the dialog to get the printer characteristics. */
	if (!PrintDlg(&pstate.dlg)) {
	    return GDI_STATUS_CANCEL;
	}
    }
    dc = pstate.dlg.hDC;

    if (default_printer_name != NULL) {
	Free(default_printer_name);
	default_printer_name = NULL;
    }

    /* Find out the printer characteristics. */

    /* LOGPIXELSX and LOGPIXELSY are the pixels-per-inch for the printer. */
    pchar.ppiX = GetDeviceCaps(dc, LOGPIXELSX);
    if (pchar.ppiX <= 0) {
	*fail = "Can't get LOGPIXELSX";
	goto failed;
    }
    pchar.ppiY = GetDeviceCaps(dc, LOGPIXELSY);
    if (pchar.ppiY <= 0) {
	*fail = "Can't get LOGPIXELSY";
	goto failed;
    }

    /*
     * PHYSICALOFFSETX and PHYSICALOFFSETY are the fixed top and left-hand
     * margins, in pixels. Whatever you print is offset by these amounts, so
     * you have to subtract them from your coordinates. You cannot print in
     * these areas.
     */
    pchar.poffX = GetDeviceCaps(dc, PHYSICALOFFSETX);
    if (pchar.poffX < 0) {
	*fail = "Can't get PHYSICALOFFSETX";
	goto failed;
    }
    pchar.poffY = GetDeviceCaps(dc, PHYSICALOFFSETY);
    if (pchar.poffY < 0) {
	*fail = "Can't get PHYSICALOFFSETY";
	goto failed;
    }

    /*
     * HORZRES and VERTRES are the size of the usable area of the page, in
     * pixels. They implicitly give you the size of the right-hand and
     * bottom physical offsets.
     */
    pchar.horzres = GetDeviceCaps(dc, HORZRES);
    if (pchar.horzres <= 0) {
	*fail = "Can't get HORZRES";
	goto failed;
    }
    pchar.vertres = GetDeviceCaps(dc, VERTRES);
    if (pchar.vertres <= 0) {
	*fail = "Can't get VERTRES";
	goto failed;
    }

    /*
     * PHYSICALWIDTH and PHYSICALHEIGHT are the size of the entire area of
     * the page, in pixels.
     */
    pchar.pwidth = GetDeviceCaps(dc, PHYSICALWIDTH);
    if (pchar.pwidth <= 0) {
	*fail = "Can't get PHYSICALWIDTH";
	goto failed;
    }
    pchar.pheight = GetDeviceCaps(dc, PHYSICALHEIGHT);
    if (pchar.pheight <= 0) {
	*fail = "Can't get PHYSICALHEIGHT";
	goto failed;
    }

    /* Trace the device characteristics. */
    devnames = (DEVNAMES *)GlobalLock(pstate.dlg.hDevNames);
    vtrace("[gdi] Printer '%s' capabilities:\n",
	    (char *)devnames + devnames->wDeviceOffset);
    GlobalUnlock(devnames);
    vtrace("[gdi]  LOGPIXELSX %d LOGPIXELSY %d\n",
	    pchar.ppiX, pchar.ppiY);
    vtrace("[gdi]  PHYSICALOFFSETX %d PHYSICALOFFSETY %d\n",
	    pchar.poffX, pchar.poffY);
    vtrace("[gdi]  HORZRES %d VERTRES %d\n",
	    pchar.horzres, pchar.vertres);
    vtrace("[gdi]  PHYSICALWIDTH %d PHYSICALHEIGHT %d\n",
	    pchar.pwidth, pchar.pheight);

    /* Compute the scale factors (points to pixels). */
    pstate.xptscale = (FLOAT)pchar.ppiX / (FLOAT)PPI;
    pstate.yptscale = (FLOAT)pchar.ppiY / (FLOAT)PPI;

    /* Compute the implied right and bottom margins. */
    rmargin = pchar.pwidth - pchar.horzres - pchar.poffX;
    bmargin = pchar.pheight - pchar.vertres - pchar.poffY;
    if (rmargin > pchar.poffX) {
	maxphmargin = rmargin;
    } else {
	maxphmargin = pchar.poffX;
    }
    if (bmargin > pchar.poffY) {
	maxpvmargin = bmargin;
    } else {
	maxpvmargin = pchar.poffY;
    }
    vtrace("[gdi] maxphmargin is %d, maxpvmargin is %d pixels\n",
	    maxphmargin, maxpvmargin);

    /* Compute the margins in pixels. */
    pstate.hmargin_pixels = (int)(uparm.hmargin * pchar.ppiX);
    pstate.vmargin_pixels = (int)(uparm.vmargin * pchar.ppiY);

    /* See if the margins are too small. */
    if (pstate.hmargin_pixels < maxphmargin) {
	pstate.hmargin_pixels = maxphmargin;
	vtrace("[gdi] hmargin is too small, setting to %g\"\n",
		(float)pstate.hmargin_pixels / pchar.ppiX);
    }
    if (pstate.vmargin_pixels < maxpvmargin) {
	pstate.vmargin_pixels = maxpvmargin;
	vtrace("[gdi] vmargin is too small, setting to %g\"\n",
		(float)pstate.vmargin_pixels / pchar.ppiX);
    }

    /* See if the margins are too big. */
    if (pstate.hmargin_pixels * 2 >= pchar.horzres) {
	pstate.hmargin_pixels = pchar.ppiX;
	vtrace("[gdi] hmargin is too big, setting to 1\"\n");
    }
    if (pstate.vmargin_pixels * 2 >= pchar.vertres) {
	pstate.vmargin_pixels = pchar.ppiY;
	vtrace("[gdi] vmargin is too big, setting to 1\"\n");
    }

    /*
     * Compute the usable area in pixels. That's the physical page size
     * less the margins, now that we know that the margins are reasonable.
     */
    pstate.usable_xpixels = pchar.pwidth - (2 * pstate.hmargin_pixels);
    pstate.usable_ypixels = pchar.pheight - (2 * pstate.vmargin_pixels);
    vtrace("[gdi] usable area is %dx%d pixels\n",
	    pstate.usable_xpixels, pstate.usable_ypixels);

    /*
     * Create the Roman font.
     *
     * If they specified a particular font size, use that as the height,
     * and let the system pick the width.
     *
     * If they did not specify a font size, or chose "auto", then let the
     * "screens per page" drive what to do. If "screens per page" is set,
     * then divide the page Y pixels by the screens-per-page times the
     * display height to get the font height, and let the system pick the
     * width.
     *
     * Otherwise, divide the page X pixels by COLS to get the font width,
     * and let the system pick the height.
     */
    if (uparm.font_size) {
	/* User-specified fixed font size. */
	fheight = (int)(uparm.font_size * pstate.yptscale);
	fwidth = 0;
    } else {
	if (uparm.spp > 1) {
	    /*
	     * Scale the height so the specified number of screens will
	     * fit.
	     */
	    fheight = pstate.usable_ypixels /
		(uparm.spp * maxROWS /* spp screens */
		 + (uparm.spp - 1) /* spaces between screens */
		 + 2 /* space and caption*/ );
	    fwidth = 0;
	} else {
	    /*
	     * Scale the width so a screen will fit the page horizonally.
	     */
	    fheight = 0;
	    fwidth = pstate.usable_xpixels / maxCOLS;
	}
    }
    if (create_roman_font(dc, fheight, fwidth, fail) < 0) {
	goto failed;
    }

    /*
     * If we computed the font size, see if the other dimension is too
     * big. If it is, scale using the other dimension, which is guaranteed to
     * make the original computed dimension no bigger.
     *
     * XXX: This needs more testing.
     */
    if (!uparm.font_size) {
	if (fwidth == 0) {
	    /*
	     * We computed the height because spp > 1. See if the width
	     * overflows.
	     */
	    if (pstate.space_size.cx * maxCOLS > pstate.usable_xpixels) {
		vtrace("[gdi] font too wide, retrying\n");
		DeleteObject(pstate.font);
		pstate.font = NULL;

		fheight = 0;
		fwidth = pstate.usable_xpixels / maxCOLS;
		if (create_roman_font(dc, fheight, fwidth, fail) < 0) {
		    goto failed;
		}
	    }
	} else if (fheight == 0) {
	    /*
	     * We computed the width (spp <= 1). See if the height
	     * overflows.
	     */
	    if (pstate.space_size.cy * (maxROWS + 2) >
		    pstate.usable_xpixels) {
		vtrace("[gdi] font too high, retrying\n");
		DeleteObject(pstate.font);
		pstate.font = NULL;

		fheight = pstate.usable_xpixels / (maxROWS + 2);
		fwidth = 0;
		if (create_roman_font(dc, fheight, fwidth, fail) < 0) {
		    goto failed;
		}
	    }
	}
    }

    /* Create a bold font that is the same size, if possible. */
    pstate.bold_font = CreateFont(
	    pstate.space_size.cy,	/* height */
	    pstate.space_size.cx,	/* width */
	    0,			/* escapement */
	    0,			/* orientation */
	    FW_BOLD,		/* weight */
	    FALSE,			/* italic */
	    FALSE,			/* underline */
	    FALSE,			/* strikeout */
	    ANSI_CHARSET,		/* character set */
	    OUT_OUTLINE_PRECIS,	/* output precision */
	    CLIP_DEFAULT_PRECIS,	/* clip precision */
	    DEFAULT_QUALITY,	/* quality */
	    FIXED_PITCH|FF_DONTCARE,/* pitch and family */
	    uparm.font_name);	/* face */
    if (pstate.bold_font == NULL) {
	*fail = "CreateFont (bold) failed";
	goto failed;
    }

    /* Create an underscore font that is the same size, if possible. */
    pstate.underscore_font = CreateFont(
	    pstate.space_size.cy,	/* height */
	    pstate.space_size.cx,	/* width */
	    0,			/* escapement */
	    0,			/* orientation */
	    FW_NORMAL,		/* weight */
	    FALSE,			/* italic */
	    TRUE,			/* underline */
	    FALSE,			/* strikeout */
	    ANSI_CHARSET,		/* character set */
	    OUT_OUTLINE_PRECIS,	/* output precision */
	    CLIP_DEFAULT_PRECIS,	/* clip precision */
	    DEFAULT_QUALITY,	/* quality */
	    FIXED_PITCH|FF_DONTCARE,/* pitch and family */
	    uparm.font_name);	/* face */
    if (pstate.underscore_font == NULL) {
	*fail = "CreateFont (underscore) failed";
	goto failed;
    }

    /* Create a bold, underscore font that is the same size, if possible. */
    pstate.bold_underscore_font = CreateFont(
	    pstate.space_size.cy,	/* height */
	    pstate.space_size.cx,	/* width */
	    0,			/* escapement */
	    0,			/* orientation */
	    FW_BOLD,		/* weight */
	    FALSE,			/* italic */
	    TRUE,			/* underline */
	    FALSE,			/* strikeout */
	    ANSI_CHARSET,		/* character set */
	    OUT_OUTLINE_PRECIS,	/* output precision */
	    CLIP_DEFAULT_PRECIS,	/* clip precision */
	    DEFAULT_QUALITY,	/* quality */
	    FIXED_PITCH|FF_DONTCARE,/* pitch and family */
	    uparm.font_name);	/* face */
    if (pstate.bold_underscore_font == NULL) {
	*fail = "CreateFont (bold underscore) failed";
	goto failed;
    }

    /* Create a caption font. */
    pstate.caption_font = CreateFont(
	    pstate.space_size.cy,	/* height */
	    0,			/* width */
	    0,			/* escapement */
	    0,			/* orientation */
	    FW_NORMAL,		/* weight */
	    TRUE,			/* italic */
	    FALSE,			/* underline */
	    FALSE,			/* strikeout */
	    ANSI_CHARSET,		/* character set */
	    OUT_OUTLINE_PRECIS,	/* output precision */
	    CLIP_DEFAULT_PRECIS,	/* clip precision */
	    DEFAULT_QUALITY,	/* quality */
	    VARIABLE_PITCH|FF_DONTCARE,/* pitch and family */
	    "Times New Roman");	/* face */
    if (pstate.bold_underscore_font == NULL) {
	*fail = "CreateFont (bold underscore) failed";
	goto failed;
    }

    /* Set up the manual spacing array. */
    pstate.dx = Malloc(sizeof(INT) * maxCOLS);
    for (i = 0; i < maxCOLS; i++) {
	pstate.dx[i] = pstate.space_size.cx;
    }

    /* Fill in the document info. */
    memset(&docinfo, '\0', sizeof(docinfo));
    docinfo.cbSize = sizeof(docinfo);
    docinfo.lpszDocName = "wc3270 screen";

    /* Start the document. */
    if (StartDoc(dc, &docinfo) <= 0) {
	*fail = "StartDoc failed";
	goto failed;
    }

    return GDI_STATUS_SUCCESS;

failed:
    /* Clean up what we can and return failure. */
    if (default_printer_name != NULL) {
	Free(default_printer_name);
    }
    cleanup_fonts();
    return GDI_STATUS_ERROR;
}
コード例 #15
0
ファイル: posix_spawn.c プロジェクト: kevinsawicki/watchman
static int posix_spawn_common(
    bool search_path,
    pid_t *pid, const char *path,
    const posix_spawn_file_actions_t *file_actions,
    const posix_spawnattr_t *attrp,
    char *const argv[], char *const envp[]) {
  STARTUPINFO sinfo;
  SECURITY_ATTRIBUTES sec;
  PROCESS_INFORMATION pinfo;
  char *cmdbuf;
  char *env_block;
  DWORD create_flags = CREATE_NO_WINDOW;
  int ret;
  int i;
  unused_parameter(envp); // FIXME

  cmdbuf = build_command_line(argv);
  if (!cmdbuf) {
    return ENOMEM;
  }

  env_block = make_env_block(envp);
  if (!env_block) {
    free(cmdbuf);
    return ENOMEM;
  }

  memset(&sinfo, 0, sizeof(sinfo));
  sinfo.cb = sizeof(sinfo);
  sinfo.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
  sinfo.wShowWindow = SW_HIDE;

  memset(&sec, 0, sizeof(sec));
  sec.nLength = sizeof(sec);
  sec.bInheritHandle = TRUE;

  memset(&pinfo, 0, sizeof(pinfo));

  if (attrp->flags & POSIX_SPAWN_SETPGROUP) {
    create_flags |= CREATE_NEW_PROCESS_GROUP;
  }

  // Process any dup(2) actions
  for (i = 0; i < file_actions->ndups; i++) {
    struct _posix_spawn_file_dup *dup = &file_actions->dups[i];
    HANDLE *target = NULL;
    DWORD err;

    switch (dup->target_fd) {
      case 0:
        target = &sinfo.hStdInput;
        break;
      case 1:
        target = &sinfo.hStdOutput;
        break;
      case 2:
        target = &sinfo.hStdError;
        break;
    }

    if (!target) {
      w_log(W_LOG_ERR, "posix_spawn: can't target fd outside range [0-2]\n");
      ret = ENOSYS;
      goto done;
    }

    if (*target) {
      CloseHandle(*target);
      *target = INVALID_HANDLE_VALUE;
    }

    if (!DuplicateHandle(GetCurrentProcess(), dup->local_handle,
          GetCurrentProcess(), target, 0,
          TRUE, DUPLICATE_SAME_ACCESS)) {
      err = GetLastError();
      w_log(W_LOG_ERR, "posix_spawn: failed to duplicate handle: %s\n",
          win32_strerror(err));
      ret = map_win32_err(err);
      goto done;
    }
  }

  // Process any file opening actions
  for (i = 0; i < file_actions->nopens; i++) {
    struct _posix_spawn_file_open *op = &file_actions->opens[i];
    HANDLE h;
    HANDLE *target = NULL;

    switch (op->target_fd) {
      case 0:
        target = &sinfo.hStdInput;
        break;
      case 1:
        target = &sinfo.hStdOutput;
        break;
      case 2:
        target = &sinfo.hStdError;
        break;
    }

    if (!target) {
      w_log(W_LOG_ERR, "posix_spawn: can't target fd outside range [0-2]\n");
      ret = ENOSYS;
      goto done;
    }

    h = w_handle_open(op->name, op->flags & ~O_CLOEXEC);
    if (h == INVALID_HANDLE_VALUE) {
      ret = errno;
      w_log(W_LOG_ERR, "posix_spawn: failed to open %s:\n",
          op->name);
      goto done;
    }

    if (*target) {
      CloseHandle(*target);
    }
    *target = h;
  }

  if (!sinfo.hStdInput) {
    sinfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
  }
  if (!sinfo.hStdOutput) {
    sinfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
  }
  if (!sinfo.hStdError) {
    sinfo.hStdError = GetStdHandle(STD_ERROR_HANDLE);
  }

  if (!CreateProcess(search_path ? NULL : path,
        cmdbuf, &sec, &sec, TRUE, create_flags, env_block,
        attrp->working_dir, &sinfo, &pinfo)) {
    w_log(W_LOG_ERR, "CreateProcess: `%s`: (cwd=%s) %s\n", cmdbuf,
        attrp->working_dir ? attrp->working_dir : "<process cwd>",
        win32_strerror(GetLastError()));
    ret = EACCES;
  } else {
    *pid = (pid_t)pinfo.dwProcessId;

    // Record the pid -> handle mapping for later wait/reap
    pthread_mutex_lock(&child_proc_lock);
    if (!child_procs) {
      child_procs = w_ht_new(2, NULL);
    }
    w_ht_set(child_procs, pinfo.dwProcessId, w_ht_ptr_val(pinfo.hProcess));
    pthread_mutex_unlock(&child_proc_lock);

    CloseHandle(pinfo.hThread);
    ret = 0;
  }

done:
  free(cmdbuf);
  free(env_block);

  // If we manufactured any handles, close them out now
  if (sinfo.hStdInput != GetStdHandle(STD_INPUT_HANDLE)) {
    CloseHandle(sinfo.hStdInput);
  }
  if (sinfo.hStdOutput != GetStdHandle(STD_OUTPUT_HANDLE)) {
    CloseHandle(sinfo.hStdOutput);
  }
  if (sinfo.hStdError != GetStdHandle(STD_ERROR_HANDLE)) {
    CloseHandle(sinfo.hStdError);
  }

  return ret;
}
コード例 #16
0
ファイル: stat.c プロジェクト: kwlzn/watchman
int lstat(const char *path, struct stat *st) {
  FILE_BASIC_INFO binfo;
  FILE_STANDARD_INFO sinfo;
  WCHAR *wpath = w_utf8_to_win_unc(path, -1);
  HANDLE h;
  DWORD err;

  memset(st, 0, sizeof(*st));

  if (!wpath) {
    return -1;
  }

  h = CreateFileW(wpath, FILE_READ_ATTRIBUTES,
        FILE_SHARE_DELETE|FILE_SHARE_READ|FILE_SHARE_WRITE,
        NULL,
        OPEN_EXISTING,
        FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS,
        NULL);
  err = GetLastError();
  free(wpath);

  if (h == INVALID_HANDLE_VALUE) {
    w_log(W_LOG_DBG, "lstat(%s): %s\n", path, win32_strerror(err));
    errno = map_win32_err(err);
    return -1;
  }

  if (path[1] == ':') {
    int drive_letter = tolower(path[0]);
    st->st_rdev = st->st_dev = drive_letter - 'a';
  }

  if (GetFileInformationByHandleEx(h, FileBasicInfo, &binfo, sizeof(binfo))) {
    FILETIME_LARGE_INTEGER_to_timespec(binfo.CreationTime, &st->st_ctim);
    st->st_ctime = st->st_ctim.tv_sec;
    FILETIME_LARGE_INTEGER_to_timespec(binfo.LastAccessTime, &st->st_atim);
    st->st_atime = st->st_atim.tv_sec;
    FILETIME_LARGE_INTEGER_to_timespec(binfo.LastWriteTime, &st->st_mtim);
    st->st_mtime = st->st_mtim.tv_sec;

    if (binfo.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
      // This is a symlink, but msvcrt has no way to indicate that.
      // We'll treat it as a regular file until we have a better
      // representation :-/
      st->st_mode = _S_IFREG;
    } else if (binfo.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
      st->st_mode |= _S_IFDIR|S_IEXEC|S_IXGRP|S_IXOTH;
    } else {
      st->st_mode |= _S_IFREG;
    }
    if (binfo.FileAttributes & FILE_ATTRIBUTE_READONLY) {
      st->st_mode |= 0444;
    } else {
      st->st_mode |= 0666;
    }
  }

  if (GetFileInformationByHandleEx(h, FileStandardInfo,
        &sinfo, sizeof(sinfo))) {
    st->st_size = sinfo.EndOfFile.QuadPart;
    st->st_nlink = sinfo.NumberOfLinks;
  }

  CloseHandle(h);

  return 0;
}
コード例 #17
0
ファイル: listener.c プロジェクト: kwlzn/watchman
static void named_pipe_accept_loop(const char *path) {
  HANDLE handles[2];
  OVERLAPPED olap;
  HANDLE connected_event = CreateEvent(NULL, FALSE, TRUE, NULL);

  if (!connected_event) {
    w_log(W_LOG_ERR, "named_pipe_accept_loop: CreateEvent failed: %s\n",
        win32_strerror(GetLastError()));
    return;
  }

  listener_thread_event = CreateEvent(NULL, FALSE, TRUE, NULL);

  handles[0] = connected_event;
  handles[1] = listener_thread_event;
  memset(&olap, 0, sizeof(olap));
  olap.hEvent = connected_event;

  w_log(W_LOG_ERR, "waiting for pipe clients on %s\n", path);
  while (!stopping) {
    w_stm_t stm;
    HANDLE client_fd;
    DWORD res;

    client_fd = CreateNamedPipe(
        path,
        PIPE_ACCESS_DUPLEX|FILE_FLAG_OVERLAPPED,
        PIPE_TYPE_BYTE|PIPE_READMODE_BYTE|
        PIPE_REJECT_REMOTE_CLIENTS,
        PIPE_UNLIMITED_INSTANCES,
        WATCHMAN_IO_BUF_SIZE,
        512, 0, NULL);

    if (client_fd == INVALID_HANDLE_VALUE) {
      w_log(W_LOG_ERR, "CreateNamedPipe(%s) failed: %s\n",
          path, win32_strerror(GetLastError()));
      continue;
    }

    ResetEvent(connected_event);
    if (!ConnectNamedPipe(client_fd, &olap)) {
      res = GetLastError();

      if (res == ERROR_PIPE_CONNECTED) {
        goto good_client;
      }

      if (res != ERROR_IO_PENDING) {
        w_log(W_LOG_ERR, "ConnectNamedPipe: %s\n",
            win32_strerror(GetLastError()));
        CloseHandle(client_fd);
        continue;
      }

      res = WaitForMultipleObjectsEx(2, handles, false, INFINITE, true);
      if (res == WAIT_OBJECT_0 + 1) {
        // Signalled to stop
        CancelIoEx(client_fd, &olap);
        CloseHandle(client_fd);
        continue;
      }

      if (res == WAIT_OBJECT_0) {
        goto good_client;
      }

      w_log(W_LOG_ERR, "WaitForMultipleObjectsEx: ConnectNamedPipe: "
          "unexpected status %u\n", res);
      CancelIoEx(client_fd, &olap);
      CloseHandle(client_fd);
    } else {
good_client:
      stm = w_stm_handleopen(client_fd);
      if (!stm) {
        w_log(W_LOG_ERR, "Failed to allocate stm for pipe handle: %s\n",
            strerror(errno));
        CloseHandle(client_fd);
        continue;
      }

      make_new_client(stm);
    }
  }
}
コード例 #18
0
ファイル: trace_ds.c プロジェクト: hharte/c3270
/* Callback for "OK" button on trace popup */
static void
tracefile_callback(Widget w, XtPointer client_data, XtPointer call_data _is_unused)
{
	char *tfn = CN;
	int devfd = -1;
#if defined(X3270_DISPLAY) /*[*/
	int pipefd[2];
	Boolean just_piped = False;
#endif /*]*/
	char *buf;

#if defined(X3270_DISPLAY) /*[*/
	if (w)
		tfn = XawDialogGetValueString((Widget)client_data);
	else
#endif /*]*/
		tfn = (char *)client_data;
	tfn = do_subst(tfn, DS_VARS | DS_TILDE | DS_UNIQUE);
	if (strchr(tfn, '\'') ||
	    ((int)strlen(tfn) > 0 && tfn[strlen(tfn)-1] == '\\')) {
		popup_an_error("Illegal file name: %s", tfn);
		Free(tfn);
		goto done;
	}

	tracef_max = 0;

	if (!strcmp(tfn, "stdout")) {
		tracef = stdout;
	} else {
#if defined(X3270_DISPLAY) /*[*/
		FILE *pipefile = NULL;

		if (!strcmp(tfn, "none") || !tfn[0]) {
			just_piped = True;
			if (!appres.trace_monitor) {
				popup_an_error("Must specify a trace file "
				    "name");
				free(tfn);
				goto done;
			}
		}

		if (appres.trace_monitor) {
			if (pipe(pipefd) < 0) {
				popup_an_errno(errno, "pipe() failed");
				Free(tfn);
				goto done;
			}
			pipefile = fdopen(pipefd[1], "w");
			if (pipefile == NULL) {
				popup_an_errno(errno, "fdopen() failed");
				(void) close(pipefd[0]);
				(void) close(pipefd[1]);
				Free(tfn);
				goto done;
			}
			(void) SETLINEBUF(pipefile);
			(void) fcntl(pipefd[1], F_SETFD, 1);
		}

		if (just_piped) {
			tracef = pipefile;
		} else
#endif /*]*/
		{
		    	Boolean append = False;

#if defined(X3270_DISPLAY) /*[*/
			tracef_pipe = pipefile;
#endif /*]*/
			/* Get the trace file maximum. */
			get_tracef_max();

			/* Open and configure the file. */
			if ((devfd = get_devfd(tfn)) >= 0)
				tracef = fdopen(dup(devfd), "a");
			else if (!strncmp(tfn, ">>", 2)) {
			    	append = True;
				tracef = fopen(tfn + 2, "a");
			} else
				tracef = fopen(tfn, "w");
			if (tracef == (FILE *)NULL) {
				popup_an_errno(errno, "%s", tfn);
#if defined(X3270_DISPLAY) /*[*/
				fclose(tracef_pipe);
				(void) close(pipefd[0]);
				(void) close(pipefd[1]);
#endif /*]*/
				Free(tfn);
				goto done;
			}
			tracef_size = ftello(tracef);
			Replace(tracefile_name,
				NewString(append? tfn + 2: tfn));
			(void) SETLINEBUF(tracef);
#if !defined(_WIN32) /*[*/
			(void) fcntl(fileno(tracef), F_SETFD, 1);
#endif /*]*/
		}
	}

#if defined(X3270_DISPLAY) /*[*/
	/* Start the monitor window */
	if (tracef != stdout && appres.trace_monitor) {
		switch (tracewindow_pid = fork_child()) {
		    case 0:	/* child process */
			{
				char cmd[64];

				(void) snprintf(cmd, sizeof(cmd), "cat <&%d",
					pipefd[0]);
				(void) execlp("xterm", "xterm",
				    "-title", just_piped? "trace": tfn,
				    "-sb", "-e", "/bin/sh", "-c",
				    cmd, CN);
			}
			(void) perror("exec(xterm) failed");
			_exit(1);
		    default:	/* parent */
			(void) close(pipefd[0]);
			++children;
			break;
		    case -1:	/* error */
			popup_an_errno(errno, "fork() failed");
			break;
		}
	}
#endif /*]*/

#if defined(_WIN32) && defined(C3270) /*[*/
	/* Start the monitor window. */
	if (tracef != stdout && appres.trace_monitor && is_installed) {
		STARTUPINFO startupinfo;
		PROCESS_INFORMATION process_information;
		char *path;
		char *args;

	    	(void) memset(&startupinfo, '\0', sizeof(STARTUPINFO));
		startupinfo.cb = sizeof(STARTUPINFO);
		startupinfo.lpTitle = tfn;
		(void) memset(&process_information, '\0',
			      sizeof(PROCESS_INFORMATION));
		path = xs_buffer("%scatf.exe", instdir);
		args = xs_buffer("\"%scatf.exe\" \"%s\"", instdir, tfn);
		if (CreateProcess(
		    path,
		    args,
		    NULL,
		    NULL,
		    FALSE,
		    CREATE_NEW_CONSOLE,
		    NULL,
		    NULL,
		    &startupinfo,
		    &process_information) == 0) {
		    	popup_an_error("CreateProcess(%s) failed: %s",
				path, win32_strerror(GetLastError()));
			Free(path);
			Free(args);
		} else {
			Free(path);
		    	Free(args);
			tracewindow_handle = process_information.hProcess;
			CloseHandle(process_information.hThread);
		}
	}
#endif /*]*/

	Free(tfn);

	/* We're really tracing, turn the flag on. */
	appres.toggle[trace_reason].value = True;
	appres.toggle[trace_reason].changed = True;
	menubar_retoggle(&appres.toggle[trace_reason], trace_reason);

	/* Display current status. */
	buf = create_tracefile_header("started");
	do_ts = False;
	wtrace("%s", buf);
	Free(buf);

done:
#if defined(X3270_DISPLAY) /*[*/
	if (w)
		XtPopdown(trace_shell);
#endif /*]*/
	return;
}
コード例 #19
0
ファイル: dynload.cpp プロジェクト: mikowiec/harvest
const std::string dlerror()
{
	return win32_strerror();
}