1/*
2 * Copyright (c) 2011 The Chromium Authors. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file.
5 */
6
7#include <stdarg.h>
8#include <stdlib.h>
9#include <string.h>
10
11#include "native_client/src/include/portability_io.h"
12#include "native_client/src/include/portability_process.h"
13#include "native_client/src/shared/platform/nacl_check.h"
14#include "ppapi/cpp/module.h"
15#include "ppapi/native_client/src/trusted/plugin/utility.h"
16
17namespace plugin {
18
19int gNaClPluginDebugPrintEnabled = -1;
20
21/*
22 * Prints formatted message to the log.
23 */
24int NaClPluginPrintLog(const char *format, ...) {
25  va_list arg;
26  int out_size;
27
28  static const int kStackBufferSize = 512;
29  char stack_buffer[kStackBufferSize];
30
31  // Just log locally to stderr if we can't use the nacl interface.
32  if (!GetNaClInterface()) {
33    va_start(arg, format);
34    int rc = vfprintf(stderr, format, arg);
35    va_end(arg);
36    return rc;
37  }
38
39  va_start(arg, format);
40  out_size = vsnprintf(stack_buffer, kStackBufferSize, format, arg);
41  va_end(arg);
42  if (out_size < kStackBufferSize) {
43    GetNaClInterface()->Vlog(stack_buffer);
44  } else {
45    // Message too large for our stack buffer; we have to allocate memory
46    // instead.
47    char *buffer = static_cast<char*>(malloc(out_size + 1));
48    va_start(arg, format);
49    vsnprintf(buffer, out_size + 1, format, arg);
50    va_end(arg);
51    GetNaClInterface()->Vlog(buffer);
52    free(buffer);
53  }
54  return out_size;
55}
56
57/*
58 * Currently looks for presence of NACL_PLUGIN_DEBUG and returns
59 * 0 if absent and 1 if present.  In the future we may include notions
60 * of verbosity level.
61 */
62int NaClPluginDebugPrintCheckEnv() {
63  char* env = getenv("NACL_PLUGIN_DEBUG");
64  return (NULL != env);
65}
66
67bool IsValidIdentifierString(const char* strval, uint32_t* length) {
68  // This function is supposed to recognize valid ECMAScript identifiers,
69  // as described in
70  // http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf
71  // It is currently restricted to only the ASCII subset.
72  // TODO(sehr): Recognize the full Unicode formulation of identifiers.
73  // TODO(sehr): Make this table-driven if efficiency becomes a problem.
74  if (NULL != length) {
75    *length = 0;
76  }
77  if (NULL == strval) {
78    return false;
79  }
80  static const char* kValidFirstChars =
81      "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz$_";
82  static const char* kValidOtherChars =
83      "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz$_"
84      "0123456789";
85  if (NULL == strchr(kValidFirstChars, strval[0])) {
86    return false;
87  }
88  uint32_t pos;
89  for (pos = 1; ; ++pos) {
90    if (0 == pos) {
91      // Unsigned overflow.
92      return false;
93    }
94    int c = strval[pos];
95    if (0 == c) {
96      break;
97    }
98    if (NULL == strchr(kValidOtherChars, c)) {
99      return false;
100    }
101  }
102  if (NULL != length) {
103    *length = pos;
104  }
105  return true;
106}
107
108// We cache the NaCl interface pointer and ensure that its set early on, on the
109// main thread. This allows GetNaClInterface() to be used from non-main threads.
110static const PPB_NaCl_Private* g_nacl_interface = NULL;
111
112const PPB_NaCl_Private* GetNaClInterface() {
113  return g_nacl_interface;
114}
115
116void SetNaClInterface(const PPB_NaCl_Private* nacl_interface) {
117  g_nacl_interface = nacl_interface;
118}
119
120void CloseFileHandle(PP_FileHandle file_handle) {
121#if NACL_WINDOWS
122  CloseHandle(file_handle);
123#else
124  close(file_handle);
125#endif
126}
127
128// Converts a PP_FileHandle to a POSIX file descriptor.
129int32_t ConvertFileDescriptor(PP_FileHandle handle, bool read_only) {
130  PLUGIN_PRINTF(("ConvertFileDescriptor, handle=%d\n", handle));
131#if NACL_WINDOWS
132  int32_t file_desc = NACL_NO_FILE_DESC;
133  // On Windows, valid handles are 32 bit unsigned integers so this is safe.
134  file_desc = reinterpret_cast<intptr_t>(handle);
135  // Convert the Windows HANDLE from Pepper to a POSIX file descriptor.
136  int flags = _O_BINARY;
137  flags |= read_only ? _O_RDONLY : _O_RDWR;
138  int32_t posix_desc = _open_osfhandle(file_desc, flags);
139  if (posix_desc == -1) {
140    // Close the Windows HANDLE if it can't be converted.
141    CloseHandle(reinterpret_cast<HANDLE>(file_desc));
142    return -1;
143  }
144  return posix_desc;
145#else
146  return handle;
147#endif
148}
149
150}  // namespace plugin
151