mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args) {
#if DEBUG_PRINT
    DEBUG_printf("__import__:\n");
    for (size_t i = 0; i < n_args; i++) {
        DEBUG_printf("  ");
        mp_obj_print(args[i], PRINT_REPR);
        DEBUG_printf("\n");
    }
#endif

    mp_obj_t module_name = args[0];
    mp_obj_t fromtuple = mp_const_none;
    mp_int_t level = 0;
    if (n_args >= 4) {
        fromtuple = args[3];
        if (n_args >= 5) {
            level = MP_OBJ_SMALL_INT_VALUE(args[4]);
            if (level < 0) {
                mp_raise_ValueError(NULL);
            }
        }
    }

    size_t mod_len;
    const char *mod_str = mp_obj_str_get_data(module_name, &mod_len);

    if (level != 0) {
        // What we want to do here is to take name of current module,
        // chop <level> trailing components, and concatenate with passed-in
        // module name, thus resolving relative import name into absolute.
        // This even appears to be correct per
        // http://legacy.python.org/dev/peps/pep-0328/#relative-imports-and-name
        // "Relative imports use a module's __name__ attribute to determine that
        // module's position in the package hierarchy."
        level--;
        mp_obj_t this_name_q = mp_obj_dict_get(MP_OBJ_FROM_PTR(mp_globals_get()), MP_OBJ_NEW_QSTR(MP_QSTR___name__));
        assert(this_name_q != MP_OBJ_NULL);
        #if MICROPY_CPYTHON_COMPAT
        if (MP_OBJ_QSTR_VALUE(this_name_q) == MP_QSTR___main__) {
            // This is a module run by -m command-line switch, get its real name from backup attribute
            this_name_q = mp_obj_dict_get(MP_OBJ_FROM_PTR(mp_globals_get()), MP_OBJ_NEW_QSTR(MP_QSTR___main__));
        }
        #endif
        mp_map_t *globals_map = &mp_globals_get()->map;
        mp_map_elem_t *elem = mp_map_lookup(globals_map, MP_OBJ_NEW_QSTR(MP_QSTR___path__), MP_MAP_LOOKUP);
        bool is_pkg = (elem != NULL);

#if DEBUG_PRINT
        DEBUG_printf("Current module/package: ");
        mp_obj_print(this_name_q, PRINT_REPR);
        DEBUG_printf(", is_package: %d", is_pkg);
        DEBUG_printf("\n");
#endif

        size_t this_name_l;
        const char *this_name = mp_obj_str_get_data(this_name_q, &this_name_l);

        const char *p = this_name + this_name_l;
        if (!is_pkg) {
            // We have module, but relative imports are anchored at package, so
            // go there.
            chop_component(this_name, &p);
        }

        while (level--) {
            chop_component(this_name, &p);
        }

        // We must have some component left over to import from
        if (p == this_name) {
            mp_raise_ValueError("cannot perform relative import");
        }

        uint new_mod_l = (mod_len == 0 ? (size_t)(p - this_name) : (size_t)(p - this_name) + 1 + mod_len);
        char *new_mod = mp_local_alloc(new_mod_l);
        memcpy(new_mod, this_name, p - this_name);
        if (mod_len != 0) {
            new_mod[p - this_name] = '.';
            memcpy(new_mod + (p - this_name) + 1, mod_str, mod_len);
        }

        qstr new_mod_q = qstr_from_strn(new_mod, new_mod_l);
        mp_local_free(new_mod);
        DEBUG_printf("Resolved base name for relative import: '%s'\n", qstr_str(new_mod_q));
        module_name = MP_OBJ_NEW_QSTR(new_mod_q);
        mod_str = qstr_str(new_mod_q);
        mod_len = new_mod_l;
    }

    // check if module already exists
    qstr module_name_qstr = mp_obj_str_get_qstr(module_name);
    mp_obj_t module_obj = mp_module_get(module_name_qstr);
    if (module_obj != MP_OBJ_NULL) {
        DEBUG_printf("Module already loaded\n");
        // If it's not a package, return module right away
        char *p = strchr(mod_str, '.');
        if (p == NULL) {
            return module_obj;
        }
        // If fromlist is not empty, return leaf module
        if (fromtuple != mp_const_none) {
            return module_obj;
        }
        // Otherwise, we need to return top-level package
        qstr pkg_name = qstr_from_strn(mod_str, p - mod_str);
        return mp_module_get(pkg_name);
    }
    DEBUG_printf("Module not yet loaded\n");

    uint last = 0;
    VSTR_FIXED(path, MICROPY_ALLOC_PATH_MAX)
    module_obj = MP_OBJ_NULL;
    mp_obj_t top_module_obj = MP_OBJ_NULL;
    mp_obj_t outer_module_obj = MP_OBJ_NULL;
    uint i;
    for (i = 1; i <= mod_len; i++) {
        if (i == mod_len || mod_str[i] == '.') {
            // create a qstr for the module name up to this depth
            qstr mod_name = qstr_from_strn(mod_str, i);
            DEBUG_printf("Processing module: %s\n", qstr_str(mod_name));
            DEBUG_printf("Previous path: =%.*s=\n", vstr_len(&path), vstr_str(&path));

            // find the file corresponding to the module name
            mp_import_stat_t stat;
            if (vstr_len(&path) == 0) {
                // first module in the dotted-name; search for a directory or file
                stat = find_file(mod_str, i, &path);
            } else {
                // latter module in the dotted-name; append to path
                vstr_add_char(&path, PATH_SEP_CHAR);
                vstr_add_strn(&path, mod_str + last, i - last);
                stat = stat_dir_or_file(&path);
            }
            DEBUG_printf("Current path: %.*s\n", vstr_len(&path), vstr_str(&path));

            if (stat == MP_IMPORT_STAT_NO_EXIST) {
                #if MICROPY_MODULE_WEAK_LINKS
                // check if there is a weak link to this module
                if (i == mod_len) {
                    mp_map_elem_t *el = mp_map_lookup((mp_map_t*)&mp_builtin_module_weak_links_map, MP_OBJ_NEW_QSTR(mod_name), MP_MAP_LOOKUP);
                    if (el == NULL) {
                        goto no_exist;
                    }
                    // found weak linked module
                    module_obj = el->value;
                    mp_module_call_init(mod_name, module_obj);
                } else {
                    no_exist:
                #else
                {
                #endif
                    // couldn't find the file, so fail
                    if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
                        mp_raise_msg(&mp_type_ImportError, "module not found");
                    } else {
                        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ImportError,
                            "no module named '%q'", mod_name));
                    }
                }
            } else {
                // found the file, so get the module
                module_obj = mp_module_get(mod_name);
            }

            if (module_obj == MP_OBJ_NULL) {
                // module not already loaded, so load it!

                module_obj = mp_obj_new_module(mod_name);

                // if args[3] (fromtuple) has magic value False, set up
                // this module for command-line "-m" option (set module's
                // name to __main__ instead of real name). Do this only
                // for *modules* however - packages never have their names
                // replaced, instead they're -m'ed using a special __main__
                // submodule in them. (This all apparently is done to not
                // touch package name itself, which is important for future
                // imports).
                if (i == mod_len && fromtuple == mp_const_false && stat != MP_IMPORT_STAT_DIR) {
                    mp_obj_module_t *o = MP_OBJ_TO_PTR(module_obj);
                    mp_obj_dict_store(MP_OBJ_FROM_PTR(o->globals), MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR___main__));
                    #if MICROPY_CPYTHON_COMPAT
                    // Store module as "__main__" in the dictionary of loaded modules (returned by sys.modules).
                    mp_obj_dict_store(MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_loaded_modules_dict)), MP_OBJ_NEW_QSTR(MP_QSTR___main__), module_obj);
                    // Store real name in "__main__" attribute. Chosen semi-randonly, to reuse existing qstr's.
                    mp_obj_dict_store(MP_OBJ_FROM_PTR(o->globals), MP_OBJ_NEW_QSTR(MP_QSTR___main__), MP_OBJ_NEW_QSTR(mod_name));
                    #endif
                }

                if (stat == MP_IMPORT_STAT_DIR) {
                    DEBUG_printf("%.*s is dir\n", vstr_len(&path), vstr_str(&path));
                    // https://docs.python.org/3/reference/import.html
                    // "Specifically, any module that contains a __path__ attribute is considered a package."
                    mp_store_attr(module_obj, MP_QSTR___path__, mp_obj_new_str(vstr_str(&path), vstr_len(&path)));
                    size_t orig_path_len = path.len;
                    vstr_add_char(&path, PATH_SEP_CHAR);
                    vstr_add_str(&path, "__init__.py");
                    if (stat_file_py_or_mpy(&path) != MP_IMPORT_STAT_FILE) {
                        //mp_warning("%s is imported as namespace package", vstr_str(&path));
                    } else {
                        do_load(module_obj, &path);
                    }
                    path.len = orig_path_len;
                } else { // MP_IMPORT_STAT_FILE
                    do_load(module_obj, &path);
                    // This should be the last component in the import path.  If there are
                    // remaining components then it's an ImportError because the current path
                    // (the module that was just loaded) is not a package.  This will be caught
                    // on the next iteration because the file will not exist.
                }
            }
            if (outer_module_obj != MP_OBJ_NULL) {
                qstr s = qstr_from_strn(mod_str + last, i - last);
                mp_store_attr(outer_module_obj, s, module_obj);
            }
            outer_module_obj = module_obj;
            if (top_module_obj == MP_OBJ_NULL) {
                top_module_obj = module_obj;
            }
            last = i + 1;
        }
    }
Exemple #2
0
int					/* O - Number of options found */
cupsParseOptions(
    const char    *arg,			/* I - Argument to parse */
    int           num_options,		/* I - Number of options */
    cups_option_t **options)		/* O - Options found */
{
  char	*copyarg,			/* Copy of input string */
	*ptr,				/* Pointer into string */
	*name,				/* Pointer to name */
	*value,				/* Pointer to value */
	sep,				/* Separator character */
	quote;				/* Quote character */


  DEBUG_printf(("cupsParseOptions(arg=\"%s\", num_options=%d, options=%p)",
                arg, num_options, options));

 /*
  * Range check input...
  */

  if (!arg)
  {
    DEBUG_printf(("1cupsParseOptions: Returning %d", num_options));
    return (num_options);
  }

  if (!options || num_options < 0)
  {
    DEBUG_puts("1cupsParseOptions: Returning 0");
    return (0);
  }

 /*
  * Make a copy of the argument string and then divide it up...
  */

  if ((copyarg = strdup(arg)) == NULL)
  {
    DEBUG_puts("1cupsParseOptions: Unable to copy arg string");
    DEBUG_printf(("1cupsParseOptions: Returning %d", num_options));
    return (num_options);
  }

  if (*copyarg == '{')
  {
   /*
    * Remove surrounding {} so we can parse "{name=value ... name=value}"...
    */

    if ((ptr = copyarg + strlen(copyarg) - 1) > copyarg && *ptr == '}')
    {
      *ptr = '\0';
      ptr  = copyarg + 1;
    }
    else
      ptr = copyarg;
  }
  else
    ptr = copyarg;

 /*
  * Skip leading spaces...
  */

  while (_cups_isspace(*ptr))
    ptr ++;

 /*
  * Loop through the string...
  */

  while (*ptr != '\0')
  {
   /*
    * Get the name up to a SPACE, =, or end-of-string...
    */

    name = ptr;
    while (!strchr("\f\n\r\t\v =", *ptr) && *ptr)
      ptr ++;

   /*
    * Avoid an empty name...
    */

    if (ptr == name)
      break;

   /*
    * Skip trailing spaces...
    */

    while (_cups_isspace(*ptr))
      *ptr++ = '\0';

    if ((sep = *ptr) == '=')
      *ptr++ = '\0';

    DEBUG_printf(("2cupsParseOptions: name=\"%s\"", name));

    if (sep != '=')
    {
     /*
      * Boolean option...
      */

      if (!_cups_strncasecmp(name, "no", 2))
        num_options = cupsAddOption(name + 2, "false", num_options,
	                            options);
      else
        num_options = cupsAddOption(name, "true", num_options, options);

      continue;
    }

   /*
    * Remove = and parse the value...
    */

    value = ptr;

    while (*ptr && !_cups_isspace(*ptr))
    {
      if (*ptr == ',')
        ptr ++;
      else if (*ptr == '\'' || *ptr == '\"')
      {
       /*
	* Quoted string constant...
	*/

	quote = *ptr;
	_cups_strcpy(ptr, ptr + 1);

	while (*ptr != quote && *ptr)
	{
	  if (*ptr == '\\' && ptr[1])
	    _cups_strcpy(ptr, ptr + 1);

	  ptr ++;
	}

	if (*ptr)
	  _cups_strcpy(ptr, ptr + 1);
      }
      else if (*ptr == '{')
      {
       /*
	* Collection value...
	*/

	int depth;

	for (depth = 0; *ptr; ptr ++)
	{
	  if (*ptr == '{')
	    depth ++;
	  else if (*ptr == '}')
	  {
	    depth --;
	    if (!depth)
	    {
	      ptr ++;
	      break;
	    }
	  }
	  else if (*ptr == '\\' && ptr[1])
	    _cups_strcpy(ptr, ptr + 1);
	}
      }
      else
      {
       /*
	* Normal space-delimited string...
	*/

	while (*ptr && !_cups_isspace(*ptr))
	{
	  if (*ptr == '\\' && ptr[1])
	    _cups_strcpy(ptr, ptr + 1);

	  ptr ++;
	}
      }
    }

    if (*ptr != '\0')
      *ptr++ = '\0';

    DEBUG_printf(("2cupsParseOptions: value=\"%s\"", value));

   /*
    * Skip trailing whitespace...
    */

    while (_cups_isspace(*ptr))
      ptr ++;

   /*
    * Add the string value...
    */

    num_options = cupsAddOption(name, value, num_options, options);
  }

 /*
  * Free the copy of the argument we made and return the number of options
  * found.
  */

  free(copyarg);

  DEBUG_printf(("1cupsParseOptions: Returning %d", num_options));

  return (num_options);
}
Exemple #3
0
static int				/* O - Index of match */
cups_find_option(
    const char    *name,		/* I - Option name */
    int           num_options,		/* I - Number of options */
    cups_option_t *options,		/* I - Options */
    int           prev,			/* I - Previous index */
    int           *rdiff)		/* O - Difference of match */
{
  int		left,			/* Low mark for binary search */
		right,			/* High mark for binary search */
		current,		/* Current index */
		diff;			/* Result of comparison */
  cups_option_t	key;			/* Search key */


  DEBUG_printf(("7cups_find_option(name=\"%s\", num_options=%d, options=%p, "
	        "prev=%d, rdiff=%p)", name, num_options, options, prev,
		rdiff));

#ifdef DEBUG
  for (left = 0; left < num_options; left ++)
    DEBUG_printf(("9cups_find_option: options[%d].name=\"%s\", .value=\"%s\"",
                  left, options[left].name, options[left].value));
#endif /* DEBUG */

  key.name = (char *)name;

  if (prev >= 0)
  {
   /*
    * Start search on either side of previous...
    */

    if ((diff = cups_compare_options(&key, options + prev)) == 0 ||
        (diff < 0 && prev == 0) ||
	(diff > 0 && prev == (num_options - 1)))
    {
      *rdiff = diff;
      return (prev);
    }
    else if (diff < 0)
    {
     /*
      * Start with previous on right side...
      */

      left  = 0;
      right = prev;
    }
    else
    {
     /*
      * Start wih previous on left side...
      */

      left  = prev;
      right = num_options - 1;
    }
  }
  else
  {
   /*
    * Start search in the middle...
    */

    left  = 0;
    right = num_options - 1;
  }

  do
  {
    current = (left + right) / 2;
    diff    = cups_compare_options(&key, options + current);

    if (diff == 0)
      break;
    else if (diff < 0)
      right = current;
    else
      left = current;
  }
  while ((right - left) > 1);

  if (diff != 0)
  {
   /*
    * Check the last 1 or 2 elements...
    */

    if ((diff = cups_compare_options(&key, options + left)) <= 0)
      current = left;
    else
    {
      diff    = cups_compare_options(&key, options + right);
      current = right;
    }
  }

 /*
  * Return the closest destination and the difference...
  */

  *rdiff = diff;

  return (current);
}
Exemple #4
0
cups_dentry_t *				/* O - Directory entry or @code NULL@ when there are no more */
cupsDirRead(cups_dir_t *dp)		/* I - Directory pointer */
{
  struct dirent	*entry;			/* Pointer to entry */
  char		filename[1024];		/* Full filename */
#  ifdef HAVE_PTHREAD_H
  char		buffer[sizeof(struct dirent) + 1024];
					/* Directory entry buffer */
#  endif /* HAVE_PTHREAD_H */


  DEBUG_printf(("2cupsDirRead(dp=%p)", (void *)dp));

 /*
  * Range check input...
  */

  if (!dp)
    return (NULL);

 /*
  * Try reading an entry that is not "." or ".."...
  */

  for (;;)
  {
#  ifdef HAVE_PTHREAD_H
   /*
    * Read the next entry using the reentrant version of readdir...
    */

    if (readdir_r(dp->dir, (struct dirent *)buffer, &entry))
    {
      DEBUG_printf(("3cupsDirRead: readdir_r() failed - %s\n", strerror(errno)));
      return (NULL);
    }

    if (!entry)
    {
      DEBUG_puts("3cupsDirRead: readdir_r() returned a NULL pointer!");
      return (NULL);
    }

    DEBUG_printf(("4cupsDirRead: readdir_r() returned \"%s\"...",
                  entry->d_name));

#  else
   /*
    * Read the next entry using the original version of readdir...
    */

    if ((entry = readdir(dp->dir)) == NULL)
    {
      DEBUG_puts("3cupsDirRead: readdir() returned a NULL pointer!");
      return (NULL);
    }

    DEBUG_printf(("4cupsDirRead: readdir() returned \"%s\"...", entry->d_name));

#  endif /* HAVE_PTHREAD_H */

   /*
    * Skip "." and ".."...
    */

    if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, ".."))
      continue;

   /*
    * Copy the name over and get the file information...
    */

    strlcpy(dp->entry.filename, entry->d_name, sizeof(dp->entry.filename));

    snprintf(filename, sizeof(filename), "%s/%s", dp->directory, entry->d_name);

    if (stat(filename, &(dp->entry.fileinfo)))
    {
      DEBUG_printf(("3cupsDirRead: stat() failed for \"%s\" - %s...", filename,
                    strerror(errno)));
      continue;
    }

   /*
    * Return the entry...
    */

    return (&(dp->entry));
  }
}
Exemple #5
0
void
_cupsRasterAddError(const char *f,	/* I - Printf-style error message */
                    ...)		/* I - Additional arguments as needed */
{
  _cups_raster_error_t	*buf = get_error_buffer();
					/* Error buffer */
  va_list	ap;			/* Pointer to additional arguments */
  char		s[2048];		/* Message string */
  ssize_t	bytes;			/* Bytes in message string */


  DEBUG_printf(("_cupsRasterAddError(f=\"%s\", ...)", f));

  va_start(ap, f);
  bytes = vsnprintf(s, sizeof(s), f, ap);
  va_end(ap);

  if (bytes <= 0)
    return;

  DEBUG_printf(("1_cupsRasterAddError: %s", s));

  bytes ++;

  if ((size_t)bytes >= sizeof(s))
    return;

  if (bytes > (ssize_t)(buf->end - buf->current))
  {
   /*
    * Allocate more memory...
    */

    char	*temp;			/* New buffer */
    size_t	size;			/* Size of buffer */


    size = (size_t)(buf->end - buf->start + 2 * bytes + 1024);

    if (buf->start)
      temp = realloc(buf->start, size);
    else
      temp = malloc(size);

    if (!temp)
      return;

   /*
    * Update pointers...
    */

    buf->end     = temp + size;
    buf->current = temp + (buf->current - buf->start);
    buf->start   = temp;
  }

 /*
  * Append the message to the end of the current string...
  */

  memcpy(buf->current, s, (size_t)bytes);
  buf->current += bytes - 1;
}
int					/* O - 1 on success, 0 on failure */
pwgFormatSizeName(char       *keyword,	/* I - Keyword buffer */
		  size_t     keysize,	/* I - Size of keyword buffer */
		  const char *prefix,	/* I - Prefix for PWG size or @code NULL@ for automatic */
		  const char *name,	/* I - Size name or @code NULL@ */
		  int        width,	/* I - Width of page in 2540ths */
		  int        length,	/* I - Length of page in 2540ths */
		  const char *units)	/* I - Units - "in", "mm", or @code NULL@ for automatic */
{
  char		usize[12 + 1 + 12 + 3],	/* Unit size: NNNNNNNNNNNNxNNNNNNNNNNNNuu */
		*uptr;			/* Pointer into unit size */
  char		*(*format)(char *, size_t, int);
					/* Formatting function */


 /*
  * Range check input...
  */

  DEBUG_printf(("pwgFormatSize(keyword=%p, keysize=" CUPS_LLFMT ", prefix=\"%s\", name=\"%s\", width=%d, length=%d, units=\"%s\")", (void *)keyword, CUPS_LLCAST keysize, prefix, name, width, length, units));

  if (keyword)
    *keyword = '\0';

  if (!keyword || keysize < 32 || width < 0 || length < 0 ||
      (units && strcmp(units, "in") && strcmp(units, "mm")))
  {
    _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Invalid media name arguments."),
                  1);
    return (0);
  }

  if (name)
  {
   /*
    * Validate name...
    */

    const char *nameptr;		/* Pointer into name */

    for (nameptr = name; *nameptr; nameptr ++)
      if (!(*nameptr >= 'a' && *nameptr <= 'z') &&
          !(*nameptr >= '0' && *nameptr <= '9') &&
          *nameptr != '.' && *nameptr != '-')
      {
        _cupsSetError(IPP_STATUS_ERROR_INTERNAL,
                      _("Invalid media name arguments."), 1);
        return (0);
      }
  }
  else
    name = usize;

  if (prefix && !strcmp(prefix, "disc"))
    width = 4000;			/* Disc sizes use hardcoded 40mm inner diameter */

  if (!units)
  {
    if ((width % 635) == 0 && (length % 635) == 0)
    {
     /*
      * Use inches since the size is a multiple of 1/4 inch.
      */

      units = "in";
    }
    else
    {
     /*
      * Use millimeters since the size is not a multiple of 1/4 inch.
      */

      units = "mm";
    }
  }

  if (!strcmp(units, "in"))
  {
    format = pwg_format_inches;

    if (!prefix)
      prefix = "oe";
  }
  else
  {
    format = pwg_format_millimeters;

    if (!prefix)
      prefix = "om";
  }

 /*
  * Format the size string...
  */

  uptr = usize;
  (*format)(uptr, sizeof(usize) - (size_t)(uptr - usize), width);
  uptr += strlen(uptr);
  *uptr++ = 'x';
  (*format)(uptr, sizeof(usize) - (size_t)(uptr - usize), length);
  uptr += strlen(uptr);

 /*
  * Safe because usize can hold up to 12 + 1 + 12 + 4 bytes.
  */

  memcpy(uptr, units, 3);

 /*
  * Format the name...
  */

  snprintf(keyword, keysize, "%s_%s_%s", prefix, name, usize);

  return (1);
}
Exemple #7
0
STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *args) {
    // This function is pretty complicated.  It's main aim is to be efficient in speed and RAM
    // usage for the common case of positional only args.
    //
    // extra_args layout: def_args, var_arg tuple, kwonly args, var_kw dict

    DEBUG_printf("Input n_args: %d, n_kw: %d\n", n_args, n_kw);
    DEBUG_printf("Input pos args: ");
    dump_args(args, n_args);
    DEBUG_printf("Input kw args: ");
    dump_args(args + n_args, n_kw * 2);
    mp_obj_fun_bc_t *self = self_in;
    DEBUG_printf("Func n_def_args: %d\n", self->n_def_args);

    const mp_obj_t *kwargs = args + n_args;
    mp_obj_t *extra_args = self->extra_args + self->n_def_args;
    uint n_extra_args = 0;

    // check positional arguments

    if (n_args > self->n_pos_args) {
        // given more than enough arguments
        if (!self->takes_var_args) {
            fun_pos_args_mismatch(self, self->n_pos_args, n_args);
        }
        // put extra arguments in varargs tuple
        *extra_args = mp_obj_new_tuple(n_args - self->n_pos_args, args + self->n_pos_args);
        n_extra_args = 1;
        n_args = self->n_pos_args;
    } else {
        if (self->takes_var_args) {
            DEBUG_printf("passing empty tuple as *args\n");
            *extra_args = mp_const_empty_tuple;
            n_extra_args = 1;
        }
        // Apply processing and check below only if we don't have kwargs,
        // otherwise, kw handling code below has own extensive checks.
        if (n_kw == 0) {
            if (n_args >= self->n_pos_args - self->n_def_args) {
                // given enough arguments, but may need to use some default arguments
                extra_args -= self->n_pos_args - n_args;
                n_extra_args += self->n_pos_args - n_args;
            } else {
                fun_pos_args_mismatch(self, self->n_pos_args - self->n_def_args, n_args);
            }
        }
    }

    // check keyword arguments

    if (n_kw != 0) {
        // We cannot use dynamically-sized array here, because GCC indeed
        // deallocates it on leaving defining scope (unlike most static stack allocs).
        // So, we have 2 choices: allocate it unconditionally at the top of function
        // (wastes stack), or use alloca which is guaranteed to dealloc on func exit.
        //mp_obj_t flat_args[self->n_args];
        mp_obj_t *flat_args = alloca((self->n_pos_args + self->n_kwonly_args) * sizeof(mp_obj_t));
        for (int i = self->n_pos_args + self->n_kwonly_args - 1; i >= 0; i--) {
            flat_args[i] = MP_OBJ_NULL;
        }
        memcpy(flat_args, args, sizeof(*args) * n_args);
        DEBUG_printf("Initial args: ");
        dump_args(flat_args, self->n_pos_args + self->n_kwonly_args);

        mp_obj_t dict = MP_OBJ_NULL;
        if (self->takes_kw_args) {
            dict = mp_obj_new_dict(n_kw); // TODO: better go conservative with 0?
        }
        for (uint i = 0; i < n_kw; i++) {
            qstr arg_name = MP_OBJ_QSTR_VALUE(kwargs[2 * i]);
            for (uint j = 0; j < self->n_pos_args + self->n_kwonly_args; j++) {
                if (arg_name == self->args[j]) {
                    if (flat_args[j] != MP_OBJ_NULL) {
                        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
                            "function got multiple values for argument '%s'", qstr_str(arg_name)));
                    }
                    flat_args[j] = kwargs[2 * i + 1];
                    goto continue2;
                }
            }
            // Didn't find name match with positional args
            if (!self->takes_kw_args) {
                nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "function does not take keyword arguments"));
            }
            mp_obj_dict_store(dict, kwargs[2 * i], kwargs[2 * i + 1]);
continue2:;
        }
        DEBUG_printf("Args with kws flattened: ");
        dump_args(flat_args, self->n_pos_args + self->n_kwonly_args);

        // Now fill in defaults for positional args
        mp_obj_t *d = &flat_args[self->n_pos_args - 1];
        mp_obj_t *s = &self->extra_args[self->n_def_args - 1];
        for (int i = self->n_def_args; i > 0; i--, d--, s--) {
            if (*d == MP_OBJ_NULL) {
                *d = *s;
            }
        }
        DEBUG_printf("Args after filling defaults: ");
        dump_args(flat_args, self->n_pos_args + self->n_kwonly_args);

        // Check that all mandatory positional args are specified
        while (d >= flat_args) {
            if (*d-- == MP_OBJ_NULL) {
                nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
                    "function missing required positional argument #%d", d - flat_args));
            }
        }

        // Check that all mandatory keyword args are specified
        for (int i = 0; i < self->n_kwonly_args; i++) {
            if (flat_args[self->n_pos_args + i] == MP_OBJ_NULL) {
                nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
                    "function missing required keyword argument '%s'", qstr_str(self->args[self->n_pos_args + i])));
            }
        }

        args = flat_args;
        n_args = self->n_pos_args + self->n_kwonly_args;

        if (self->takes_kw_args) {
            extra_args[n_extra_args] = dict;
            n_extra_args += 1;
        }
    } else {
        // no keyword arguments given
        if (self->n_kwonly_args != 0) {
            nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
                "function missing keyword-only argument"));
        }
        if (self->takes_kw_args) {
            extra_args[n_extra_args] = mp_obj_new_dict(0);
            n_extra_args += 1;
        }
    }

    mp_obj_dict_t *old_globals = mp_globals_get();
    mp_globals_set(self->globals);
    mp_obj_t result;
    DEBUG_printf("Calling: args=%p, n_args=%d, extra_args=%p, n_extra_args=%d\n", args, n_args, extra_args, n_extra_args);
    dump_args(args, n_args);
    dump_args(extra_args, n_extra_args);
    mp_vm_return_kind_t vm_return_kind = mp_execute_byte_code(self->bytecode, args, n_args, extra_args, n_extra_args, &result);
    mp_globals_set(old_globals);

    if (vm_return_kind == MP_VM_RETURN_NORMAL) {
        return result;
    } else { // MP_VM_RETURN_EXCEPTION
        nlr_raise(result);
    }
}
Exemple #8
0
char *					/* O  - Line read or @code NULL@ on end of file or error */
cupsFileGetConf(cups_file_t *fp,	/* I  - CUPS file */
                char        *buf,	/* O  - String buffer */
		size_t      buflen,	/* I  - Size of string buffer */
                char        **value,	/* O  - Pointer to value */
		int         *linenum)	/* IO - Current line number */
{
  char	*ptr;				/* Pointer into line */


 /*
  * Range check input...
  */

  DEBUG_printf(("2cupsFileGetConf(fp=%p, buf=%p, buflen=" CUPS_LLFMT
                ", value=%p, linenum=%p)", fp, buf, CUPS_LLCAST buflen,
		value, linenum));

  if (!fp || (fp->mode != 'r' && fp->mode != 's') ||
      !buf || buflen < 2 || !value)
  {
    if (value)
      *value = NULL;

    return (NULL);
  }

 /*
  * Read the next non-comment line...
  */

  *value = NULL;

  while (cupsFileGets(fp, buf, buflen))
  {
    (*linenum) ++;

   /*
    * Strip any comments...
    */

    if ((ptr = strchr(buf, '#')) != NULL)
    {
      if (ptr > buf && ptr[-1] == '\\')
      {
        // Unquote the #...
	_cups_strcpy(ptr - 1, ptr);
      }
      else
      {
        // Strip the comment and any trailing whitespace...
	while (ptr > buf)
	{
	  if (!_cups_isspace(ptr[-1]))
	    break;

	  ptr --;
	}

	*ptr = '\0';
      }
    }

   /*
    * Strip leading whitespace...
    */

    for (ptr = buf; _cups_isspace(*ptr); ptr ++);

    if (ptr > buf)
      _cups_strcpy(buf, ptr);

   /*
    * See if there is anything left...
    */

    if (buf[0])
    {
     /*
      * Yes, grab any value and return...
      */

      for (ptr = buf; *ptr; ptr ++)
        if (_cups_isspace(*ptr))
	  break;

      if (*ptr)
      {
       /*
        * Have a value, skip any other spaces...
	*/

        while (_cups_isspace(*ptr))
	  *ptr++ = '\0';

        if (*ptr)
	  *value = ptr;

       /*
        * Strip trailing whitespace and > for lines that begin with <...
	*/

        ptr += strlen(ptr) - 1;

        if (buf[0] == '<' && *ptr == '>')
	  *ptr-- = '\0';
	else if (buf[0] == '<' && *ptr != '>')
        {
	 /*
	  * Syntax error...
	  */

	  *value = NULL;
	  return (buf);
	}

        while (ptr > *value && _cups_isspace(*ptr))
	  *ptr-- = '\0';
      }

     /*
      * Return the line...
      */

      return (buf);
    }
  }

  return (NULL);
}
Exemple #9
0
size_t					/* O - Number of bytes on line or 0 on end of file */
cupsFileGetLine(cups_file_t *fp,	/* I - File to read from */
                char        *buf,	/* I - Buffer */
                size_t      buflen)	/* I - Size of buffer */
{
  int		ch;			/* Character from file */
  char		*ptr,			/* Current position in line buffer */
		*end;			/* End of line buffer */


 /*
  * Range check input...
  */

  DEBUG_printf(("2cupsFileGetLine(fp=%p, buf=%p, buflen=" CUPS_LLFMT ")",
                fp, buf, CUPS_LLCAST buflen));

  if (!fp || (fp->mode != 'r' && fp->mode != 's') || !buf || buflen < 3)
    return (0);

 /*
  * Now loop until we have a valid line...
  */

  for (ptr = buf, end = buf + buflen - 2; ptr < end ;)
  {
    if (fp->ptr >= fp->end)
      if (cups_fill(fp) <= 0)
        break;

    *ptr++ = ch = *(fp->ptr)++;
    fp->pos ++;

    if (ch == '\r')
    {
     /*
      * Check for CR LF...
      */

      if (fp->ptr >= fp->end)
	if (cups_fill(fp) <= 0)
          break;

      if (*(fp->ptr) == '\n')
      {
        *ptr++ = *(fp->ptr)++;
	fp->pos ++;
      }

      break;
    }
    else if (ch == '\n')
    {
     /*
      * Line feed ends a line...
      */

      break;
    }
  }

  *ptr = '\0';

  DEBUG_printf(("4cupsFileGetLine: pos=" CUPS_LLFMT, CUPS_LLCAST fp->pos));

  return (ptr - buf);
}
Exemple #10
0
ipp_status_t				/* O - Request status - @code IPP_OK@ on success. */
cupsGetDevices(
    http_t           *http,		/* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
    int              timeout,		/* I - Timeout in seconds or @code CUPS_TIMEOUT_DEFAULT@ */
    const char       *include_schemes,	/* I - Comma-separated URI schemes to include or @code CUPS_INCLUDE_ALL@ */
    const char       *exclude_schemes,	/* I - Comma-separated URI schemes to exclude or @code CUPS_EXCLUDE_NONE@ */
    cups_device_cb_t callback,		/* I - Callback function */
    void             *user_data)	/* I - User data pointer */
{
  ipp_t		*request,		/* CUPS-Get-Devices request */
		*response;		/* CUPS-Get-Devices response */
  ipp_attribute_t *attr;		/* Current attribute */
  const char	*device_class,		/* device-class value */
		*device_id,		/* device-id value */
		*device_info,		/* device-info value */
		*device_location,	/* device-location value */
		*device_make_and_model,	/* device-make-and-model value */
		*device_uri;		/* device-uri value */
  int		blocking;		/* Current blocking-IO mode */
  cups_option_t	option;			/* in/exclude-schemes option */
  http_status_t	status;			/* HTTP status of request */
  ipp_state_t	state;			/* IPP response state */


 /*
  * Range check input...
  */

  DEBUG_printf(("cupsGetDevices(http=%p, timeout=%d, include_schemes=\"%s\", exclude_schemes=\"%s\", callback=%p, user_data=%p)", (void *)http, timeout, include_schemes, exclude_schemes, (void *)callback, user_data));

  if (!callback)
    return (IPP_STATUS_ERROR_INTERNAL);

  if (!http)
    http = _cupsConnect();

  if (!http)
    return (IPP_STATUS_ERROR_SERVICE_UNAVAILABLE);

 /*
  * Create a CUPS-Get-Devices request...
  */

  request = ippNewRequest(IPP_OP_CUPS_GET_DEVICES);

  if (timeout > 0)
    ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "timeout",
                  timeout);

  if (include_schemes)
  {
    option.name  = "include-schemes";
    option.value = (char *)include_schemes;

    cupsEncodeOptions2(request, 1, &option, IPP_TAG_OPERATION);
  }

  if (exclude_schemes)
  {
    option.name  = "exclude-schemes";
    option.value = (char *)exclude_schemes;

    cupsEncodeOptions2(request, 1, &option, IPP_TAG_OPERATION);
  }

 /*
  * Send the request and do any necessary authentication...
  */

  do
  {
    DEBUG_puts("2cupsGetDevices: Sending request...");
    status = cupsSendRequest(http, request, "/", ippLength(request));

    DEBUG_puts("2cupsGetDevices: Waiting for response status...");
    while (status == HTTP_STATUS_CONTINUE)
      status = httpUpdate(http);

    if (status != HTTP_STATUS_OK)
    {
      httpFlush(http);

      if (status == HTTP_STATUS_UNAUTHORIZED)
      {
       /*
	* See if we can do authentication...
	*/

	DEBUG_puts("2cupsGetDevices: Need authorization...");

	if (!cupsDoAuthentication(http, "POST", "/"))
	  httpReconnect2(http, 30000, NULL);
	else
	{
	  status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED;
	  break;
	}
      }

#ifdef HAVE_SSL
      else if (status == HTTP_STATUS_UPGRADE_REQUIRED)
      {
       /*
	* Force a reconnect with encryption...
	*/

	DEBUG_puts("2cupsGetDevices: Need encryption...");

	if (!httpReconnect2(http, 30000, NULL))
	  httpEncryption(http, HTTP_ENCRYPTION_REQUIRED);
      }
#endif /* HAVE_SSL */
    }
  }
  while (status == HTTP_STATUS_UNAUTHORIZED ||
         status == HTTP_STATUS_UPGRADE_REQUIRED);

  DEBUG_printf(("2cupsGetDevices: status=%d", status));

  ippDelete(request);

  if (status != HTTP_STATUS_OK)
  {
    _cupsSetHTTPError(status);
    return (cupsLastError());
  }

 /*
  * Read the response in non-blocking mode...
  */

  blocking = httpGetBlocking(http);
  httpBlocking(http, 0);

  response              = ippNew();
  device_class          = NULL;
  device_id             = NULL;
  device_info           = NULL;
  device_location       = "";
  device_make_and_model = NULL;
  device_uri            = NULL;
  attr                  = NULL;

  DEBUG_puts("2cupsGetDevices: Reading response...");

  do
  {
    if ((state = ippRead(http, response)) == IPP_STATE_ERROR)
      break;

    DEBUG_printf(("2cupsGetDevices: state=%d, response->last=%p", state, (void *)response->last));

    if (!response->attrs)
      continue;

    while (attr != response->last)
    {
      if (!attr)
	attr = response->attrs;
      else
        attr = attr->next;

      DEBUG_printf(("2cupsGetDevices: attr->name=\"%s\", attr->value_tag=%d",
                    attr->name, attr->value_tag));

      if (!attr->name)
      {
        if (device_class && device_id && device_info && device_make_and_model &&
	    device_uri)
          (*callback)(device_class, device_id, device_info,
	              device_make_and_model, device_uri, device_location,
		      user_data);

	device_class          = NULL;
	device_id             = NULL;
	device_info           = NULL;
	device_location       = "";
	device_make_and_model = NULL;
	device_uri            = NULL;
      }
      else if (!strcmp(attr->name, "device-class") &&
               attr->value_tag == IPP_TAG_KEYWORD)
        device_class = attr->values[0].string.text;
      else if (!strcmp(attr->name, "device-id") &&
               attr->value_tag == IPP_TAG_TEXT)
        device_id = attr->values[0].string.text;
      else if (!strcmp(attr->name, "device-info") &&
               attr->value_tag == IPP_TAG_TEXT)
        device_info = attr->values[0].string.text;
      else if (!strcmp(attr->name, "device-location") &&
               attr->value_tag == IPP_TAG_TEXT)
        device_location = attr->values[0].string.text;
      else if (!strcmp(attr->name, "device-make-and-model") &&
               attr->value_tag == IPP_TAG_TEXT)
        device_make_and_model = attr->values[0].string.text;
      else if (!strcmp(attr->name, "device-uri") &&
               attr->value_tag == IPP_TAG_URI)
        device_uri = attr->values[0].string.text;
    }
  }
  while (state != IPP_STATE_DATA);

  DEBUG_printf(("2cupsGetDevices: state=%d, response->last=%p", state, (void *)response->last));

  if (device_class && device_id && device_info && device_make_and_model &&
      device_uri)
    (*callback)(device_class, device_id, device_info,
		device_make_and_model, device_uri, device_location, user_data);

 /*
  * Set the IPP status and return...
  */

  httpBlocking(http, blocking);
  httpFlush(http);

  if (status == HTTP_STATUS_ERROR)
    _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(http->error), 0);
  else
  {
    attr = ippFindAttribute(response, "status-message", IPP_TAG_TEXT);

    DEBUG_printf(("cupsGetDevices: status-code=%s, status-message=\"%s\"",
		  ippErrorString(response->request.status.status_code),
		  attr ? attr->values[0].string.text : ""));

    _cupsSetError(response->request.status.status_code,
		  attr ? attr->values[0].string.text :
		      ippErrorString(response->request.status.status_code), 0);
  }

  ippDelete(response);

  return (cupsLastError());
}
Exemple #11
0
const char *				/* O - Full path to file or @code NULL@ if not found */
cupsFileFind(const char *filename,	/* I - File to find */
             const char *path,		/* I - Colon/semicolon-separated path */
             int        executable,	/* I - 1 = executable files, 0 = any file/dir */
	     char       *buffer,	/* I - Filename buffer */
	     int        bufsize)	/* I - Size of filename buffer */
{
  char	*bufptr,			/* Current position in buffer */
	*bufend;			/* End of buffer */


 /*
  * Range check input...
  */

  DEBUG_printf(("cupsFileFind(filename=\"%s\", path=\"%s\", executable=%d, "
                "buffer=%p, bufsize=%d)", filename, path, executable, buffer,
		bufsize));

  if (!filename || !buffer || bufsize < 2)
    return (NULL);

  if (!path)
  {
   /*
    * No path, so check current directory...
    */

    if (!access(filename, 0))
    {
      strlcpy(buffer, filename, bufsize);
      return (buffer);
    }
    else
      return (NULL);
  }

 /*
  * Now check each path and return the first match...
  */

  bufend = buffer + bufsize - 1;
  bufptr = buffer;

  while (*path)
  {
#ifdef WIN32
    if (*path == ';' || (*path == ':' && ((bufptr - buffer) > 1 || !isalpha(buffer[0] & 255))))
#else
    if (*path == ';' || *path == ':')
#endif /* WIN32 */
    {
      if (bufptr > buffer && bufptr[-1] != '/' && bufptr < bufend)
        *bufptr++ = '/';

      strlcpy(bufptr, filename, bufend - bufptr);

#ifdef WIN32
      if (!access(buffer, 0))
#else
      if (!access(buffer, executable ? X_OK : 0))
#endif /* WIN32 */
      {
        DEBUG_printf(("1cupsFileFind: Returning \"%s\"", buffer));
        return (buffer);
      }

      bufptr = buffer;
    }
    else if (bufptr < bufend)
      *bufptr++ = *path;

    path ++;
  }

 /*
  * Check the last path...
  */

  if (bufptr > buffer && bufptr[-1] != '/' && bufptr < bufend)
    *bufptr++ = '/';

  strlcpy(bufptr, filename, bufend - bufptr);

  if (!access(buffer, 0))
  {
    DEBUG_printf(("1cupsFileFind: Returning \"%s\"", buffer));
    return (buffer);
  }
  else
  {
    DEBUG_puts("1cupsFileFind: Returning NULL");
    return (NULL);
  }
}
Exemple #12
0
void
cupsdAddCert(int        pid,		/* I - Process ID */
             const char *username,	/* I - Username */
             int        type)		/* I - AuthType for username */
{
  int		i;			/* Looping var */
  cupsd_cert_t	*cert;			/* Current certificate */
  int		fd;			/* Certificate file */
  char		filename[1024];		/* Certificate filename */
  static const char hex[] = "0123456789ABCDEF";
					/* Hex constants... */


  cupsdLogMessage(CUPSD_LOG_DEBUG2,
                  "cupsdAddCert: Adding certificate for PID %d", pid);

 /*
  * Allocate memory for the certificate...
  */

  if ((cert = calloc(sizeof(cupsd_cert_t), 1)) == NULL)
    return;

 /*
  * Fill in the certificate information...
  */

  cert->pid  = pid;
  cert->type = type;
  strlcpy(cert->username, username, sizeof(cert->username));

  for (i = 0; i < 32; i ++)
    cert->certificate[i] = hex[CUPS_RAND() & 15];

 /*
  * Save the certificate to a file readable only by the User and Group
  * (or root and SystemGroup for PID == 0)...
  */

  snprintf(filename, sizeof(filename), "%s/certs/%d", StateDir, pid);
  unlink(filename);

  if ((fd = open(filename, O_WRONLY | O_CREAT | O_EXCL, 0400)) < 0)
  {
    cupsdLogMessage(CUPSD_LOG_ERROR,
                    "Unable to create certificate file %s - %s",
                    filename, strerror(errno));
    free(cert);
    return;
  }

  if (pid == 0)
  {
#ifdef HAVE_ACL_INIT
    acl_t		acl;		/* ACL information */
    acl_entry_t		entry;		/* ACL entry */
    acl_permset_t	permset;	/* Permissions */
#  ifdef HAVE_MBR_UID_TO_UUID
    uuid_t		group;		/* Group ID */
#  endif /* HAVE_MBR_UID_TO_UUID */
    static int		acls_not_supported = 0;
					/* Only warn once */
#endif /* HAVE_ACL_INIT */


   /*
    * Root certificate...
    */

    fchmod(fd, 0440);
    fchown(fd, RunUser, SystemGroupIDs[0]);

    cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdAddCert: NumSystemGroups=%d",
                    NumSystemGroups);

#ifdef HAVE_ACL_INIT
    if (NumSystemGroups > 1)
    {
     /*
      * Set POSIX ACLs for the root certificate so that all system
      * groups can access it...
      */

      int	j;			/* Looping var */

#  ifdef HAVE_MBR_UID_TO_UUID
     /*
      * On MacOS X, ACLs use UUIDs instead of GIDs...
      */

      acl = acl_init(NumSystemGroups - 1);

      for (i = 1; i < NumSystemGroups; i ++)
      {
       /*
        * Add each group ID to the ACL...
	*/

        for (j = 0; j < i; j ++)
	  if (SystemGroupIDs[j] == SystemGroupIDs[i])
            break;

        if (j < i)
          continue;			/* Skip duplicate groups */

        acl_create_entry(&acl, &entry);
	acl_get_permset(entry, &permset);
	acl_add_perm(permset, ACL_READ_DATA);
	acl_set_tag_type(entry, ACL_EXTENDED_ALLOW);
	mbr_gid_to_uuid((gid_t)SystemGroupIDs[i], group);
	acl_set_qualifier(entry, &group);
	acl_set_permset(entry, permset);
      }

#  else
     /*
      * POSIX ACLs need permissions for owner, group, other, and mask
      * in addition to the rest of the system groups...
      */

      acl = acl_init(NumSystemGroups + 3);

      /* Owner */
      acl_create_entry(&acl, &entry);
      acl_get_permset(entry, &permset);
      acl_add_perm(permset, ACL_READ);
      acl_set_tag_type(entry, ACL_USER_OBJ);
      acl_set_permset(entry, permset);

      /* Group */
      acl_create_entry(&acl, &entry);
      acl_get_permset(entry, &permset);
      acl_add_perm(permset, ACL_READ);
      acl_set_tag_type(entry, ACL_GROUP_OBJ);
      acl_set_permset(entry, permset);

      /* Others */
      acl_create_entry(&acl, &entry);
      acl_get_permset(entry, &permset);
      acl_add_perm(permset, 0);
      acl_set_tag_type(entry, ACL_OTHER);
      acl_set_permset(entry, permset);

      /* Mask */
      acl_create_entry(&acl, &entry);
      acl_get_permset(entry, &permset);
      acl_add_perm(permset, ACL_READ);
      acl_set_tag_type(entry, ACL_MASK);
      acl_set_permset(entry, permset);

      for (i = 1; i < NumSystemGroups; i ++)
      {
       /*
        * Add each group ID to the ACL...
	*/

        for (j = 0; j < i; j ++)
	  if (SystemGroupIDs[j] == SystemGroupIDs[i])
            break;

        if (j < i)
          continue;			/* Skip duplicate groups */

        acl_create_entry(&acl, &entry);
	acl_get_permset(entry, &permset);
	acl_add_perm(permset, ACL_READ);
	acl_set_tag_type(entry, ACL_GROUP);
	acl_set_qualifier(entry, SystemGroupIDs + i);
	acl_set_permset(entry, permset);
      }

      if (acl_valid(acl))
      {
        char *text, *textptr;		/* Temporary string */

        cupsdLogMessage(CUPSD_LOG_ERROR, "ACL did not validate: %s",
	                strerror(errno));
        text = acl_to_text(acl, NULL);
	for (textptr = strchr(text, '\n');
	     textptr;
	     textptr = strchr(textptr + 1, '\n'))
	  *textptr = ',';

	cupsdLogMessage(CUPSD_LOG_ERROR, "ACL: %s", text);
	acl_free(text);
      }
#  endif /* HAVE_MBR_UID_TO_UUID */

      if (acl_set_fd(fd, acl))
      {
	if (errno != EOPNOTSUPP || !acls_not_supported)
	  cupsdLogMessage(CUPSD_LOG_ERROR,
			  "Unable to set ACLs on root certificate \"%s\" - %s",
			  filename, strerror(errno));

	if (errno == EOPNOTSUPP)
	  acls_not_supported = 1;
      }

      acl_free(acl);
    }
#endif /* HAVE_ACL_INIT */

    RootCertTime = time(NULL);
  }
  else
  {
   /*
    * CGI certificate...
    */

    fchmod(fd, 0400);
    fchown(fd, User, Group);
  }

  DEBUG_printf(("ADD pid=%d, username=%s, cert=%s\n", pid, username,
                cert->certificate));

  write(fd, cert->certificate, strlen(cert->certificate));
  close(fd);

 /*
  * Insert the certificate at the front of the list...
  */

  cert->next = Certs;
  Certs      = cert;
}
Exemple #13
0
void *gc_realloc(void *ptr_in, size_t n_bytes, bool allow_move) {
    if (MP_STATE_MEM(gc_lock_depth) > 0) {
        return NULL;
    }

    // check for pure allocation
    if (ptr_in == NULL) {
        return gc_alloc(n_bytes, false);
    }

    // check for pure free
    if (n_bytes == 0) {
        gc_free(ptr_in);
        return NULL;
    }

    void *ptr = ptr_in;

    // sanity check the ptr
    if (!VERIFY_PTR(ptr)) {
        return NULL;
    }

    // get first block
    size_t block = BLOCK_FROM_PTR(ptr);

    // sanity check the ptr is pointing to the head of a block
    if (ATB_GET_KIND(block) != AT_HEAD) {
        return NULL;
    }

    // compute number of new blocks that are requested
    size_t new_blocks = (n_bytes + BYTES_PER_BLOCK - 1) / BYTES_PER_BLOCK;

    // Get the total number of consecutive blocks that are already allocated to
    // this chunk of memory, and then count the number of free blocks following
    // it.  Stop if we reach the end of the heap, or if we find enough extra
    // free blocks to satisfy the realloc.  Note that we need to compute the
    // total size of the existing memory chunk so we can correctly and
    // efficiently shrink it (see below for shrinking code).
    size_t n_free   = 0;
    size_t n_blocks = 1; // counting HEAD block
    size_t max_block = MP_STATE_MEM(gc_alloc_table_byte_len) * BLOCKS_PER_ATB;
    for (size_t bl = block + n_blocks; bl < max_block; bl++) {
        byte block_type = ATB_GET_KIND(bl);
        if (block_type == AT_TAIL) {
            n_blocks++;
            continue;
        }
        if (block_type == AT_FREE) {
            n_free++;
            if (n_blocks + n_free >= new_blocks) {
                // stop as soon as we find enough blocks for n_bytes
                break;
            }
            continue;
        }
        break;
    }

    // return original ptr if it already has the requested number of blocks
    if (new_blocks == n_blocks) {
        return ptr_in;
    }

    // check if we can shrink the allocated area
    if (new_blocks < n_blocks) {
        // free unneeded tail blocks
        for (size_t bl = block + new_blocks, count = n_blocks - new_blocks; count > 0; bl++, count--) {
            ATB_ANY_TO_FREE(bl);
        }

        // set the last_free pointer to end of this block if it's earlier in the heap
        if ((block + new_blocks) / BLOCKS_PER_ATB < MP_STATE_MEM(gc_last_free_atb_index)) {
            MP_STATE_MEM(gc_last_free_atb_index) = (block + new_blocks) / BLOCKS_PER_ATB;
        }

        #if EXTENSIVE_HEAP_PROFILING
        gc_dump_alloc_table();
        #endif

        return ptr_in;
    }

    // check if we can expand in place
    if (new_blocks <= n_blocks + n_free) {
        // mark few more blocks as used tail
        for (size_t bl = block + n_blocks; bl < block + new_blocks; bl++) {
            assert(ATB_GET_KIND(bl) == AT_FREE);
            ATB_FREE_TO_TAIL(bl);
        }

        // zero out the additional bytes of the newly allocated blocks (see comment above in gc_alloc)
        memset((byte*)ptr_in + n_bytes, 0, new_blocks * BYTES_PER_BLOCK - n_bytes);

        #if EXTENSIVE_HEAP_PROFILING
        gc_dump_alloc_table();
        #endif

        return ptr_in;
    }

    if (!allow_move) {
        // not allowed to move memory block so return failure
        return NULL;
    }

    // can't resize inplace; try to find a new contiguous chain
    void *ptr_out = gc_alloc(n_bytes,
#if MICROPY_ENABLE_FINALISER
        FTB_GET(block)
#else
        false
#endif
    );

    // check that the alloc succeeded
    if (ptr_out == NULL) {
        return NULL;
    }

    DEBUG_printf("gc_realloc(%p -> %p)\n", ptr_in, ptr_out);
    memcpy(ptr_out, ptr_in, n_blocks * BYTES_PER_BLOCK);
    gc_free(ptr_in);
    return ptr_out;
}
Exemple #14
0
void *gc_alloc(size_t n_bytes, bool has_finaliser) {
    size_t n_blocks = ((n_bytes + BYTES_PER_BLOCK - 1) & (~(BYTES_PER_BLOCK - 1))) / BYTES_PER_BLOCK;
    DEBUG_printf("gc_alloc(" UINT_FMT " bytes -> " UINT_FMT " blocks)\n", n_bytes, n_blocks);

    // check if GC is locked
    if (MP_STATE_MEM(gc_lock_depth) > 0) {
        return NULL;
    }

    // check for 0 allocation
    if (n_blocks == 0) {
        return NULL;
    }

    size_t i;
    size_t end_block;
    size_t start_block;
    size_t n_free = 0;
    int collected = !MP_STATE_MEM(gc_auto_collect_enabled);
    for (;;) {

        // look for a run of n_blocks available blocks
        for (i = MP_STATE_MEM(gc_last_free_atb_index); i < MP_STATE_MEM(gc_alloc_table_byte_len); i++) {
            byte a = MP_STATE_MEM(gc_alloc_table_start)[i];
            if (ATB_0_IS_FREE(a)) { if (++n_free >= n_blocks) { i = i * BLOCKS_PER_ATB + 0; goto found; } } else { n_free = 0; }
            if (ATB_1_IS_FREE(a)) { if (++n_free >= n_blocks) { i = i * BLOCKS_PER_ATB + 1; goto found; } } else { n_free = 0; }
            if (ATB_2_IS_FREE(a)) { if (++n_free >= n_blocks) { i = i * BLOCKS_PER_ATB + 2; goto found; } } else { n_free = 0; }
            if (ATB_3_IS_FREE(a)) { if (++n_free >= n_blocks) { i = i * BLOCKS_PER_ATB + 3; goto found; } } else { n_free = 0; }
        }

        // nothing found!
        if (collected) {
            return NULL;
        }
        DEBUG_printf("gc_alloc(" UINT_FMT "): no free mem, triggering GC\n", n_bytes);
        gc_collect();
        collected = 1;
    }

    // found, ending at block i inclusive
found:
    // get starting and end blocks, both inclusive
    end_block = i;
    start_block = i - n_free + 1;

    // Set last free ATB index to block after last block we found, for start of
    // next scan.  To reduce fragmentation, we only do this if we were looking
    // for a single free block, which guarantees that there are no free blocks
    // before this one.  Also, whenever we free or shink a block we must check
    // if this index needs adjusting (see gc_realloc and gc_free).
    if (n_free == 1) {
        MP_STATE_MEM(gc_last_free_atb_index) = (i + 1) / BLOCKS_PER_ATB;
    }

    // mark first block as used head
    ATB_FREE_TO_HEAD(start_block);

    // mark rest of blocks as used tail
    // TODO for a run of many blocks can make this more efficient
    for (size_t bl = start_block + 1; bl <= end_block; bl++) {
        ATB_FREE_TO_TAIL(bl);
    }

    // get pointer to first block
    void *ret_ptr = (void*)(MP_STATE_MEM(gc_pool_start) + start_block * BYTES_PER_BLOCK);
    DEBUG_printf("gc_alloc(%p)\n", ret_ptr);

    // zero out the additional bytes of the newly allocated blocks
    // This is needed because the blocks may have previously held pointers
    // to the heap and will not be set to something else if the caller
    // doesn't actually use the entire block.  As such they will continue
    // to point to the heap and may prevent other blocks from being reclaimed.
    memset((byte*)ret_ptr + n_bytes, 0, (end_block - start_block + 1) * BYTES_PER_BLOCK - n_bytes);

    #if MICROPY_ENABLE_FINALISER
    if (has_finaliser) {
        // clear type pointer in case it is never set
        ((mp_obj_base_t*)ret_ptr)->type = NULL;
        // set mp_obj flag only if it has a finaliser
        FTB_SET(start_block);
    }
    #else
    (void)has_finaliser;
    #endif

    #if EXTENSIVE_HEAP_PROFILING
    gc_dump_alloc_table();
    #endif

    return ret_ptr;
}
STATIC mp_uint_t lwip_socket_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) {
    lwip_socket_obj_t *socket = self_in;
    mp_uint_t ret;

    if (request == MP_STREAM_POLL) {
        uintptr_t flags = arg;
        ret = 0;

        if (flags & MP_STREAM_POLL_RD && socket->incoming.pbuf != NULL) {
            ret |= MP_STREAM_POLL_RD;
        }

        // Note: pcb.tcp==NULL if state<0, and in this case we can't call tcp_sndbuf
        if (flags & MP_STREAM_POLL_WR && socket->pcb.tcp != NULL && tcp_sndbuf(socket->pcb.tcp) > 0) {
            ret |= MP_STREAM_POLL_WR;
        }

        if (socket->state == STATE_NEW) {
            // New sockets are not connected so set HUP
            ret |= flags & MP_STREAM_POLL_HUP;
        } else if (socket->state == STATE_PEER_CLOSED) {
            // Peer-closed socket is both readable and writable: read will
            // return EOF, write - error. Without this poll will hang on a
            // socket which was closed by peer.
            ret |= flags & (MP_STREAM_POLL_RD | MP_STREAM_POLL_WR);
        } else if (socket->state == ERR_RST) {
            // Socket was reset by peer, a write will return an error
            ret |= flags & (MP_STREAM_POLL_WR | MP_STREAM_POLL_HUP);
        } else if (socket->state < 0) {
            // Socket in some other error state, use catch-all ERR flag
            // TODO: may need to set other return flags here
            ret |= flags & MP_STREAM_POLL_ERR;
        }

    } else if (request == MP_STREAM_CLOSE) {
        bool socket_is_listener = false;

        if (socket->pcb.tcp == NULL) {
            return 0;
        }
        switch (socket->type) {
            case MOD_NETWORK_SOCK_STREAM: {
                if (socket->pcb.tcp->state == LISTEN) {
                    socket_is_listener = true;
                }
                if (tcp_close(socket->pcb.tcp) != ERR_OK) {
                    DEBUG_printf("lwip_close: had to call tcp_abort()\n");
                    tcp_abort(socket->pcb.tcp);
                }
                break;
            }
            case MOD_NETWORK_SOCK_DGRAM: udp_remove(socket->pcb.udp); break;
            //case MOD_NETWORK_SOCK_RAW: raw_remove(socket->pcb.raw); break;
        }
        socket->pcb.tcp = NULL;
        socket->state = _ERR_BADF;
        if (socket->incoming.pbuf != NULL) {
            if (!socket_is_listener) {
                pbuf_free(socket->incoming.pbuf);
            } else {
                tcp_abort(socket->incoming.connection);
            }
            socket->incoming.pbuf = NULL;
        }
        ret = 0;

    } else {
        *errcode = MP_EINVAL;
        ret = MP_STREAM_ERROR;
    }

    return ret;
}
Exemple #16
0
char *					/* O - Line read or @code NULL@ on end of file or error */
cupsFileGets(cups_file_t *fp,		/* I - CUPS file */
             char        *buf,		/* O - String buffer */
	     size_t      buflen)	/* I - Size of string buffer */
{
  int		ch;			/* Character from file */
  char		*ptr,			/* Current position in line buffer */
		*end;			/* End of line buffer */


 /*
  * Range check input...
  */

  DEBUG_printf(("2cupsFileGets(fp=%p, buf=%p, buflen=" CUPS_LLFMT ")", fp, buf,
                CUPS_LLCAST buflen));

  if (!fp || (fp->mode != 'r' && fp->mode != 's') || !buf || buflen < 2)
    return (NULL);

 /*
  * Now loop until we have a valid line...
  */

  for (ptr = buf, end = buf + buflen - 1; ptr < end ;)
  {
    if (fp->ptr >= fp->end)
      if (cups_fill(fp) <= 0)
      {
        if (ptr == buf)
	  return (NULL);
	else
          break;
      }

    ch = *(fp->ptr)++;
    fp->pos ++;

    if (ch == '\r')
    {
     /*
      * Check for CR LF...
      */

      if (fp->ptr >= fp->end)
	if (cups_fill(fp) <= 0)
          break;

      if (*(fp->ptr) == '\n')
      {
        fp->ptr ++;
	fp->pos ++;
      }

      break;
    }
    else if (ch == '\n')
    {
     /*
      * Line feed ends a line...
      */

      break;
    }
    else
      *ptr++ = ch;
  }

  *ptr = '\0';

  DEBUG_printf(("4cupsFileGets: pos=" CUPS_LLFMT, CUPS_LLCAST fp->pos));

  return (buf);
}
Exemple #17
0
static int				/* O - 1 if form data was read */
cgi_initialize_multipart(
    const char *boundary)		/* I - Boundary string */
{
  char		line[10240],		/* MIME header line */
		name[1024],		/* Form variable name */
		filename[1024],		/* Form filename */
		mimetype[1024],		/* MIME media type */
		bstring[256],		/* Boundary string to look for */
		*ptr,			/* Pointer into name/filename */
		*end;			/* End of buffer */
  int		ch,			/* Character from file */
		fd;			/* Temporary file descriptor */
  size_t	blen;			/* Length of boundary string */


  DEBUG_printf(("cgi_initialize_multipart(boundary=\"%s\")\n", boundary));

 /*
  * Read multipart form data until we run out...
  */

  name[0]     = '\0';
  filename[0] = '\0';
  mimetype[0] = '\0';

  snprintf(bstring, sizeof(bstring), "\r\n--%s", boundary);
  blen = strlen(bstring);

  while (fgets(line, sizeof(line), stdin))
  {
    if (!strcmp(line, "\r\n"))
    {
     /*
      * End of headers, grab value...
      */

      if (filename[0])
      {
       /*
        * Read an embedded file...
	*/

        if (form_file)
	{
	 /*
	  * Remove previous file...
	  */

	  cgi_unlink_file();
	}

       /*
        * Allocate memory for the new file...
	*/

	if ((form_file = calloc(1, sizeof(cgi_file_t))) == NULL)
	  return (0);

        form_file->name     = strdup(name);
	form_file->filename = strdup(filename);
	form_file->mimetype = strdup(mimetype);

        fd = cupsTempFd(form_file->tempfile, sizeof(form_file->tempfile));

        if (fd < 0)
	  return (0);

        atexit(cgi_unlink_file);

       /*
        * Copy file data to the temp file...
	*/

        ptr = line;

	while ((ch = getchar()) != EOF)
	{
	  *ptr++ = (char)ch;

          if ((size_t)(ptr - line) >= blen && !memcmp(ptr - blen, bstring, blen))
	  {
	    ptr -= blen;
	    break;
	  }

          if ((ptr - line - (int)blen) >= 8192)
	  {
	   /*
	    * Write out the first 8k of the buffer...
	    */

	    write(fd, line, 8192);
	    memmove(line, line + 8192, (size_t)(ptr - line - 8192));
	    ptr -= 8192;
	  }
	}

       /*
        * Write the rest of the data and close the temp file...
	*/

	if (ptr > line)
          write(fd, line, (size_t)(ptr - line));

	close(fd);
      }
      else
      {
       /*
        * Just get a form variable; the current code only handles
	* form values up to 10k in size...
	*/

        ptr = line;
	end = line + sizeof(line) - 1;

	while ((ch = getchar()) != EOF)
	{
	  if (ptr < end)
	    *ptr++ = (char)ch;

          if ((size_t)(ptr - line) >= blen && !memcmp(ptr - blen, bstring, blen))
	  {
	    ptr -= blen;
	    break;
	  }
	}

	*ptr = '\0';

       /*
        * Set the form variable...
	*/

	if ((ptr = strrchr(name, '-')) != NULL && isdigit(ptr[1] & 255))
	{
	 /*
	  * Set a specific index in the array...
	  */

	  *ptr++ = '\0';
	  if (line[0])
            cgiSetArray(name, atoi(ptr) - 1, line);
	}
	else if (cgiGetVariable(name))
	{
	 /*
	  * Add another element in the array...
	  */

	  cgiSetArray(name, cgiGetSize(name), line);
	}
	else
	{
	 /*
	  * Just set the line...
	  */

	  cgiSetVariable(name, line);
	}
      }

     /*
      * Read the rest of the current line...
      */

      fgets(line, sizeof(line), stdin);

     /*
      * Clear the state vars...
      */

      name[0]     = '\0';
      filename[0] = '\0';
      mimetype[0] = '\0';
    }
    else if (!_cups_strncasecmp(line, "Content-Disposition:", 20))
    {
      if ((ptr = strstr(line + 20, " name=\"")) != NULL)
      {
        strlcpy(name, ptr + 7, sizeof(name));

	if ((ptr = strchr(name, '\"')) != NULL)
	  *ptr = '\0';
      }

      if ((ptr = strstr(line + 20, " filename=\"")) != NULL)
      {
        strlcpy(filename, ptr + 11, sizeof(filename));

	if ((ptr = strchr(filename, '\"')) != NULL)
	  *ptr = '\0';
      }
    }
    else if (!_cups_strncasecmp(line, "Content-Type:", 13))
    {
      for (ptr = line + 13; isspace(*ptr & 255); ptr ++);

      strlcpy(mimetype, ptr, sizeof(mimetype));

      for (ptr = mimetype + strlen(mimetype) - 1;
           ptr > mimetype && isspace(*ptr & 255);
	   *ptr-- = '\0');
    }
  }

 /*
  * Return 1 for "form data found"...
  */

  return (1);
}
Exemple #18
0
cups_file_t *				/* O - CUPS file or @code NULL@ if the file or socket cannot be opened */
cupsFileOpen(const char *filename,	/* I - Name of file */
             const char *mode)		/* I - Open mode */
{
  cups_file_t	*fp;			/* New CUPS file */
  int		fd;			/* File descriptor */
  char		hostname[1024],		/* Hostname */
		*portname;		/* Port "name" (number or service) */
  http_addrlist_t *addrlist;		/* Host address list */


  DEBUG_printf(("cupsFileOpen(filename=\"%s\", mode=\"%s\")", filename,
                mode));

 /*
  * Range check input...
  */

  if (!filename || !mode ||
      (*mode != 'r' && *mode != 'w' && *mode != 'a' && *mode != 's') ||
      (*mode == 'a' && isdigit(mode[1] & 255)))
    return (NULL);

 /*
  * Open the file...
  */

  switch (*mode)
  {
    case 'a' : /* Append file */
        fd = cups_open(filename,
		       O_RDWR | O_CREAT | O_APPEND | O_LARGEFILE | O_BINARY);
        break;

    case 'r' : /* Read file */
	fd = open(filename, O_RDONLY | O_LARGEFILE | O_BINARY, 0);
	break;

    case 'w' : /* Write file */
        fd = cups_open(filename, O_WRONLY | O_LARGEFILE | O_BINARY);
	if (fd < 0 && errno == ENOENT)
	{
	  fd = cups_open(filename,
	                 O_WRONLY | O_CREAT | O_EXCL | O_LARGEFILE | O_BINARY);
	  if (fd < 0 && errno == EEXIST)
	    fd = cups_open(filename, O_WRONLY | O_LARGEFILE | O_BINARY);
	}

	if (fd >= 0)
#ifdef WIN32
	  _chsize(fd, 0);
#else
	  ftruncate(fd, 0);
#endif /* WIN32 */
        break;

    case 's' : /* Read/write socket */
        strlcpy(hostname, filename, sizeof(hostname));
	if ((portname = strrchr(hostname, ':')) != NULL)
	  *portname++ = '\0';
	else
	  return (NULL);

       /*
        * Lookup the hostname and service...
	*/

        if ((addrlist = httpAddrGetList(hostname, AF_UNSPEC, portname)) == NULL)
	  return (NULL);

       /*
	* Connect to the server...
	*/

        if (!httpAddrConnect(addrlist, &fd))
	{
	  httpAddrFreeList(addrlist);
	  return (NULL);
	}

	httpAddrFreeList(addrlist);
	break;

    default : /* Remove bogus compiler warning... */
        return (NULL);
  }

  if (fd < 0)
    return (NULL);

 /*
  * Create the CUPS file structure...
  */

  if ((fp = cupsFileOpenFd(fd, mode)) == NULL)
  {
    if (*mode == 's')
      closesocket(fd);
    else
      close(fd);
  }

 /*
  * Return it...
  */

  return (fp);
}
int write_bb_black_respond(char* fileName,char *rev)
{
    long len;
    char sw[15];

    char uid[60];
    char ip_s[20];
    char port_s[10];
    char port_l[10];
    char* pContent;
    //First read the old config
    FILE* fp = fopen(fileName, "rb+");
    if(fp==NULL)
    {
        DEBUG_printf("open error\n");
        exit(1);
    }
    fseek(fp,0,SEEK_END);
    len=ftell(fp);
    if(0 == len)
    {
        return 0;
    }
    fseek(fp,0,SEEK_SET);
    pContent = (char*) malloc(sizeof(char)*len+100);
    fread(pContent,1,len,fp);
    fclose(fp);
    cJSON *jsonroot = cJSON_Parse(pContent); //json
    strcpy(sw,cJSON_GetObjectItem(jsonroot,"api-switch")->valuestring);
    strcpy(uid,cJSON_GetObjectItem(jsonroot,"api-uid")->valuestring);

    strcpy(ip_s,cJSON_GetObjectItem(jsonroot,"ip_server")->valuestring);
    strcpy(port_s,cJSON_GetObjectItem(jsonroot,"port_server")->valuestring);
    strcpy(port_l,cJSON_GetObjectItem(jsonroot,"port_local")->valuestring);
    cJSON_Delete(jsonroot);
    //Write configuration, update
    fp = fopen(fileName, "w+");
    if(fp==NULL)
    {
        DEBUG_printf("open error\n");
    }
    cJSON *root;
    char *out;
    root=cJSON_CreateObject();
    cJSON_AddStringToObject(root, "api-switch" , sw);
    cJSON_AddStringToObject(root, "api-uid", uid);
    cJSON_AddStringToObject(root, "auth", rev);
    cJSON_AddStringToObject(root, "ip_server" ,ip_s);
    cJSON_AddStringToObject(root, "port_server", port_s);
    cJSON_AddStringToObject(root, "port_local", port_l);
    out=cJSON_Print(root);
    fprintf(fp,"%s",out);
    fclose(fp);

    cJSON_Delete(root);
    free(out);
    out = NULL;
    root = NULL;
    free(pContent);
    return 1;
}
Exemple #20
0
int					/* O - 0 on success, -1 on error */
cupsFileClose(cups_file_t *fp)		/* I - CUPS file */
{
  int	fd;				/* File descriptor */
  char	mode;				/* Open mode */
  int	status;				/* Return status */
  int	is_stdio;			/* Is a stdio file? */


  DEBUG_printf(("cupsFileClose(fp=%p)", fp));

 /*
  * Range check...
  */

  if (!fp)
    return (-1);

 /*
  * Flush pending write data...
  */

  if (fp->mode == 'w')
    status = cupsFileFlush(fp);
  else
    status = 0;

#ifdef HAVE_LIBZ
  if (fp->compressed && status >= 0)
  {
    if (fp->mode == 'r')
    {
     /*
      * Free decompression data...
      */

      inflateEnd(&fp->stream);
    }
    else
    {
     /*
      * Flush any remaining compressed data...
      */

      unsigned char	trailer[8];	/* Trailer CRC and length */
      int		done;		/* Done writing... */


      fp->stream.avail_in = 0;

      for (done = 0;;)
      {
        if (fp->stream.next_out > fp->cbuf)
	{
	  if (cups_write(fp, (char *)fp->cbuf,
	                 fp->stream.next_out - fp->cbuf) < 0)
	    status = -1;

	  fp->stream.next_out  = fp->cbuf;
	  fp->stream.avail_out = sizeof(fp->cbuf);
	}

        if (done || status < 0)
	  break;

        done = deflate(&fp->stream, Z_FINISH) == Z_STREAM_END &&
	       fp->stream.next_out == fp->cbuf;
      }

     /*
      * Write the CRC and length...
      */

      trailer[0] = fp->crc;
      trailer[1] = fp->crc >> 8;
      trailer[2] = fp->crc >> 16;
      trailer[3] = fp->crc >> 24;
      trailer[4] = fp->pos;
      trailer[5] = fp->pos >> 8;
      trailer[6] = fp->pos >> 16;
      trailer[7] = fp->pos >> 24;

      if (cups_write(fp, (char *)trailer, 8) < 0)
        status = -1;

     /*
      * Free all memory used by the compression stream...
      */

      deflateEnd(&(fp->stream));
    }
  }
#endif /* HAVE_LIBZ */

 /*
  * Save the file descriptor we used and free memory...
  */

  fd       = fp->fd;
  mode     = fp->mode;
  is_stdio = fp->is_stdio;

  if (fp->printf_buffer)
    free(fp->printf_buffer);

  free(fp);

 /*
  * Close the file, returning the close status...
  */

  if (mode == 's')
  {
    if (closesocket(fd) < 0)
      status = -1;
  }
  else if (!is_stdio)
  {
    if (close(fd) < 0)
      status = -1;
  }

  return (status);
}
Exemple #21
0
void *					/* O - Search context */
cgiCompileSearch(const char *query)	/* I - Query string */
{
  regex_t	*re;			/* Regular expression */
  char		*s,			/* Regular expression string */
		*sptr,			/* Pointer into RE string */
		*sword;			/* Pointer to start of word */
  int		slen;			/* Allocated size of RE string */
  const char	*qptr,			/* Pointer into query string */
		*qend;			/* End of current word */
  const char	*prefix;		/* Prefix to add to next word */
  int		quoted;			/* Word is quoted */
  int		wlen;			/* Word length */
  char		*lword;			/* Last word in query */


  DEBUG_printf(("cgiCompileSearch(query=\"%s\")\n", query));

 /*
  * Range check input...
  */

  if (!query)
    return (NULL);

 /*
  * Allocate a regular expression storage structure...
  */

  if ((re = (regex_t *)calloc(1, sizeof(regex_t))) == NULL)
    return (NULL);

 /*
  * Allocate a buffer to hold the regular expression string, starting
  * at 1024 bytes or 3 times the length of the query string, whichever
  * is greater.  We'll expand the string as needed...
  */

  slen = strlen(query) * 3;
  if (slen < 1024)
    slen = 1024;

  if ((s = (char *)malloc(slen)) == NULL)
  {
    free(re);
    return (NULL);
  }

 /*
  * Copy the query string to the regular expression, handling basic
  * AND and OR logic...
  */

  prefix = ".*";
  qptr   = query;
  sptr   = s;
  lword  = NULL;

  while (*qptr)
  {
   /*
    * Skip leading whitespace...
    */

    while (isspace(*qptr & 255))
      qptr ++;

    if (!*qptr)
      break;

   /*
    * Find the end of the current word...
    */

    if (*qptr == '\"' || *qptr == '\'')
    {
     /*
      * Scan quoted string...
      */

      quoted = *qptr ++;
      for (qend = qptr; *qend && *qend != quoted; qend ++);

      if (!*qend)
      {
       /*
        * No closing quote, error out!
	*/

	free(s);
	free(re);

	if (lword)
          free(lword);

	return (NULL);
      }
    }
    else
    {
     /*
      * Scan whitespace-delimited string...
      */

      quoted = 0;
      for (qend = qptr + 1; *qend && !isspace(*qend); qend ++);
    }

    wlen = qend - qptr;

   /*
    * Look for logic words: AND, OR
    */

    if (wlen == 3 && !_cups_strncasecmp(qptr, "AND", 3))
    {
     /*
      * Logical AND with the following text...
      */

      if (sptr > s)
        prefix = ".*";

      qptr = qend;
    }
    else if (wlen == 2 && !_cups_strncasecmp(qptr, "OR", 2))
    {
     /*
      * Logical OR with the following text...
      */

      if (sptr > s)
        prefix = ".*|.*";

      qptr = qend;
    }
    else
    {
     /*
      * Add a search word, making sure we have enough room for the
      * string + RE overhead...
      */

      wlen = (sptr - s) + 2 * 4 * wlen + 2 * strlen(prefix) + 11;
      if (lword)
        wlen += strlen(lword);

      if (wlen > slen)
      {
       /*
        * Expand the RE string buffer...
	*/

        char *temp;			/* Temporary string pointer */


	slen = wlen + 128;
        temp = (char *)realloc(s, slen);
	if (!temp)
	{
	  free(s);
	  free(re);

	  if (lword)
            free(lword);

	  return (NULL);
	}

        sptr = temp + (sptr - s);
	s    = temp;
      }

     /*
      * Add the prefix string...
      */

      memcpy(sptr, prefix, strlen(prefix) + 1);
      sptr += strlen(sptr);

     /*
      * Then quote the remaining word characters as needed for the
      * RE...
      */

      sword = sptr;

      while (qptr < qend)
      {
       /*
        * Quote: ^ . [ $ ( ) | * + ? { \
	*/

        if (strchr("^.[$()|*+?{\\", *qptr))
	  *sptr++ = '\\';

	*sptr++ = *qptr++;
      }

      *sptr = '\0';

     /*
      * For "word1 AND word2", add reciprocal "word2 AND word1"...
      */

      if (!strcmp(prefix, ".*") && lword)
      {
        char *lword2;			/* New "last word" */


        if ((lword2 = strdup(sword)) == NULL)
	{
	  free(lword);
	  free(s);
	  free(re);
	  return (NULL);
	}

        memcpy(sptr, ".*|.*", 6);
	sptr += 5;

	memcpy(sptr, lword2, strlen(lword2) + 1);
	sptr += strlen(sptr);

        memcpy(sptr, ".*", 3);
	sptr += 2;

	memcpy(sptr, lword, strlen(lword) + 1);
	sptr += strlen(sptr);

        free(lword);
	lword = lword2;
      }
      else
      {
	if (lword)
          free(lword);

	lword = strdup(sword);
      }

      prefix = ".*|.*";
    }

   /*
    * Advance to the next string...
    */

    if (quoted)
      qptr ++;
  }

  if (lword)
    free(lword);

  if (sptr > s)
    memcpy(sptr, ".*", 3);
  else
  {
   /*
    * No query data, return NULL...
    */

    free(s);
    free(re);

    return (NULL);
  }

 /*
  * Compile the regular expression...
  */

  DEBUG_printf(("    s=\"%s\"\n", s));

  if (regcomp(re, s, REG_EXTENDED | REG_ICASE))
  {
    free(re);
    free(s);

    return (NULL);
  }

 /*
  * Free the RE string and return the new regular expression we compiled...
  */

  free(s);

  return ((void *)re);
}
Exemple #22
0
cups_file_t *				/* O - CUPS file or @code NULL@ if the file could not be opened */
cupsFileOpenFd(int        fd,		/* I - File descriptor */
	       const char *mode)	/* I - Open mode */
{
  cups_file_t	*fp;			/* New CUPS file */


  DEBUG_printf(("cupsFileOpenFd(fd=%d, mode=\"%s\")", fd, mode));

 /*
  * Range check input...
  */

  if (fd < 0 || !mode ||
      (*mode != 'r' && *mode != 'w' && *mode != 'a' && *mode != 's') ||
      (*mode == 'a' && isdigit(mode[1] & 255)))
    return (NULL);

 /*
  * Allocate memory...
  */

  if ((fp = calloc(1, sizeof(cups_file_t))) == NULL)
    return (NULL);

 /*
  * Open the file...
  */

  fp->fd = fd;

  switch (*mode)
  {
    case 'a' :
        fp->pos = lseek(fd, 0, SEEK_END);

    case 'w' :
	fp->mode = 'w';
	fp->ptr  = fp->buf;
	fp->end  = fp->buf + sizeof(fp->buf);

#ifdef HAVE_LIBZ
	if (mode[1] >= '1' && mode[1] <= '9')
	{
	 /*
	  * Open a compressed stream, so write the standard gzip file
	  * header...
	  */

          unsigned char header[10];	/* gzip file header */
	  time_t	curtime;	/* Current time */


          curtime   = time(NULL);
	  header[0] = 0x1f;
	  header[1] = 0x8b;
	  header[2] = Z_DEFLATED;
	  header[3] = 0;
	  header[4] = curtime;
	  header[5] = curtime >> 8;
	  header[6] = curtime >> 16;
	  header[7] = curtime >> 24;
	  header[8] = 0;
	  header[9] = 0x03;

	  cups_write(fp, (char *)header, 10);

         /*
	  * Initialize the compressor...
	  */

          deflateInit2(&(fp->stream), mode[1] - '0', Z_DEFLATED, -15, 8,
	               Z_DEFAULT_STRATEGY);

	  fp->stream.next_out  = fp->cbuf;
	  fp->stream.avail_out = sizeof(fp->cbuf);
	  fp->compressed       = 1;
	  fp->crc              = crc32(0L, Z_NULL, 0);
	}
#endif /* HAVE_LIBZ */
        break;

    case 'r' :
	fp->mode = 'r';
	break;

    case 's' :
        fp->mode = 's';
	break;

    default : /* Remove bogus compiler warning... */
        return (NULL);
  }
Exemple #23
0
STATIC mp_uint_t _webrepl_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) {
    // We know that os.dupterm always calls with size = 1
    assert(size == 1);
    mp_obj_webrepl_t *self = self_in;
    const mp_stream_p_t *sock_stream = mp_get_stream_raise(self->sock, MP_STREAM_OP_READ);
    mp_uint_t out_sz = sock_stream->read(self->sock, buf, size, errcode);
    //DEBUG_printf("webrepl: Read %d initial bytes from websocket\n", out_sz);
    if (out_sz == 0 || out_sz == MP_STREAM_ERROR) {
        return out_sz;
    }

    if (self->state == STATE_PASSWD) {
        char c = *(char*)buf;
        if (c == '\r' || c == '\n') {
            self->hdr.fname[self->data_to_recv] = 0;
            DEBUG_printf("webrepl: entered password: %s\n", self->hdr.fname);

            if (strcmp(self->hdr.fname, webrepl_passwd) != 0) {
                write_webrepl_str(self->sock, SSTR(denied_prompt));
                return 0;
            }

            self->state = STATE_NORMAL;
            self->data_to_recv = 0;
            write_webrepl_str(self->sock, SSTR(connected_prompt));
        } else if (self->data_to_recv < 10) {
            self->hdr.fname[self->data_to_recv++] = c;
        }
        return -2;
    }

    // If last read data belonged to text record (== REPL)
    int err;
    if (sock_stream->ioctl(self->sock, MP_STREAM_GET_DATA_OPTS, 0, &err) == 1) {
        return out_sz;
    }

    DEBUG_printf("webrepl: received bin data, hdr_to_recv: %d, data_to_recv=%d\n", self->hdr_to_recv, self->data_to_recv);

    if (self->hdr_to_recv != 0) {
        char *p = (char*)&self->hdr + sizeof(self->hdr) - self->hdr_to_recv;
        *p++ = *(char*)buf;
        if (--self->hdr_to_recv != 0) {
            mp_uint_t hdr_sz = sock_stream->read(self->sock, p, self->hdr_to_recv, errcode);
            if (hdr_sz == MP_STREAM_ERROR) {
                return hdr_sz;
            }
            self->hdr_to_recv -= hdr_sz;
            if (self->hdr_to_recv != 0) {
                return -2;
            }
        }

        DEBUG_printf("webrepl: op: %d, file: %s, chunk @%x, sz=%d\n", self->hdr.type, self->hdr.fname, (uint32_t)self->hdr.offset, self->hdr.size);

        handle_op(self);

        return -2;
    }

    if (self->data_to_recv != 0) {
        static byte filebuf[512];
        filebuf[0] = *(byte*)buf;
        mp_uint_t buf_sz = 1;
        if (--self->data_to_recv != 0) {
            size_t to_read = MIN(sizeof(filebuf) - 1, self->data_to_recv);
            mp_uint_t sz = sock_stream->read(self->sock, filebuf + 1, to_read, errcode);
            if (sz == MP_STREAM_ERROR) {
                return sz;
            }
            self->data_to_recv -= sz;
            buf_sz += sz;
        }

        DEBUG_printf("webrepl: Writing %lu bytes to file\n", buf_sz);
        int err;
        mp_uint_t res = mp_stream_writeall(self->cur_file, filebuf, buf_sz, &err);
        if(res == MP_STREAM_ERROR) {
            assert(0);
        }

        if (self->data_to_recv == 0) {
            close_meth(self->cur_file);
            self->hdr_to_recv = sizeof(struct webrepl_file);
            DEBUG_printf("webrepl: Finished writing file\n");
            write_webrepl_resp(self->sock, 0);
        }

        #ifdef MICROPY_PY_WEBREPL_DELAY
        // Some platforms may have broken drivers and easily gets
        // overloaded with modest traffic WebREPL file transfers
        // generate. The basic workaround is a crude rate control
        // done in such way.
        mp_hal_delay_ms(MICROPY_PY_WEBREPL_DELAY);
        #endif
    }

    return -2;
}
Exemple #24
0
ipp_status_t				/* O - IPP status code */
cupsCreateDestJob(
    http_t        *http,		/* I - Connection to destination */
    cups_dest_t   *dest,		/* I - Destination */
    cups_dinfo_t  *info, 		/* I - Destination information */
    int           *job_id,		/* O - Job ID or 0 on error */
    const char    *title,		/* I - Job name */
    int           num_options,		/* I - Number of job options */
    cups_option_t *options)		/* I - Job options */
{
  ipp_t			*request,	/* Create-Job request */
			*response;	/* Create-Job response */
  ipp_attribute_t	*attr;		/* job-id attribute */


  DEBUG_printf(("cupsCreateDestJob(http=%p, dest=%p(%s/%s), info=%p, "
                "job_id=%p, title=\"%s\", num_options=%d, options=%p)", (void *)http, (void *)dest, dest ? dest->name : NULL, dest ? dest->instance : NULL, (void *)info, (void *)job_id, title, num_options, (void *)options));

 /*
  * Range check input...
  */

  if (job_id)
    *job_id = 0;

  if (!http || !dest || !info || !job_id)
  {
    _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0);
    DEBUG_puts("1cupsCreateDestJob: Bad arguments.");
    return (IPP_STATUS_ERROR_INTERNAL);
  }

 /*
  * Build a Create-Job request...
  */

  if ((request = ippNewRequest(IPP_OP_CREATE_JOB)) == NULL)
  {
    _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(ENOMEM), 0);
    DEBUG_puts("1cupsCreateDestJob: Unable to create Create-Job request.");
    return (IPP_STATUS_ERROR_INTERNAL);
  }

  ippSetVersion(request, info->version / 10, info->version % 10);

  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
               NULL, info->uri);
  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
               NULL, cupsUser());
  if (title)
    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", NULL,
                 title);

  cupsEncodeOptions2(request, num_options, options, IPP_TAG_OPERATION);
  cupsEncodeOptions2(request, num_options, options, IPP_TAG_JOB);
  cupsEncodeOptions2(request, num_options, options, IPP_TAG_SUBSCRIPTION);

 /*
  * Send the request and get the job-id...
  */

  response = cupsDoRequest(http, request, info->resource);

  if ((attr = ippFindAttribute(response, "job-id", IPP_TAG_INTEGER)) != NULL)
  {
    *job_id = attr->values[0].integer;
    DEBUG_printf(("1cupsCreateDestJob: job-id=%d", *job_id));
  }

  ippDelete(response);

 /*
  * Return the status code from the Create-Job request...
  */

  DEBUG_printf(("1cupsCreateDestJob: %s (%s)", ippErrorString(cupsLastError()),
                cupsLastErrorString()));

  return (cupsLastError());
}
Exemple #25
0
STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *args) {
    // This function is pretty complicated.  It's main aim is to be efficient in speed and RAM
    // usage for the common case of positional only args.

    DEBUG_printf("Input n_args: %d, n_kw: %d\n", n_args, n_kw);
    DEBUG_printf("Input pos args: ");
    dump_args(args, n_args);
    DEBUG_printf("Input kw args: ");
    dump_args(args + n_args, n_kw * 2);
    mp_obj_fun_bc_t *self = self_in;
    DEBUG_printf("Func n_def_args: %d\n", self->n_def_args);

    const byte *ip = self->bytecode;

    // get code info size, and skip line number table
    machine_uint_t code_info_size = ip[0] | (ip[1] << 8) | (ip[2] << 16) | (ip[3] << 24);
    ip += code_info_size;

    // bytecode prelude: state size and exception stack size; 16 bit uints
    machine_uint_t n_state = ip[0] | (ip[1] << 8);
    machine_uint_t n_exc_stack = ip[2] | (ip[3] << 8);
    ip += 4;

#if VM_DETECT_STACK_OVERFLOW
    n_state += 1;
#endif

    // allocate state for locals and stack
    uint state_size = n_state * sizeof(mp_obj_t) + n_exc_stack * sizeof(mp_exc_stack_t);
    mp_code_state *code_state;
    if (state_size > VM_MAX_STATE_ON_STACK) {
        code_state = m_new_obj_var(mp_code_state, byte, state_size);
    } else {
        code_state = alloca(sizeof(mp_code_state) + state_size);
    }

    code_state->code_info = self->bytecode;
    code_state->sp = &code_state->state[0] - 1;
    code_state->exc_sp = (mp_exc_stack_t*)(code_state->state + n_state) - 1;
    code_state->n_state = n_state;

    // zero out the local stack to begin with
    memset(code_state->state, 0, n_state * sizeof(*code_state->state));

    const mp_obj_t *kwargs = args + n_args;

    // var_pos_kw_args points to the stack where the var-args tuple, and var-kw dict, should go (if they are needed)
    mp_obj_t *var_pos_kw_args = &code_state->state[n_state - 1 - self->n_pos_args - self->n_kwonly_args];

    // check positional arguments

    if (n_args > self->n_pos_args) {
        // given more than enough arguments
        if (!self->takes_var_args) {
            fun_pos_args_mismatch(self, self->n_pos_args, n_args);
        }
        // put extra arguments in varargs tuple
        *var_pos_kw_args-- = mp_obj_new_tuple(n_args - self->n_pos_args, args + self->n_pos_args);
        n_args = self->n_pos_args;
    } else {
        if (self->takes_var_args) {
            DEBUG_printf("passing empty tuple as *args\n");
            *var_pos_kw_args-- = mp_const_empty_tuple;
        }
        // Apply processing and check below only if we don't have kwargs,
        // otherwise, kw handling code below has own extensive checks.
        if (n_kw == 0 && !self->has_def_kw_args) {
            if (n_args >= self->n_pos_args - self->n_def_args) {
                // given enough arguments, but may need to use some default arguments
                for (uint i = n_args; i < self->n_pos_args; i++) {
                    code_state->state[n_state - 1 - i] = self->extra_args[i - (self->n_pos_args - self->n_def_args)];
                }
            } else {
                fun_pos_args_mismatch(self, self->n_pos_args - self->n_def_args, n_args);
            }
        }
    }

    // copy positional args into state
    for (uint i = 0; i < n_args; i++) {
        code_state->state[n_state - 1 - i] = args[i];
    }

    // check keyword arguments

    if (n_kw != 0 || self->has_def_kw_args) {
        DEBUG_printf("Initial args: ");
        dump_args(code_state->state + n_state - self->n_pos_args - self->n_kwonly_args, self->n_pos_args + self->n_kwonly_args);

        mp_obj_t dict = MP_OBJ_NULL;
        if (self->takes_kw_args) {
            dict = mp_obj_new_dict(n_kw); // TODO: better go conservative with 0?
            *var_pos_kw_args = dict;
        }

        for (uint i = 0; i < n_kw; i++) {
            qstr arg_name = MP_OBJ_QSTR_VALUE(kwargs[2 * i]);
            for (uint j = 0; j < self->n_pos_args + self->n_kwonly_args; j++) {
                if (arg_name == self->args[j]) {
                    if (code_state->state[n_state - 1 - j] != MP_OBJ_NULL) {
                        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
                            "function got multiple values for argument '%s'", qstr_str(arg_name)));
                    }
                    code_state->state[n_state - 1 - j] = kwargs[2 * i + 1];
                    goto continue2;
                }
            }
            // Didn't find name match with positional args
            if (!self->takes_kw_args) {
                nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "function does not take keyword arguments"));
            }
            mp_obj_dict_store(dict, kwargs[2 * i], kwargs[2 * i + 1]);
continue2:;
        }

        DEBUG_printf("Args with kws flattened: ");
        dump_args(code_state->state + n_state - self->n_pos_args - self->n_kwonly_args, self->n_pos_args + self->n_kwonly_args);

        // fill in defaults for positional args
        mp_obj_t *d = &code_state->state[n_state - self->n_pos_args];
        mp_obj_t *s = &self->extra_args[self->n_def_args - 1];
        for (int i = self->n_def_args; i > 0; i--, d++, s--) {
            if (*d == MP_OBJ_NULL) {
                *d = *s;
            }
        }

        DEBUG_printf("Args after filling default positional: ");
        dump_args(code_state->state + n_state - self->n_pos_args - self->n_kwonly_args, self->n_pos_args + self->n_kwonly_args);

        // Check that all mandatory positional args are specified
        while (d < &code_state->state[n_state]) {
            if (*d++ == MP_OBJ_NULL) {
                nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
                    "function missing required positional argument #%d", &code_state->state[n_state] - d));
            }
        }

        // Check that all mandatory keyword args are specified
        // Fill in default kw args if we have them
        for (uint i = 0; i < self->n_kwonly_args; i++) {
            if (code_state->state[n_state - 1 - self->n_pos_args - i] == MP_OBJ_NULL) {
                mp_map_elem_t *elem = NULL;
                if (self->has_def_kw_args) {
                    elem = mp_map_lookup(&((mp_obj_dict_t*)self->extra_args[self->n_def_args])->map, MP_OBJ_NEW_QSTR(self->args[self->n_pos_args + i]), MP_MAP_LOOKUP);
                }
                if (elem != NULL) {
                    code_state->state[n_state - 1 - self->n_pos_args - i] = elem->value;
                } else {
                    nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
                        "function missing required keyword argument '%s'", qstr_str(self->args[self->n_pos_args + i])));
                }
            }
        }

    } else {
        // no keyword arguments given
        if (self->n_kwonly_args != 0) {
            nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
                "function missing keyword-only argument"));
        }
        if (self->takes_kw_args) {
            *var_pos_kw_args = mp_obj_new_dict(0);
        }
    }

    // bytecode prelude: initialise closed over variables
    for (uint n_local = *ip++; n_local > 0; n_local--) {
        uint local_num = *ip++;
        code_state->state[n_state - 1 - local_num] = mp_obj_new_cell(code_state->state[n_state - 1 - local_num]);
    }

    // now that we skipped over the prelude, set the ip for the VM
    code_state->ip = ip;

    DEBUG_printf("Calling: n_pos_args=%d, n_kwonly_args=%d\n", self->n_pos_args, self->n_kwonly_args);
    dump_args(code_state->state + n_state - self->n_pos_args - self->n_kwonly_args, self->n_pos_args + self->n_kwonly_args);
    dump_args(code_state->state, n_state);

    // execute the byte code with the correct globals context
    mp_obj_dict_t *old_globals = mp_globals_get();
    mp_globals_set(self->globals);
    mp_vm_return_kind_t vm_return_kind = mp_execute_bytecode(code_state, MP_OBJ_NULL);
    mp_globals_set(old_globals);

#if VM_DETECT_STACK_OVERFLOW
    if (vm_return_kind == MP_VM_RETURN_NORMAL) {
        if (code_state->sp < code_state->state) {
            printf("VM stack underflow: " INT_FMT "\n", code_state->sp - code_state->state);
            assert(0);
        }
    }
    // We can't check the case when an exception is returned in state[n_state - 1]
    // and there are no arguments, because in this case our detection slot may have
    // been overwritten by the returned exception (which is allowed).
    if (!(vm_return_kind == MP_VM_RETURN_EXCEPTION && self->n_pos_args + self->n_kwonly_args == 0)) {
        // Just check to see that we have at least 1 null object left in the state.
        bool overflow = true;
        for (uint i = 0; i < n_state - self->n_pos_args - self->n_kwonly_args; i++) {
            if (code_state->state[i] == MP_OBJ_NULL) {
                overflow = false;
                break;
            }
        }
        if (overflow) {
            printf("VM stack overflow state=%p n_state+1=" UINT_FMT "\n", code_state->state, n_state);
            assert(0);
        }
    }
#endif

    mp_obj_t result;
    switch (vm_return_kind) {
        case MP_VM_RETURN_NORMAL:
            // return value is in *sp
            result = *code_state->sp;
            break;

        case MP_VM_RETURN_EXCEPTION:
            // return value is in state[n_state - 1]
            result = code_state->state[n_state - 1];
            break;

        case MP_VM_RETURN_YIELD: // byte-code shouldn't yield
        default:
            assert(0);
            result = mp_const_none;
            vm_return_kind = MP_VM_RETURN_NORMAL;
            break;
    }

    // free the state if it was allocated on the heap
    if (state_size > VM_MAX_STATE_ON_STACK) {
        m_del_var(mp_code_state, byte, state_size, code_state);
    }

    if (vm_return_kind == MP_VM_RETURN_NORMAL) {
        return result;
    } else { // MP_VM_RETURN_EXCEPTION
        nlr_raise(result);
    }
}
Exemple #26
0
http_status_t				/* O - Status of document creation */
cupsStartDestDocument(
    http_t        *http,		/* I - Connection to destination */
    cups_dest_t   *dest,		/* I - Destination */
    cups_dinfo_t  *info, 		/* I - Destination information */
    int           job_id,		/* I - Job ID */
    const char    *docname,		/* I - Document name */
    const char    *format,		/* I - Document format */
    int           num_options,		/* I - Number of document options */
    cups_option_t *options,		/* I - Document options */
    int           last_document)	/* I - 1 if this is the last document */
{
  ipp_t		*request;		/* Send-Document request */
  http_status_t	status;			/* HTTP status */


  DEBUG_printf(("cupsStartDestDocument(http=%p, dest=%p(%s/%s), info=%p, job_id=%d, docname=\"%s\", format=\"%s\", num_options=%d, options=%p, last_document=%d)", (void *)http, (void *)dest, dest ? dest->name : NULL, dest ? dest->instance : NULL, (void *)info, job_id, docname, format, num_options, (void *)options, last_document));

 /*
  * Range check input...
  */

  if (!http || !dest || !info || job_id <= 0)
  {
    _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0);
    DEBUG_puts("1cupsStartDestDocument: Bad arguments.");
    return (HTTP_STATUS_ERROR);
  }

 /*
  * Create a Send-Document request...
  */

  if ((request = ippNewRequest(IPP_OP_SEND_DOCUMENT)) == NULL)
  {
    _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(ENOMEM), 0);
    DEBUG_puts("1cupsStartDestDocument: Unable to create Send-Document "
               "request.");
    return (HTTP_STATUS_ERROR);
  }

  ippSetVersion(request, info->version / 10, info->version % 10);

  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
               NULL, info->uri);
  ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id", job_id);
  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
               NULL, cupsUser());
  if (docname)
    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "document-name",
                 NULL, docname);
  if (format)
    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE,
                 "document-format", NULL, format);
  ippAddBoolean(request, IPP_TAG_OPERATION, "last-document", (char)last_document);

  cupsEncodeOptions2(request, num_options, options, IPP_TAG_OPERATION);
  cupsEncodeOptions2(request, num_options, options, IPP_TAG_DOCUMENT);

 /*
  * Send and delete the request, then return the status...
  */

  status = cupsSendRequest(http, request, info->resource, CUPS_LENGTH_VARIABLE);

  ippDelete(request);

  return (status);
}
Exemple #27
0
int					/* O  - Number of options */
cupsAddOption(const char    *name,	/* I  - Name of option */
              const char    *value,	/* I  - Value of option */
	      int           num_options,/* I  - Number of options */
              cups_option_t **options)	/* IO - Pointer to options */
{
  cups_option_t	*temp;			/* Pointer to new option */
  int		insert,			/* Insertion point */
		diff;			/* Result of search */


  DEBUG_printf(("2cupsAddOption(name=\"%s\", value=\"%s\", num_options=%d, "
                "options=%p)", name, value, num_options, options));

  if (!name || !name[0] || !value || !options || num_options < 0)
  {
    DEBUG_printf(("3cupsAddOption: Returning %d", num_options));
    return (num_options);
  }

 /*
  * Look for an existing option with the same name...
  */

  if (num_options == 0)
  {
    insert = 0;
    diff   = 1;
  }
  else
  {
    insert = cups_find_option(name, num_options, *options, num_options - 1,
                              &diff);

    if (diff > 0)
      insert ++;
  }

  if (diff)
  {
   /*
    * No matching option name...
    */

    DEBUG_printf(("4cupsAddOption: New option inserted at index %d...",
                  insert));

    if (num_options == 0)
      temp = (cups_option_t *)malloc(sizeof(cups_option_t));
    else
      temp = (cups_option_t *)realloc(*options, sizeof(cups_option_t) * (size_t)(num_options + 1));

    if (!temp)
    {
      DEBUG_puts("3cupsAddOption: Unable to expand option array, returning 0");
      return (0);
    }

    *options = temp;

    if (insert < num_options)
    {
      DEBUG_printf(("4cupsAddOption: Shifting %d options...",
                    (int)(num_options - insert)));
      memmove(temp + insert + 1, temp + insert, (size_t)(num_options - insert) * sizeof(cups_option_t));
    }

    temp        += insert;
    temp->name  = _cupsStrAlloc(name);
    num_options ++;
  }
  else
  {
   /*
    * Match found; free the old value...
    */

    DEBUG_printf(("4cupsAddOption: Option already exists at index %d...",
                  insert));

    temp = *options + insert;
    _cupsStrFree(temp->value);
  }

  temp->value = _cupsStrAlloc(value);

  DEBUG_printf(("3cupsAddOption: Returning %d", num_options));

  return (num_options);
}
Exemple #28
0
ipp_status_t				/* O - IPP status code */
cupsCloseDestJob(
    http_t       *http,			/* I - Connection to destination */
    cups_dest_t  *dest,			/* I - Destination */
    cups_dinfo_t *info, 		/* I - Destination information */
    int          job_id)		/* I - Job ID */
{
  int			i;		/* Looping var */
  ipp_t			*request = NULL;/* Close-Job/Send-Document request */
  ipp_attribute_t	*attr;		/* operations-supported attribute */


  DEBUG_printf(("cupsCloseDestJob(http=%p, dest=%p(%s/%s), info=%p, job_id=%d)", (void *)http, (void *)dest, dest ? dest->name : NULL, dest ? dest->instance : NULL, (void *)info, job_id));

 /*
  * Range check input...
  */

  if (!http || !dest || !info || job_id <= 0)
  {
    _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0);
    DEBUG_puts("1cupsCloseDestJob: Bad arguments.");
    return (IPP_STATUS_ERROR_INTERNAL);
  }

 /*
  * Build a Close-Job or empty Send-Document request...
  */

  if ((attr = ippFindAttribute(info->attrs, "operations-supported",
                               IPP_TAG_ENUM)) != NULL)
  {
    for (i = 0; i < attr->num_values; i ++)
      if (attr->values[i].integer == IPP_OP_CLOSE_JOB)
      {
        request = ippNewRequest(IPP_OP_CLOSE_JOB);
        break;
      }
  }

  if (!request)
    request = ippNewRequest(IPP_OP_SEND_DOCUMENT);

  if (!request)
  {
    _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(ENOMEM), 0);
    DEBUG_puts("1cupsCloseDestJob: Unable to create Close-Job/Send-Document "
               "request.");
    return (IPP_STATUS_ERROR_INTERNAL);
  }

  ippSetVersion(request, info->version / 10, info->version % 10);

  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
               NULL, info->uri);
  ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id",
                job_id);
  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
               NULL, cupsUser());
  if (ippGetOperation(request) == IPP_OP_SEND_DOCUMENT)
    ippAddBoolean(request, IPP_TAG_OPERATION, "last-document", 1);

 /*
  * Send the request and return the status...
  */

  ippDelete(cupsDoRequest(http, request, info->resource));

  DEBUG_printf(("1cupsCloseDestJob: %s (%s)", ippErrorString(cupsLastError()),
                cupsLastErrorString()));

  return (cupsLastError());
}
Exemple #29
0
/*
 * '_sspiRead()' - Read a buffer from an ssl socket
 */
int					/* O  - Bytes read or SOCKET_ERROR */
_sspiRead(_sspi_struct_t *conn,		/* I  - Client connection */
          void           *buf,		/* I  - Buffer */
          size_t         len)		/* I  - Buffer length */
{
  SecBufferDesc	message;		/* Array of SecBuffer struct */
  SecBuffer	buffers[4] = { 0 };	/* Security package buffer */
  int		num = 0;		/* Return value */

  if (!conn)
  {
    WSASetLastError(WSAEINVAL);
    num = SOCKET_ERROR;
    goto cleanup;
  }

 /*
  * If there are bytes that have already been
  * decrypted and have not yet been read, return
  * those
  */
  if (buf && (conn->readBufferUsed > 0))
  {
    int bytesToCopy = (int) min(conn->readBufferUsed, len);	/* Amount of bytes to copy */
								/* from read buffer */

    memcpy(buf, conn->readBuffer, bytesToCopy);
    conn->readBufferUsed -= bytesToCopy;

    if (conn->readBufferUsed > 0)
     /*
      * If the caller didn't request all the bytes
      * we have in the buffer, then move the unread
      * bytes down
      */
      memmove(conn->readBuffer,
              conn->readBuffer + bytesToCopy,
              conn->readBufferUsed);

    num = bytesToCopy;
  }
  else
  {
    PSecBuffer		pDataBuffer;	/* Data buffer */
    PSecBuffer		pExtraBuffer;	/* Excess data buffer */
    SECURITY_STATUS	scRet;		/* SSPI status */
    int			i;		/* Loop control variable */

   /*
    * Initialize security buffer structs
    */
    message.ulVersion = SECBUFFER_VERSION;
    message.cBuffers = 4;
    message.pBuffers = buffers;

    do
    {
     /*
      * If there is not enough space in the
      * buffer, then increase it's size
      */
      if (conn->decryptBufferLength <= conn->decryptBufferUsed)
      {
        conn->decryptBufferLength += 4096;
        conn->decryptBuffer = (BYTE*) realloc(conn->decryptBuffer,
                                              conn->decryptBufferLength);

        if (!conn->decryptBuffer)
        {
          DEBUG_printf(("_sspiRead: unable to allocate %d byte buffer",
                        conn->decryptBufferLength));
          WSASetLastError(E_OUTOFMEMORY);
          num = SOCKET_ERROR;
          goto cleanup;
        }
      }

      buffers[0].pvBuffer	= conn->decryptBuffer;
      buffers[0].cbBuffer	= (unsigned long) conn->decryptBufferUsed;
      buffers[0].BufferType	= SECBUFFER_DATA;
      buffers[1].BufferType	= SECBUFFER_EMPTY;
      buffers[2].BufferType	= SECBUFFER_EMPTY;
      buffers[3].BufferType	= SECBUFFER_EMPTY;

      scRet = DecryptMessage(&conn->context, &message, 0, NULL);

      if (scRet == SEC_E_INCOMPLETE_MESSAGE)
      {
        if (buf)
        {
          num = recv(conn->sock,
                     conn->decryptBuffer + conn->decryptBufferUsed,
                     (int)(conn->decryptBufferLength - conn->decryptBufferUsed),
                     0);
          if (num == SOCKET_ERROR)
          {
            DEBUG_printf(("_sspiRead: recv failed: %d", WSAGetLastError()));
            goto cleanup;
          }
          else if (num == 0)
          {
            DEBUG_printf(("_sspiRead: server disconnected"));
            goto cleanup;
          }

          conn->decryptBufferUsed += num;
        }
        else
        {
          num = (int) conn->readBufferUsed;
          goto cleanup;
        }
      }
    }
    while (scRet == SEC_E_INCOMPLETE_MESSAGE);

    if (scRet == SEC_I_CONTEXT_EXPIRED)
    {
      DEBUG_printf(("_sspiRead: context expired"));
      WSASetLastError(WSAECONNRESET);
      num = SOCKET_ERROR;
      goto cleanup;
    }
    else if (scRet != SEC_E_OK)
    {
      DEBUG_printf(("_sspiRead: DecryptMessage failed: %lx", scRet));
      WSASetLastError(WSASYSCALLFAILURE);
      num = SOCKET_ERROR;
      goto cleanup;
    }

   /*
    * The decryption worked.  Now, locate data buffer.
    */
    pDataBuffer  = NULL;
    pExtraBuffer = NULL;
    for (i = 1; i < 4; i++)
    {
      if (buffers[i].BufferType == SECBUFFER_DATA)
        pDataBuffer = &buffers[i];
      else if (!pExtraBuffer && (buffers[i].BufferType == SECBUFFER_EXTRA))
        pExtraBuffer = &buffers[i];
    }

   /*
    * If a data buffer is found, then copy
    * the decrypted bytes to the passed-in
    * buffer
    */
    if (pDataBuffer)
    {
      int bytesToCopy = min(pDataBuffer->cbBuffer, (int) len);
                           		/* Number of bytes to copy into buf */
      int bytesToSave = pDataBuffer->cbBuffer - bytesToCopy;
                           		/* Number of bytes to save in our read buffer */

      if (bytesToCopy)
        memcpy(buf, pDataBuffer->pvBuffer, bytesToCopy);

     /*
      * If there are more decrypted bytes than can be
      * copied to the passed in buffer, then save them
      */
      if (bytesToSave)
      {
        if ((int)(conn->readBufferLength - conn->readBufferUsed) < bytesToSave)
        {
          conn->readBufferLength = conn->readBufferUsed + bytesToSave;
          conn->readBuffer = realloc(conn->readBuffer,
                                     conn->readBufferLength);

          if (!conn->readBuffer)
          {
            DEBUG_printf(("_sspiRead: unable to allocate %d bytes", conn->readBufferLength));
            WSASetLastError(E_OUTOFMEMORY);
            num = SOCKET_ERROR;
            goto cleanup;
          }
        }

        memcpy(((BYTE*) conn->readBuffer) + conn->readBufferUsed,
               ((BYTE*) pDataBuffer->pvBuffer) + bytesToCopy,
               bytesToSave);

        conn->readBufferUsed += bytesToSave;
      }

      num = (buf) ? bytesToCopy : (int) conn->readBufferUsed;
    }
    else
    {
      DEBUG_printf(("_sspiRead: unable to find data buffer"));
      WSASetLastError(WSASYSCALLFAILURE);
      num = SOCKET_ERROR;
      goto cleanup;
    }

   /*
    * If the decryption process left extra bytes,
    * then save those back in decryptBuffer. They will
    * be processed the next time through the loop.
    */
    if (pExtraBuffer)
    {
      memmove(conn->decryptBuffer, pExtraBuffer->pvBuffer, pExtraBuffer->cbBuffer);
      conn->decryptBufferUsed = pExtraBuffer->cbBuffer;
    }
    else
    {
      conn->decryptBufferUsed = 0;
    }
  }

cleanup:

  return (num);
}
Exemple #30
0
http_status_t				/* O - @code HTTP_STATUS_CONTINUE@ if OK or HTTP status on error */
cupsWriteRequestData(
    http_t     *http,			/* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
    const char *buffer,			/* I - Bytes to write */
    size_t     length)			/* I - Number of bytes to write */
{
  int	wused;				/* Previous bytes in buffer */


 /*
  * Get the default connection as needed...
  */

  DEBUG_printf(("cupsWriteRequestData(http=%p, buffer=%p, "
                "length=" CUPS_LLFMT ")", http, buffer, CUPS_LLCAST length));

  if (!http)
  {
    _cups_globals_t *cg = _cupsGlobals();
					/* Pointer to library globals */

    if ((http = cg->http) == NULL)
    {
      _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("No active connection"), 1);
      DEBUG_puts("1cupsWriteRequestData: Returning HTTP_STATUS_ERROR.");
      return (HTTP_STATUS_ERROR);
    }
  }

 /*
  * Then write to the HTTP connection...
  */

  wused = http->wused;

  if (httpWrite2(http, buffer, length) < 0)
  {
    DEBUG_puts("1cupsWriteRequestData: Returning HTTP_STATUS_ERROR.");
    _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(http->error), 0);
    return (HTTP_STATUS_ERROR);
  }

 /*
  * Finally, check if we have any pending data from the server...
  */

  if (length >= HTTP_MAX_BUFFER ||
      http->wused < wused ||
      (wused > 0 && http->wused == length))
  {
   /*
    * We've written something to the server, so check for response data...
    */

    if (_httpWait(http, 0, 1))
    {
      http_status_t	status;		/* Status from _httpUpdate */

      _httpUpdate(http, &status);
      if (status >= HTTP_STATUS_MULTIPLE_CHOICES)
      {
        _cupsSetHTTPError(status);

	do
	{
	  status = httpUpdate(http);
	}
	while (status != HTTP_STATUS_ERROR && http->state == HTTP_STATE_POST_RECV);

        httpFlush(http);
      }

      DEBUG_printf(("1cupsWriteRequestData: Returning %d.\n", status));
      return (status);
    }
  }

  DEBUG_puts("1cupsWriteRequestData: Returning HTTP_STATUS_CONTINUE.");
  return (HTTP_STATUS_CONTINUE);
}