Ejemplo n.º 1
0
int special_gpio_request(unsigned gpio, const char *label)
{
	/*
	 * Allow that the identical GPIO can
	 * be requested from the same driver twice
	 * Do nothing and return -
	 */

	if (cmp_label(gpio, label) == 0)
		return 0;

	if (unlikely(is_reserved(special_gpio, gpio, 1))) {
		printf("bfin-gpio: GPIO %d is already reserved by %s !\n",
		       gpio, get_label(gpio));
		return -EBUSY;
	}
	if (unlikely(is_reserved(peri, gpio, 1))) {
		printf("bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n",
		       gpio, get_label(gpio));

		return -EBUSY;
	}

	reserve(special_gpio, gpio);
	reserve(peri, gpio);

	set_label(gpio, label);
	port_setup(gpio, GPIO_USAGE);

	return 0;
}
Ejemplo n.º 2
0
int gpio_request(unsigned gpio, const char *label)
{
	if (check_gpio(gpio) < 0)
		return -EINVAL;

	/*
	 * Allow that the identical GPIO can
	 * be requested from the same driver twice
	 * Do nothing and return -
	 */

	if (cmp_label(gpio, label) == 0)
		return 0;

	if (unlikely(is_reserved(gpio, gpio, 1))) {
		printf("bfin-gpio: GPIO %d is already reserved by %s !\n",
		       gpio, get_label(gpio));
		return -EBUSY;
	}
	if (unlikely(is_reserved(peri, gpio, 1))) {
		printf("bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n",
		       gpio, get_label(gpio));
		return -EBUSY;
	}
	else {	/* Reset POLAR setting when acquiring a gpio for the first time */
		set_gpio_polar(gpio, 0);
	}

	reserve(gpio, gpio);
	set_label(gpio, label);

	port_setup(gpio, GPIO_USAGE);

	return 0;
}
Ejemplo n.º 3
0
int peripheral_request(unsigned short per, const char *label)
{
	unsigned short ident = P_IDENT(per);

	/*
	 * Don't cares are pins with only one dedicated function
	 */

	if (per & P_DONTCARE)
		return 0;

	if (!(per & P_DEFINED))
		return -ENODEV;

	BUG_ON(ident >= MAX_RESOURCES);

	/* If a pin can be muxed as either GPIO or peripheral, make
	 * sure it is not already a GPIO pin when we request it.
	 */
	if (unlikely(!check_gpio(ident) && is_reserved(gpio, ident, 1))) {
		printf("%s: Peripheral %d is already reserved as GPIO by %s !\n",
		       __func__, ident, get_label(ident));
		return -EBUSY;
	}

	if (unlikely(is_reserved(peri, ident, 1))) {

		/*
		 * Pin functions like AMC address strobes my
		 * be requested and used by several drivers
		 */

		if (!(per & P_MAYSHARE)) {
			/*
			 * Allow that the identical pin function can
			 * be requested from the same driver twice
			 */

			if (cmp_label(ident, label) == 0)
				goto anyway;

			printf("%s: Peripheral %d function %d is already reserved by %s !\n",
			       __func__, ident, P_FUNCT2MUX(per), get_label(ident));
			return -EBUSY;
		}
	}

 anyway:
	reserve(peri, ident);

	portmux_setup(per);
	port_setup(ident, PERIPHERAL_USAGE);

	set_label(ident, label);

	return 0;
}
Ejemplo n.º 4
0
extern void addkey (
    char *key,
    rwcodes_ty val)
{
    templ_ty *p;

    /* Check to see whether key is a reserved word or not. */
    if ( (settings.c_plus_plus  && is_reserved_cc (key, strlen (key)) != 0) ||
         (!settings.c_plus_plus && is_reserved (key, strlen (key)) != 0))
    {
    }
    else
    {
       if (user_specials == 0)
       {
          user_specials = (templ_ty *) xmalloc (5 * sizeof (templ_ty));
          user_specials_max = 5;
          user_specials_idx = 0;
       }
       else if (user_specials_idx == user_specials_max)
       {
          user_specials_max += 5;
          user_specials = (templ_ty *) xrealloc ((char *) user_specials, user_specials_max * sizeof (templ_ty));
       }
       else
       {
         /* what ? */
       }

       p = &user_specials[user_specials_idx++];
       p->rwd = key;
       p->rwcode = val;
    }
}
Ejemplo n.º 5
0
void gpio_labels(void)
{
	int c, gpio;

	for (c = 0; c < MAX_RESOURCES; c++) {
		gpio = is_reserved(gpio, c, 1);
		if (!check_gpio(c) && gpio)
			printf("GPIO_%d:\t%s\tGPIO %s\n", c,
				get_label(c),
				get_gpio_dir(c) ? "OUTPUT" : "INPUT");
		else if (is_reserved(peri, c, 1))
			printf("GPIO_%d:\t%s\tPeripheral\n", c, get_label(c));
		else
			continue;
	}
}
Ejemplo n.º 6
0
void special_gpio_free(unsigned gpio)
{
	if (unlikely(!is_reserved(special_gpio, gpio, 0))) {
		gpio_error(gpio);
		return;
	}

	unreserve(special_gpio, gpio);
	unreserve(peri, gpio);
	set_label(gpio, "free");
}
Ejemplo n.º 7
0
int hmap_insert(struct hmap *map, void *key, void *data)
{
	unsigned long i=0, index=map->hash(key);
	unsigned char *aux_key=map->keys, *aux_data=map->data;
	if (is_reserved(key, map->key_size))/*Makes sure to dont add reserved keys*/
        return FAILURE;
	while (!is_reserved(aux_key+((index+i)%map->map_size)*(map->key_size),
			map->key_size))
	/*While haven't found a empty or deleted key*/
	{
		if (i==map->map_size) /*If already passed through the whole map*/
			return FAILURE;
		i++;
	}
	memcpy(aux_key+((index+i)%map->map_size)*(map->key_size), key,
			map->key_size); /*Write key and data*/
	memcpy(aux_data+((index+i)%map->map_size)*(map->data_size), data,
			 map->data_size);
	return SUCCESS;
}
Ejemplo n.º 8
0
int gpio_free(unsigned gpio)
{
	if (check_gpio(gpio) < 0)
		return -1;

	if (unlikely(!is_reserved(gpio, gpio, 0))) {
		gpio_error(gpio);
		return -1;
	}

	unreserve(gpio, gpio);

	set_label(gpio, "free");

	return 0;
}
Ejemplo n.º 9
0
void ReservedSpace::release() {
  if (is_reserved()) {
    char *real_base = _base - _noaccess_prefix;
    const size_t real_size = _size + _noaccess_prefix;
    if (special()) {
      os::release_memory_special(real_base, real_size);
    } else{
      os::release_memory(real_base, real_size);
    }
    _base = NULL;
    _size = 0;
    _noaccess_prefix = 0;
    _special = false;
    _executable = false;
  }
}
Ejemplo n.º 10
0
int gpio_direction_input(unsigned gpio)
{
	unsigned long flags;

	if (!is_reserved(gpio, gpio, 0)) {
		gpio_error(gpio);
		return -EINVAL;
	}

	local_irq_save(flags);
	__gpio_direction_input(gpio);
	AWA_DUMMY_READ(inen);
	local_irq_restore(flags);

	return 0;
}
Ejemplo n.º 11
0
//relacao estado e o token que ele gera
Token_type state_converter_token_type(States state, char buffer[50]){
	switch(state){
		case S1:
			return TT_END_OF_COMMAND;
		case S2:
			if (is_reserved(buffer) == 0){
				return TT_RESERVED;
			} else {
				return TT_IDENTIFIER;
			}
		case S3:
			return TT_COMPARATOR;
		case S4:
			return TT_COMPARATOR;
		case S5:
			return TT_INT;
		case S6:
			return TT_ARITH_SYMBOL;
		case S8:
			return TT_STRING; 
		case S10:
			return TT_STRING;
		case S11:
			if(strcmp(buffer, "]") == 0){
				return TT_R_SQ_BRACKET;
			}else if(strcmp(buffer, "[") == 0){
				return TT_L_SQ_BRACKET;
			}else if(strcmp(buffer, ")") == 0){
				return TT_R_PARENTHESIS;
			}else if(strcmp(buffer, "(") == 0){
				return TT_L_PARENTHESIS;
			}else{
				return TT_SEPARATOR;
			}
		case S13:
			return TT_ASSIGNMENT;
		case S14:
			return TT_FLOAT;
		case S23:
			return TT_IGNORE;
		case S24:
			return TT_IGNORE;
		default:
			return TT_UNKNOWN;
	}
}
Ejemplo n.º 12
0
/************************************************************************
*	Function :	parse_uric
*
*	Parameters :
*		char *in ;	string of characters
*		int max ;	maximum limit
*		token *out ; token object where the string of characters is 
*					 copied
*
*	Description : Parses a string of uric characters starting at in[0]
*		as defined in http://www.ietf.org/rfc/rfc2396.txt (RFC explaining 
*		URIs)	
*
*	Return : int ;
*
*	Note :
************************************************************************/
int
parse_uric( char *in,
            int max,
            token * out )
{
    int i = 0;

    while( ( i < max )
            && ( ( is_unreserved( in[i] ) ) || ( is_reserved( in[i] ) )
                 || ( ( i + 2 < max ) && ( is_escaped( &in[i] ) ) ) ) ) {
        i++;
    }

    out->size = i;
    out->buff = in;
    return i;
}
Ejemplo n.º 13
0
/* Returns a MSR for a performance monitoring counter. */
struct msr *get_msr(uint64_t evt, uint64_t cpu_filter) {
   int i;

   get_available_msr();

   /* Perform search in reverse to increase the chance to use MSR 5-3 on 15h */
   /* because these counters can be used on a limited subset of events       */
   for(i = msr_count - 1; i >= 0; i--) {
      if(!is_reserved(i, evt, cpu_filter) && available_msrs[i].can_be_used(&available_msrs[i], evt)) {
         struct msr *msr = malloc(sizeof(*msr));
         memcpy(msr, &available_msrs[i], sizeof(*msr));
         return msr;
      }
   }

   die("No free msr for event %llx", (long long unsigned)evt);
   return 0;
}
Ejemplo n.º 14
0
void peripheral_free(unsigned short per)
{
	unsigned short ident = P_IDENT(per);

	if (per & P_DONTCARE)
		return;

	if (!(per & P_DEFINED))
		return;

	if (unlikely(!is_reserved(peri, ident, 0)))
		return;

	if (!(per & P_MAYSHARE))
		port_setup(ident, GPIO_USAGE);

	unreserve(peri, ident);

	set_label(ident, "free");
}
Ejemplo n.º 15
0
int gpio_direction_output(unsigned gpio, int value)
{
	unsigned long flags;

	if (!is_reserved(gpio, gpio, 0)) {
		gpio_error(gpio);
		return -EINVAL;
	}

	local_irq_save(flags);

	gpio_array[gpio_bank(gpio)]->inen &= ~gpio_bit(gpio);
	gpio_set_value(gpio, value);
	gpio_array[gpio_bank(gpio)]->dir |= gpio_bit(gpio);

	AWA_DUMMY_READ(dir);
	local_irq_restore(flags);

	return 0;
}
Ejemplo n.º 16
0
/*!
 * \brief Parses a string of uric characters starting at in[0] as defined in
 * http://www.ietf.org/rfc/rfc2396.txt (RFC explaining URIs).
 *
 * \return 
 */
static size_t parse_uric(
	/*! [in] String of characters. */
	const char *in,
	/*! [in] Maximum limit. */
	size_t max,
	/*! [out] Token object where the string of characters is copied. */
	token *out)
{
	size_t i = (size_t)0;

	while (i < max &&
	       (is_unreserved(in[i]) ||
	        is_reserved(in[i])   ||
	        ((i + (size_t)2 < max) && is_escaped(&in[i])))) {
		i++;
	}

	out->size = i;
	out->buff = in;
	return i;
}
Ejemplo n.º 17
0
std::string uri::decode(const std::experimental::string_view input) {
  std::string res;
  res.reserve(input.size());
  for (auto it = input.cbegin(), e = input.cend(); it not_eq e; ++it) {
    if (*it == '%') {

      if (++it >= e) return decode_error(std::move(res));
      const uint8_t nibble1 = (*it);

      if (++it >= e) return decode_error(std::move(res));
      const uint8_t nibble2 = (*it);

      res += static_cast<char>(from_hex(nibble1, nibble2));

    } else {
      if (is_reserved(*it) or is_unreserved(*it))
        res += *it;
      else
        return decode_error(std::move(res));
    }
  }
  return res;
}
Ejemplo n.º 18
0
int vgroup_insert(int32 infile_id,
                  int32 outfile_id,
                  int32 sd_id,             /* SD interface identifier */
                  int32 sd_out,            /* SD interface identifier */
                  int32 gr_id,             /* GR interface identifier */
                  int32 gr_out,            /* GR interface identifier */
                  int32 vgroup_id_out_par, /* output parent group ID */
                  char*path_name,          /* absolute path for input group name */          
                  int32* in_tags,          /* tag list for parent group */
                  int32* in_refs,          /* ref list for parent group */
                  int npairs,              /* number tag/ref pairs for parent group */
                  list_table_t *list_tbl,
                  dim_table_t *td1,
                  dim_table_t *td2,
                  options_t *options)
{
    int32 vg_id;             /* vgroup identifier for opened group in input */
    int32 ntagrefs;              /* number of tag/ref pairs in a vgroup */
    int32 *tags=NULL;            /* buffer to hold the tag numbers of vgroups   */
    int32 *refs=NULL;            /* buffer to hold the ref numbers of vgroups   */
    int32 vgroup_id_out =-1;         /* vgroup identifier for the created group in output */
    char  *vg_name;
    char  *vg_class;
    char  *path=NULL;
    uint16 name_len;
    int   visited;
    int32 tag;                   
    int32 ref; 
    int   i;

    
    for ( i = 0; i < npairs; i++ ) 
    {       
        tag = in_tags[i];
        ref = in_refs[i];
        
        switch(tag) 
        {
        /*-------------------------------------------------------------------------
         * DFTAG_VG
         *-------------------------------------------------------------------------
         */
        case DFTAG_VG: 

            visited = list_table_search(list_tbl,DFTAG_VG,ref);
            
           /*-------------------------------------------------------------------------
            * open input
            *-------------------------------------------------------------------------
            */
                    
            vg_id = Vattach (infile_id, ref, "r");

	    /* Get vgroup's name */
            if (Vgetnamelen(vg_id, &name_len)==FAIL)
            {
                printf("Error: Could not get name length for group with ref <%d>\n", ref);
                goto out;
            }
            vg_name = (char *) HDmalloc(sizeof(char) * (name_len+1));
            if (Vgetname (vg_id, vg_name)==FAIL)
            {
                printf( "Could not get name for group\n");
                goto out;
                
            }

	    /* Get vgroup's class name */
            if (Vgetclassnamelen(vg_id, &name_len)==FAIL)
            {
                printf("Error: Could not get name length for group with ref <%d>\n", ref);
                goto out;
            }

            vg_class = (char *) HDmalloc(sizeof(char) * (name_len+1));
            if (Vgetclass (vg_id, vg_class)==FAIL)
            {
                printf( "Could not get class for group\n");
                goto out;
            }
            
            /* ignore reserved HDF groups/vdatas */
            if( is_reserved(vg_class))
            {
                if (Vdetach (vg_id)==FAIL)
                {
                    printf( "Could not detach group\n");
                    goto out;
                }
                continue;
            }
            if(strcmp(vg_name,GR_NAME)==0) 
            {
                if (Vdetach (vg_id)==FAIL)
                {
                    printf( "Could not detach group\n");
                    goto out;
                }
                continue;
            }
            
            
           /*-------------------------------------------------------------------------
            * create the group in output or create the link
            *-------------------------------------------------------------------------
            */
         
            if (options->trip==1)
            {
            
                if ( visited < 0 )
                    
                {
                    
                   /* 
                    * create the group in the output file.  the vgroup reference number 
                    * is set to -1 for creating and the access mode is "w" for writing 
                    */
                    vgroup_id_out = Vattach (outfile_id, -1, "w");
                    if (Vsetname (vgroup_id_out, vg_name)==FAIL)
                    {
                        printf("Error: Could not create group <%s>\n", vg_name);
                        goto out;
                    }
                    if (Vsetclass (vgroup_id_out, vg_class)==FAIL)
                    {
                        printf("Error: Could not create group <%s>\n", vg_name);
                        goto out;
                    }
                    
                    if (copy_vgroup_attrs(vg_id,vgroup_id_out,path,options)<0)
                        goto out;
                    if (copy_vg_an(infile_id,outfile_id,vg_id,vgroup_id_out,path,options)<0)
                        goto out;
                    
                }
                
                else
                    
                {
                    /* open previously visited group */
                    vgroup_id_out = Vattach (outfile_id, ref, "r");


                }
                    
                
                /* insert the created (or opened) vgroup into its parent */
                if (Vinsert (vgroup_id_out_par, vgroup_id_out)==FAIL)
                {
                    printf("Could not insert group <%s>\n", vg_name);
                    goto out;
                }
                    
            } /* create the group in output or create the link */
            
            
            
             
           /*-------------------------------------------------------------------------
            * if group not visited, add to table and check for more tag/ref pairs
            *-------------------------------------------------------------------------
            */
            
                     
            /* check if already visited */
            if ( visited < 0  ) 
            {
                
                /* initialize path */
                path=get_path(path_name,vg_name);
                
                /* add object to table */
                list_table_add(list_tbl,tag,ref,path);
                
                if (options->verbose)
                    printf(PFORMAT,"","","",path);    
                
                if ( options->trip==0 ) 
                {
                    /*we must go to other groups always */
                }
                
                
                /* insert objects for this group */
                ntagrefs  = Vntagrefs(vg_id);
                if ( ntagrefs > 0 )
                {
                    tags = (int32 *) malloc(sizeof(int32) * ntagrefs);
                    refs = (int32 *) malloc(sizeof(int32) * ntagrefs);
                    if (Vgettagrefs(vg_id, tags, refs, ntagrefs)<0)
                        goto out;
                    /* recurse */
                    if (vgroup_insert(
                        infile_id,
                        outfile_id,
                        sd_id,
                        sd_out,
                        gr_id,
                        gr_out,
                        vgroup_id_out,
                        path,
                        tags,
                        refs,
                        ntagrefs,
                        list_tbl,
                        td1,
                        td2,
                        options)<0) {
                        goto out;
                    }
                    free (tags);
                    tags=NULL;
                    free (refs);
                    refs=NULL;
                } /* ntagrefs > 0 */
                
                
                if (path)
                    free(path);
                
            } /* check if already visited */
            
            
            if(Vdetach (vg_id)==FAIL)
            {
                printf("Error: Could not detach group <%s>\n", vg_name);
                goto out;
            }
            if (options->trip==1)
            {
                if (Vdetach (vgroup_id_out)==FAIL)
                {
                    printf("Error: Could not detach group <%s>\n", vg_name);
                    goto out;
                }
            }
            
            break;
            
            
  /*-------------------------------------------------------------------------
   * SDS
   *-------------------------------------------------------------------------
   */   
            
  case DFTAG_SD:  /* Scientific Data */
  case DFTAG_SDG: /* Scientific Data Group */
  case DFTAG_NDG: /* Numeric Data Group */
      /* copy dataset */
      if (copy_sds(sd_id,
          sd_out,
          tag,ref,
          vgroup_id_out_par,
          path_name,
          options,
          list_tbl,
          td1,
          td2,
          infile_id,
          outfile_id)<0)
          return FAIL;
      
      break;
      
  /*-------------------------------------------------------------------------
   * Image
   *-------------------------------------------------------------------------
   */   
      
  case DFTAG_RI:   /* Raster Image */
  case DFTAG_CI:   /* Compressed Image */
  case DFTAG_RIG:  /* Raster Image Group */
  case DFTAG_RI8:  /* Raster-8 image */
  case DFTAG_CI8:  /* RLE compressed 8-bit image */
  case DFTAG_II8:  /* IMCOMP compressed 8-bit image */
      /* copy GR  */
      if (copy_gr(infile_id,
          outfile_id,
          gr_id,
          gr_out,
          tag,
          ref,
          vgroup_id_out_par,
          path_name,
          options,
          list_tbl)<0)
          return FAIL;
      break;
      
 /*-------------------------------------------------------------------------
  * Vdata
  *-------------------------------------------------------------------------
  */   
      
  case DFTAG_VH:  /* Vdata Header */
      if (copy_vs(infile_id,
          outfile_id,
          tag,
          ref,
          vgroup_id_out_par,
          path_name,
          options,
          list_tbl,
          0)<0)
          return FAIL;
      break;
  } /* switch */
  
 } /* i */
 
 return SUCCEED;
 
out:
 
 if (tags!=NULL)
     free (tags);
 if (refs!=NULL)
     free (refs);
 
 return FAIL;
}
Ejemplo n.º 19
0
int list_vg(int32 infile_id,
            int32 outfile_id,
            int32 sd_id,
            int32 sd_out,
            int32 gr_id,
            int32 gr_out,
            list_table_t *list_tbl,
            dim_table_t *td1,
            dim_table_t *td2,
            options_t *options)
{
   

    int32  vg_id;          /* vgroup identifier */
    int32  nlones = 0;     /* number of lone vgroups */
    int32  ntagrefs;       /* number of tag/ref pairs in a vgroup */
    int32  *ref_array=NULL;/* buffer to hold the ref numbers of lone vgroups   */
    int32  *tags=NULL;     /* buffer to hold the tag numbers of vgroups   */
    int32  *refs=NULL;     /* buffer to hold the ref numbers of vgroups   */
    int32  vgroup_id_out=0;/* vgroup identifier */
    int32  tag_vg;
    int32  ref_vg;
    char   *vg_name;
    char   *vg_class;
    uint16 name_len;
    int32  i;
    
   /*-------------------------------------------------------------------------
    * initialize the V interface
    *-------------------------------------------------------------------------
    */
    
    if (Vstart(infile_id) == FAIL)  
    {
        return FAIL;
    } 
    
    if (options->trip==1)
    {
        if (Vstart(outfile_id) == FAIL)  
        {
            return FAIL;
        }
    }
    
   /*-------------------------------------------------------------------------
    * get and print the names and class names of all the lone vgroups.
    * first, call Vlone with nlones set to 0 to get the number of
    * lone vgroups in the file, but not to get their reference numbers.
    *-------------------------------------------------------------------------
    */
    nlones = Vlone (infile_id, NULL, nlones );
    
    if (nlones > 0)
    {
       /*
        * use the nlones returned to allocate sufficient space for the
        * buffer ref_array to hold the reference numbers of all lone vgroups,
        */
        ref_array = (int32 *) malloc(sizeof(int32) * nlones);
        
       /*
        * and call Vlone again to retrieve the reference numbers into 
        * the buffer ref_array.
        */
        nlones = Vlone (infile_id, ref_array, nlones);
        
       /*
        * iterate tru each lone vgroup.
        */
        for (i = 0; i < nlones; i++)
        {

            int32 ref = ref_array[i];
	    uint16 name_len;

           /*
            * attach to the current vgroup then get its
            * name and class. note: the current vgroup must be detached before
            * moving to the next.
            */
            if ((vg_id = Vattach (infile_id, ref, "r"))==FAIL)
            {
                printf("Error: Could not attach group with ref <%d>\n", ref);
                goto out;
            }

	    /* Get vgroup's name */
            if (Vgetnamelen(vg_id, &name_len)==FAIL)
            {
                printf("Error: Could not get name length for group with ref <%d>\n", ref);
                goto out;
            }
            vg_name = (char *) HDmalloc(sizeof(char) * (name_len+1));

            if (Vgetname (vg_id, vg_name)==FAIL)
            {
                printf( "Could not get name for group\n");
                goto out;
                
            }

	    /* Get vgroup's class name */
            if (Vgetclassnamelen(vg_id, &name_len)==FAIL)
            {
                printf("Error: Could not get name length for group with ref <%d>\n", ref);
                goto out;
            }


            vg_class = (char *) HDmalloc(sizeof(char) * (name_len+1));

            if (Vgetclass (vg_id, vg_class)==FAIL)
            {
                printf( "Could not get class for group\n");
                goto out;
            }
            
            /* ignore reserved HDF groups/vdatas */
            if( is_reserved(vg_class))
            {
                if (Vdetach (vg_id)==FAIL)
                {
                    printf( "Could not detach group\n");
                    goto out;
                }
                continue;
            }
            if(strcmp(vg_name,GR_NAME)==0) 
            {
                if (Vdetach (vg_id)==FAIL)
                {
                    printf( "Could not detach group\n");
                    goto out;
                }
                continue;
            }
            
            /* get ref, tag */
            if ((ref_vg = VQueryref(vg_id))==FAIL)
            {
                printf( "Failed to get ref for <%s>\n", vg_name);
                goto out;
            }
            if ((tag_vg = VQuerytag(vg_id))==FAIL)
            {
                printf( "Failed to get tag for <%s>\n", vg_name);
                goto out;
            }
            
           /*-------------------------------------------------------------------------
            * add object to table
            *-------------------------------------------------------------------------
            */
            list_table_add(list_tbl,tag_vg,ref_vg,vg_name);
            
            if (options->verbose)
                printf(PFORMAT,"","","",vg_name);  
            
            if (options->trip==1)
            {
                
               /* 
                * create the group in the output file.  the vgroup reference number is set
                * to -1 for creating and the access mode is "w" for writing 
                */
                vgroup_id_out = Vattach (outfile_id, -1, "w");
                if (Vsetname (vgroup_id_out, vg_name)==FAIL)
                {
                    printf("Error: Could not create group <%s>\n", vg_name);
                    goto out;
                }
                if (Vsetclass (vgroup_id_out, vg_class)==FAIL)
                {
                    printf("Error: Could not create group <%s>\n", vg_name);
                    goto out;
                }
                
                if (copy_vgroup_attrs(vg_id,vgroup_id_out,vg_name,options)<0)
                    goto out;
                if (copy_vg_an(infile_id,outfile_id,vg_id,vgroup_id_out,vg_name,options)<0)
                    goto out;
            }
            
            
            
            /* insert objects for this group */
            ntagrefs = Vntagrefs(vg_id);
            if ( ntagrefs > 0 )
            {
                tags = (int32 *) malloc(sizeof(int32) * ntagrefs);
                refs = (int32 *) malloc(sizeof(int32) * ntagrefs);
                if (Vgettagrefs(vg_id, tags, refs, ntagrefs)<0)
                    goto out;
                
                if (vgroup_insert(infile_id,
                    outfile_id,
                    sd_id,
                    sd_out,
                    gr_id,
                    gr_out,
                    vgroup_id_out,
                    vg_name,
                    tags,
                    refs,
                    ntagrefs,
                    list_tbl,
                    td1,
                    td2,
                    options)<0) {
                    goto out;
                }
                
                free (tags);
                tags=NULL;
                free (refs);
                refs=NULL;
            }
            
            if(Vdetach (vg_id)==FAIL)
            {
                printf("Error: Could not detach group <%s>\n", vg_name);
                goto out;
            }
            if (options->trip==1)
            {
                if (Vdetach (vgroup_id_out)==FAIL)
                {
                    printf("Error: Could not detach group <%s>\n", vg_name);
                    goto out;
                }
            }

            free (vg_name);
            
  } /* for nlones */
  
  
  /* free the space allocated */
  if (ref_array!=NULL) 
      free (ref_array);

 } /* if  nlones */
 

/*-------------------------------------------------------------------------
 * terminate access to the V interface
 *-------------------------------------------------------------------------
 */
 
 if (Vend (infile_id)==FAIL)
 {
     printf("Error: Could not end group interface in <%s>\n", vg_name);
     return FAIL;
 }
 if (options->trip==1)
 {
     if (Vend (outfile_id)==FAIL){
         printf("Error: Could not end group interface in <%s>\n", vg_name);
         return FAIL;
     }
 }
 
 return SUCCEED;
 
 
out:
 
 Vend (infile_id);
 if (options->trip==1)
     Vend (outfile_id);
 
 /* free the space allocated */
 if (ref_array!=NULL) 
     free (ref_array);
 if (tags!=NULL) 
     free (tags);
 if (refs!=NULL) 
     free (refs);
 
 return FAIL;
 
}
Ejemplo n.º 20
0
static int ftp_init_transfer(void)
{
	struct sockaddr_storage sa;
	unsigned char *a, *p;

	if(!ftp_connected())
		return -1;

	if (!(ftp->data = sock_create())) {
		return -1;
	}
	sock_copy(ftp->data, ftp->ctrl);

	if (ftp_is_passive())
  {
    memcpy(&sa, sock_remote_addr(ftp->ctrl), sizeof(struct sockaddr_storage));

    unsigned char pac[6];
    unsigned short ipv6_port;
		if (!ftp_pasv(sa.ss_family != AF_INET, pac, &ipv6_port))
			goto err1;

    socklen_t len = sizeof(struct sockaddr_in);
    if (sa.ss_family == AF_INET)
    {
      memcpy(&((struct sockaddr_in*)&sa)->sin_addr, pac, (size_t)4);
		  memcpy(&((struct sockaddr_in*)&sa)->sin_port, pac+4, (size_t)2);
    }
#ifdef HAVE_IPV6
    else if (sa.ss_family == AF_INET6)
    {
      ((struct sockaddr_in6*)&sa)->sin6_port = htons(ipv6_port);
      len = sizeof(struct sockaddr_in6);
    }
#endif
    else
      return -1;

    struct sockaddr_storage tmp;
    memcpy(&tmp, sock_remote_addr(ftp->ctrl), sizeof(struct sockaddr_storage));
		if (is_reserved((struct sockaddr*) &sa) ||
			   is_multicast((struct sockaddr*) &sa)  ||
			   (is_private((struct sockaddr*) &sa) != is_private((struct sockaddr*) &tmp)) ||
			   (is_loopback((struct sockaddr*) &sa) != is_loopback((struct sockaddr*) &tmp)))
		{
			// Invalid address returned by PASV. Replace with address from control
			// socket.
			ftp_err(_("Address returned by PASV seems to be incorrect.\n"));
			((struct sockaddr_in*)&sa)->sin_addr = ((struct sockaddr_in*)&tmp)->sin_addr;
		}

		if (!sock_connect_addr(ftp->data, (struct sockaddr*) &sa, len))
    {
      perror("connect()");
			goto err1;
    }
	} else {
    const struct sockaddr* local = sock_local_addr(ftp->data);
		sock_listen(ftp->data, local->sa_family);

    if (local->sa_family == AF_INET)
    {
      struct sockaddr_in* tmp = (struct sockaddr_in*)local;
  		a = (unsigned char *)&tmp->sin_addr;
	  	p = (unsigned char *)&tmp->sin_port;

		  ftp_set_tmp_verbosity(vbError);
		  ftp_cmd("PORT %d,%d,%d,%d,%d,%d",
				  a[0], a[1], a[2], a[3], p[0], p[1]);
    }
#ifdef HAVE_IPV6
    else if (local->sa_family == AF_INET6)
    {
      char* addr = printable_address(local);

      ftp_set_tmp_verbosity(vbError);
		  ftp_cmd("EPRT |2|%s|%u", addr, ntohs(((struct sockaddr_in6*)local)->sin6_port));
      free(addr);
    }
#endif
    else
      goto err1;

		if(ftp->code != ctComplete)
			goto err1;
	}

	sock_throughput(ftp->data);

	return 0;

 err1:
	sock_destroy(ftp->data);
	ftp->data = 0;
	return -1;
}
Ejemplo n.º 21
0
/**
 * Get info on the next appendable volume in the Director's database
 *
 * Returns: true  on success dcr->VolumeName is volume
 *                reserve_volume() called on Volume name
 *          false on failure dcr->VolumeName[0] == 0
 *                also sets dcr->found_in_use if at least one
 *                in use volume was found.
 *
 * Volume information returned in dcr
 */
bool SD_DCR::dir_find_next_appendable_volume()
{
    bool retval;
    BSOCK *dir = jcr->dir_bsock;
    POOL_MEM unwanted_volumes(PM_MESSAGE);

    Dmsg2(dbglvl, "dir_find_next_appendable_volume: reserved=%d Vol=%s\n", is_reserved(), VolumeName);

    /*
     * Try the twenty oldest or most available volumes. Note,
     * the most available could already be mounted on another
     * drive, so we continue looking for a not in use Volume.
     */
    lock_volumes();
    P(vol_info_mutex);
    clear_found_in_use();

    pm_strcpy(unwanted_volumes, "");
    for (int vol_index = 1; vol_index < 20; vol_index++) {
       bash_spaces(media_type);
       bash_spaces(pool_name);
       bash_spaces(unwanted_volumes.c_str());
       dir->fsend(Find_media, jcr->Job, vol_index, pool_name, media_type, unwanted_volumes.c_str());
       unbash_spaces(media_type);
       unbash_spaces(pool_name);
       unbash_spaces(unwanted_volumes.c_str());
       Dmsg1(dbglvl, ">dird %s", dir->msg);

       if (do_get_volume_info(this)) {
          if (vol_index == 1) {
             pm_strcpy(unwanted_volumes, VolumeName);
          } else {
             pm_strcat(unwanted_volumes, ",");
             pm_strcat(unwanted_volumes, VolumeName);
          }

          if (can_i_write_volume()) {
             Dmsg1(dbglvl, "Call reserve_volume for write. Vol=%s\n", VolumeName);
             if (reserve_volume(this, VolumeName) == NULL) {
                Dmsg2(dbglvl, "Could not reserve volume %s on %s\n", VolumeName, dev->print_name());
                continue;
             }
             Dmsg1(dbglvl, "dir_find_next_appendable_volume return true. vol=%s\n", VolumeName);
             retval = true;
             goto get_out;
          } else {
             Dmsg1(dbglvl, "Volume %s is in use.\n", VolumeName);

             /*
              * If volume is not usable, it is in use by someone else
              */
             set_found_in_use();
             continue;
          }
       }
       Dmsg2(dbglvl, "No vol. index %d return false. dev=%s\n", vol_index, dev->print_name());
       break;
    }
    retval = false;
    VolumeName[0] = 0;

get_out:
    V(vol_info_mutex);
    unlock_volumes();

    return retval;
}
Ejemplo n.º 22
0
void handle_request(worker_type_t wtype) {
    const char *param, *p_method, *p_uri;
    char *argp;
    unsigned int plen;
    int cluster_readonly = 0, s2sreq = 0;

    if(sx_hashfs_cluster_get_mode(hashfs, &cluster_readonly)) {
        CRIT("Failed to get cluster operating mode");
        quit_errmsg(500, "Internal error: failed to check cluster operating mode");
    }

    if(sx_hashfs_distcheck(hashfs) < 0) {
	CRIT("Failed to reload distribution");
	quit_errmsg(503, "Internal error: failed to load distribution");
    }

    if(sx_hashfs_is_orphan(hashfs))
	quit_errmsg(410, "This node is no longer a cluster member");

    msg_new_id();
    verb = VERB_UNSUP;
    p_method = FCGX_GetParam("REQUEST_METHOD", envp);
    if(p_method) {
	plen = strlen(p_method);
	switch(plen) {
	case 3:
	    if(!memcmp(p_method, "GET", 4))
		verb = VERB_GET;
	    else if(!memcmp(p_method, "PUT", 4))
		verb = VERB_PUT;
	    break;
	case 4:
	    if(!memcmp(p_method, "HEAD", 5))
		verb = VERB_HEAD;
	    else if(!memcmp(p_method, "POST", 5))
		verb = VERB_POST;
	    break;
	case 6:
	    if(!memcmp(p_method, "DELETE", 7))
		verb = VERB_DELETE;
	    break;
	case 7:
	    if(!memcmp(p_method, "OPTIONS", 8)) {
		CGI_PUTS("Allow: GET,HEAD,OPTIONS,PUT,DELETE\r\nContent-Length: 0\r\n\r\n");
		return;
	    }
	    break;
	}
    }
    if(verb == VERB_UNSUP)
	quit_errmsg(405, "Method Not Allowed");

    if(content_len()<0 || (verb != VERB_PUT && content_len()))
	quit_errmsg(400, "Invalid Content-Length: must be positive and method must be PUT");

    p_uri = param = FCGX_GetParam("REQUEST_URI", envp);
    if(!p_uri)
	quit_errmsg(400, "No URI provided");
    plen = strlen(p_uri);
    if(*p_uri != '/')
	quit_errmsg(400, "URI must start with /");
    if(plen > sizeof(reqbuf) - 1)
	quit_errmsg(414, "URL too long: request line must be <8k");

    do {
	param++;
	plen--;
    } while(*param == '/');

    if(!strncmp(param, ".s2s/", lenof(".s2s/"))) {
	param += lenof(".s2s/");
	plen -= lenof(".s2s/");
	while(*param == '/') {
	    param++;
	    plen--;
	}
	s2sreq = 1;
    }
    if(wtype == WORKER_S2S && !s2sreq)
	WARN("Misconfiguration detected. Please make sure your restricted-socket config option is properly set.");
    /* FIXME: we could detect the opposite kind of mismatch
     * at the cost of extra complications in the wtype definition
     * I prefer to privilege simplicity at this point */

    memcpy(reqbuf, param, plen+1);
    argp = memchr(reqbuf, '?', plen);
    nargs = 0;
    if(argp) {
	unsigned int argslen = plen - (argp - reqbuf);
	plen = argp - reqbuf;
	do {
	    *argp = '\0';
	    argp++;
	    argslen--;
	} while(*argp == '?');
	if(!argslen)
	    argp = NULL;
	else {
	    do {
		char *nextarg;
		if(nargs >= MAX_ARGS)
		    quit_errmsg(414, "Too many parameters");
		nextarg = memchr(argp, '&', argslen);
		if(nextarg) {
		    do {
			*nextarg = '\0';
			nextarg++;
		    } while(*nextarg == '&');
		}
		if(*argp) {
		    if(!(args[nargs] = inplace_urldecode(argp, 0, 0, NULL, 1)))
			quit_errmsg(400, "Invalid URL encoding");
		    if(sxi_utf8_validate_len(args[nargs]) < 0)
			quit_errmsg(400, "Parameters with invalid utf-8 encoding");
		    nargs++;
		}
		argslen -= nextarg - argp;
		argp = nextarg;
	    } while (argp);
	}
    }

    while(plen && reqbuf[plen-1] == '/') {
	plen--;
	reqbuf[plen] = '\0';
    }

    path = memchr(reqbuf, '/', plen);
    if(path) {
	do {
	    *path = '\0';
	    path ++;
	} while(*path == '/');
	if(!*path)
	    path = NULL;
    }
    volume = *reqbuf ? reqbuf : NULL;

    int forbidden = 0;
    if((volume && !inplace_urldecode(volume, '/', 0, &forbidden, 0)) || (path && !inplace_urldecode(path, '/', '/', &forbidden, 0))) {
        if (forbidden)
            quit_errmsg(400, "Volume or path with forbidden %2f or %00");
        else
            quit_errmsg(400, "Invalid URL encoding");
    }

    int vlen = volume ? sxi_utf8_validate_len(volume) : 0;
    int flen = path ? strlen(path) : 0;

    if (vlen < 0 || flen < 0)
       quit_errmsg(400, "URL with invalid utf-8 encoding");

    if (is_reserved()) {
        /* No UTF8/url-encoding used on reserved volumes, allow higher limit.
         * Otherwise we hit the 1024 limit with batch requests already */
        if (path && strlen(path) > SXLIMIT_MAX_FILENAME_LEN * 3) {
            msg_set_reason("Path too long: filename must be <%d bytes (%ld)",
                           SXLIMIT_MAX_FILENAME_LEN*3+ 1, strlen(path));
            quit_errmsg(414, msg_get_reason());
        }
    } else {
        if (flen > SXLIMIT_MAX_FILENAME_LEN) {
            msg_set_reason("Path too long: filename must be <%d bytes (%d)",
                           SXLIMIT_MAX_FILENAME_LEN + 1, flen);
            quit_errmsg(414, msg_get_reason());
        }
    }

    if (volume && strlen(volume) > SXLIMIT_MAX_VOLNAME_LEN) {
        msg_set_reason("Volume name too long: must be <= %d bytes", SXLIMIT_MAX_VOLNAME_LEN);
        quit_errmsg(414, msg_get_reason());
    }

    body_ctx = sxi_md_init();
    if (!body_ctx || !sxi_sha1_init(body_ctx))
	quit_errmsg(500, "Failed to initialize crypto engine");
    hmac_ctx = sxi_hmac_sha1_init();
    if (!hmac_ctx)
        quit_errmsg(503, "Cannot initialize crypto library");

    authed = AUTH_NOTAUTH;
    role = PRIV_NONE;


    /* Begin auth check */
    uint8_t buf[AUTHTOK_BIN_LEN], key[AUTH_KEY_LEN];
    unsigned int blen = sizeof(buf);
    time_t reqdate, now;

    param = FCGX_GetParam("HTTP_AUTHORIZATION", envp);
    if(!param || strlen(param) != lenof("SKY ") + AUTHTOK_ASCII_LEN || strncmp(param, "SKY ", 4)) {
	if(volume) {
	    send_authreq();
	    return;
	}
	quit_home();
    }

    if(sxi_b64_dec_core(param+4, buf, &blen) || blen != sizeof(buf)) {
	send_authreq();
	return;
    }

    memcpy(user, buf, sizeof(user));
    memcpy(rhmac, buf+20, sizeof(rhmac));

    if(sx_hashfs_get_user_info(hashfs, user, &uid, key, &role, NULL, &user_quota) != OK) /* no such user */ {
	DEBUG("No such user: %s", param+4);
	send_authreq();
	return;
    }
    DEBUG("Request from uid %lld", (long long)uid);
    if(cluster_readonly && (verb == VERB_PUT || verb == VERB_DELETE) && !has_priv(PRIV_CLUSTER) && !has_priv(PRIV_ADMIN))
        quit_errmsg(503, "Cluster is in read-only mode");

    if(s2sreq && !has_priv(PRIV_CLUSTER)) {
	send_authreq();
	return;
    }

    if(!sxi_hmac_sha1_init_ex(hmac_ctx, key, sizeof(key))) {
	WARN("hmac_init failed");
	quit_errmsg(500, "Failed to initialize crypto engine");
    }

    if(!sxi_hmac_sha1_update_str(hmac_ctx, p_method))
	quit_errmsg(500, "Crypto error authenticating the request");

    if(!sxi_hmac_sha1_update_str(hmac_ctx, p_uri+1))
	quit_errmsg(500, "Crypto error authenticating the request");

    param = FCGX_GetParam("HTTP_DATE", envp);
    if(!param)
	quit_errmsg(400, "Missing Date: header");
    if(httpdate_to_time_t(param, &reqdate))
	quit_errmsg(400, "Date header in wrong format");
    now = time(NULL);
    if(reqdate < now - MAX_CLOCK_DRIFT * 60 || reqdate > now + MAX_CLOCK_DRIFT * 60) {
	CGI_PUTS("WWW-Authenticate: SKY realm=\"SXCLOCK\"\r\n");
	quit_errmsg(401, "Client clock drifted more than "STRIFY(MAX_CLOCK_DRIFT)" minutes");
    }
    if(!sxi_hmac_sha1_update_str(hmac_ctx, param))
	quit_errmsg(500, "Crypto error authenticating the request");

    if(!content_len()) {
	/* If no body is present, complete authentication now */
	uint8_t chmac[20];
	unsigned int chmac_len = 20;
	if(!sxi_hmac_sha1_update_str(hmac_ctx, "da39a3ee5e6b4b0d3255bfef95601890afd80709"))
	    quit_errmsg(500, "Crypto error authenticating the request");
	if(!sxi_hmac_sha1_final(hmac_ctx, chmac, &chmac_len))
	    quit_errmsg(500, "Crypto error authenticating the request");
	if(!hmac_compare(chmac, rhmac, sizeof(rhmac))) {
	    authed = AUTH_OK;
	} else {
	    /* WARN("auth mismatch"); */
	    send_authreq();
	    return;
	}
    } else /* Otherwise set it as pending */
	authed = AUTH_BODYCHECK;

    if(has_priv(PRIV_CLUSTER) && sx_hashfs_uses_secure_proto(hashfs) != is_https() &&
       !sx_storage_is_bare(hashfs)) {
        /* programmed nodes: must obey cluster SSL mode
         * unprogrammed nodes: can use SSL instead of non-SSL,
         *  it is the cluster's responsibility to initiate programming via SSL,
         *  as the unprogrammed node would accept both         *
         * */
        WARN("hashfs use-ssl: %d, https: %d, is_bare: %d",
              sx_hashfs_uses_secure_proto(hashfs), is_https(),
              sx_storage_is_bare(hashfs));
	quit_errmsg(403, sx_hashfs_uses_secure_proto(hashfs) ? "Cluster operations require SECURE mode" : "Cluster operations require INSECURE mode");
    }

    if(!volume)
	cluster_ops();
    else if(!path)
	volume_ops();
    else
	file_ops();

    if(authed == AUTH_BODYCHECKING)
	DEBUG("Bad request signature");

    sxi_hmac_sha1_cleanup(&hmac_ctx);
    sxi_md_cleanup(&body_ctx);
}
Ejemplo n.º 23
0
/***************************************************************
 * rta_add_table(): - Add one table to the list of
 * tables in the system.  If the table has an associated
 * "savefile" we try to open the savefile and execute any SQL
 * commands found there.
 *
 * Input:  ptbl:  pointer to the table to add
 * Output: RTA_SUCCESS   - Add successful
 *         RTA_DUP       - Table is already in the list.  (Note
 *                         that this might not be an error since
 *                         we can allow redefinition of a table)
 *         RTA_ERROR     - The passed table definition has a
 *                         problem which prevents its addition.
 *                         A syslog error message describes the
 *                         problem
 **************************************************************/
int
rta_add_table(RTA_TBLDEF *ptbl)
{
  extern RTA_TBLDEF rta_columnsTable;
  int      i, j;       /* a loop index */


  /* Initialize the RTA tables if this is the first call to add_table */
  if (rta_Ntbl == -1)
    rta_init();

  /* Error if at rta_Ntbl limit */
  if (rta_Ntbl == RTA_MX_TBL) {
    rta_log(LOC, Er_Max_Tbls);
    return (RTA_ERROR);
  }

  /* verify that table name is unique */
  i = 0;
  while (i < rta_Ntbl) {
    if (!strncmp(ptbl->name, rta_Tbl[i]->name, RTA_MXTBLNAME)) {
      rta_log(LOC, Er_Tbl_Dup, ptbl->name);
      return (RTA_ERROR);
    }
    i++;
  }

  /* verify length of table name */
  if (strlen(ptbl->name) > RTA_MXTBLNAME) {
    rta_log(LOC, Er_Tname_Big, ptbl->name);
    return (RTA_ERROR);
  }

  /* verify table name is not a reserved word */
  if (is_reserved(ptbl->name)) {
    rta_log(LOC, Er_Reserved, ptbl->name);
    return (RTA_ERROR);
  }

  /* verify savefile name is a valid pointer */
  if (ptbl->savefile == (char *) 0) {
    rta_log(LOC, Er_Col_Type, "savefile");
    return (RTA_ERROR);
  }

  /* Check the upper bound on # columns / table */
  if (ptbl->ncol > RTA_NCMDCOLS) {
    rta_log(LOC, Er_Cmd_Cols, ptbl->name);
    return (RTA_ERROR);
  }

  /* verify that column names are unique within table */
  for (i = 0; i < ptbl->ncol; i++) {
    for (j = 0; j < i; j++) {
      if (!strncmp(ptbl->cols[i].name, ptbl->cols[j].name, RTA_MXCOLNAME)) {
        rta_log(LOC, Er_Col_Dup, ptbl->name, ptbl->cols[i].name);
        return (RTA_ERROR);
      }
    }
  }

  /* verify column name length, help length, data type, flag contents,
     and that column table name is valid */
  for (i = 0; i < ptbl->ncol; i++) {
    if (strlen(ptbl->cols[i].name) > RTA_MXCOLNAME) {
      rta_log(LOC, Er_Cname_Big, ptbl->cols[i].name);
      return (RTA_ERROR);
    }
    if (is_reserved(ptbl->cols[i].name)) {
      rta_log(LOC, Er_Reserved, ptbl->cols[i].name);
      return (RTA_ERROR);
    }
    if (strlen(ptbl->cols[i].help) > RTA_MXHELPSTR) {
      rta_log(LOC, Er_Hname_Big, ptbl->cols[i].name);
      return (RTA_ERROR);
    }
    if (ptbl->cols[i].type > RTA_MXCOLTYPE) {
      rta_log(LOC, Er_Col_Type, ptbl->cols[i].name);
      return (RTA_ERROR);
    }
    if (ptbl->cols[i].flags > RTA_DISKSAVE + RTA_READONLY) {
      rta_log(LOC, Er_Col_Flag, ptbl->cols[i].name);
      return (RTA_ERROR);
    }
    if (strcmp(ptbl->cols[i].table, ptbl->name)) {
      rta_log(LOC, Er_Col_Name, ptbl->cols[i].name);
      return (RTA_ERROR);
    }
  }

  /* Verify that we can add the columns */
  if ((rta_Ncol + ptbl->ncol) >= RTA_MX_COL) {
    rta_log(LOC, Er_Max_Cols);
    return (RTA_ERROR);
  }

  /* Everything looks OK.  Add table and columns */
  rta_Tbl[rta_Ntbl++] = ptbl;
  rta_Tbl[0]->nrows = rta_Ntbl;

  /* Add columns to list of column pointers */
  for (i = 0; i < ptbl->ncol; i++) {
    rta_Col[rta_Ncol++] = &(ptbl->cols[i]);
  }
  rta_columnsTable.nrows += ptbl->ncol;

  /* Execute commands in the save file to restore */
  if (ptbl->savefile && strlen(ptbl->savefile) > 0)
    (void) rta_load(ptbl, ptbl->savefile);

  return (RTA_SUCCESS);
}
Ejemplo n.º 24
0
void handle_request(void) {
    const char *param;
    char *argp;
    unsigned int plen;

    msg_new_id();
    verb = VERB_UNSUP;
    param = FCGX_GetParam("REQUEST_METHOD", envp);
    if(param) {
	plen = strlen(param);
	switch(plen) {
	case 3:
	    if(!memcmp(param, "GET", 4))
		verb = VERB_GET;
	    else if(!memcmp(param, "PUT", 4))
		verb = VERB_PUT;
	    break;
	case 4:
	    if(!memcmp(param, "HEAD", 5))
		verb = VERB_HEAD;
	    else if(!memcmp(param, "POST", 5))
		verb = VERB_POST;
	    break;
	case 6:
	    if(!memcmp(param, "DELETE", 7))
		verb = VERB_DELETE;
	    break;
	case 7:
	    if(!memcmp(param, "OPTIONS", 8)) {
		CGI_PUTS("Allow: GET,HEAD,OPTIONS,PUT,DELETE\r\nContent-Length: 0\r\n\r\n");
		return;
	    }
	    break;
	}
    }
    if(verb == VERB_UNSUP)
	quit_errmsg(405, "Method Not Allowed");

    if(content_len()<0 || (verb != VERB_PUT && content_len()))
	quit_errmsg(400, "Invalid Content-Length: must be positive and method must be PUT");

    param = FCGX_GetParam("REQUEST_URI", envp);
    if(!param)
	quit_errmsg(400, "No URI provided");
    plen = strlen(param);
    if(*param != '/')
	quit_errmsg(400, "URI must start with /");
    if(plen > sizeof(reqbuf) - 1)
	quit_errmsg(414, "URL too long: request line must be <8k");

    do {
	param++;
	plen--;
    } while(*param == '/');

    memcpy(reqbuf, param, plen+1);
    argp = memchr(reqbuf, '?', plen);
    nargs = 0;
    if(argp) {
	unsigned int argslen = plen - (argp - reqbuf);
	plen = argp - reqbuf;
	do {
	    *argp = '\0';
	    argp++;
	    argslen--;
	} while(*argp == '?');
	if(!argslen)
	    argp = NULL;
	else {
	    do {
		char *nextarg;
		if(nargs >= MAX_ARGS)
		    quit_errmsg(414, "Too many parameters");
		nextarg = memchr(argp, '&', argslen);
		if(nextarg) {
		    do {
			*nextarg = '\0';
			nextarg++;
		    } while(*nextarg == '&');
		}
		if(*argp) {
		    if(!(args[nargs] = inplace_urldecode(argp, 0, 0, NULL)))
			quit_errmsg(400, "Invalid URL encoding");
		    if(utf8_validate_len(args[nargs]) < 0)
			quit_errmsg(400, "Parameters with invalid utf-8 encoding");
		    nargs++;
		}
		argslen -= nextarg - argp;
		argp = nextarg;
	    } while (argp);
	}
    }

    while(plen && reqbuf[plen-1] == '/') {
	plen--;
	reqbuf[plen] = '\0';
    }

    path = memchr(reqbuf, '/', plen);
    if(path) {
	do {
	    *path = '\0';
	    path ++;
	} while(*path == '/');
	if(!*path)
	    path = NULL;
    }
    volume = *reqbuf ? reqbuf : NULL;

    int forbidden = 0;
    if((volume && !inplace_urldecode(volume, '/', 0, &forbidden)) || (path && !inplace_urldecode(path, '/', '/', &forbidden))) {
        if (forbidden)
            quit_errmsg(400, "Volume or path with forbidden %2f or %00");
        else
            quit_errmsg(400, "Invalid URL encoding");
    }

    int vlen = volume ? utf8_validate_len(volume) : 0;
    int flen = path ? utf8_validate_len(path) : 0;

    if (vlen < 0 || flen < 0)
       quit_errmsg(400, "URL with invalid utf-8 encoding");

    if (is_reserved()) {
        /* No UTF8 used on reserved volumes, allow higher limit.
         * Otherwise we hit the 512 limit with batch requests already */
        if (path && strlen(path) > SXLIMIT_MAX_FILENAME_LEN * 12) {
            msg_set_reason("Path too long: filename must be <%d characters (%ld)",
                           SXLIMIT_MAX_FILENAME_LEN*12+ 1, strlen(path));
            quit_errmsg(414, msg_get_reason());
        }
    } else {
        if (flen > SXLIMIT_MAX_FILENAME_LEN) {
            msg_set_reason("Path too long: filename must be <%d UTF8 characters (%d)",
                           SXLIMIT_MAX_FILENAME_LEN + 1, flen);
            quit_errmsg(414, msg_get_reason());
        }
    }

    if (volume && strlen(volume) > SXLIMIT_MAX_VOLNAME_LEN) {
        msg_set_reason("Volume name too long: must be <= %d bytes", SXLIMIT_MAX_VOLNAME_LEN);
        quit_errmsg(414, msg_get_reason());
    }

    if(!EVP_DigestInit(&body_ctx, EVP_sha1()))
	quit_errmsg(500, "Failed to initialize crypto engine");
    HMAC_CTX_init(&hmac_ctx);

    authed = AUTH_NOTAUTH;
    role = PRIV_NONE;
    auth_begin();

    if(has_priv(PRIV_CLUSTER) && sx_hashfs_uses_secure_proto(hashfs) != is_https() &&
       !sx_storage_is_bare(hashfs)) {
        /* programmed nodes: must obey cluster SSL mode
         * unprogrammed nodes: can use SSL instead of non-SSL,
         *  it is the cluster's responsibility to initiate programming via SSL,
         *  as the unprogrammed node would accept both         *
         * */
        WARN("hashfs use-ssl: %d, https: %d, is_bare: %d",
              sx_hashfs_uses_secure_proto(hashfs), is_https(),
              sx_storage_is_bare(hashfs));
	quit_errmsg(403, sx_hashfs_uses_secure_proto(hashfs) ? "Cluster operations require SECURE mode" : "Cluster operations require INSECURE mode");
    }

    int dc = sx_hashfs_distcheck(hashfs);
    if(dc < 0) {
	CRIT("Failed to reload distribution");
	/* MODHDIST: should die here */
    }

    if(!volume)
	cluster_ops();
    else if(!path)
	volume_ops();
    else
	file_ops();

    if(authed == AUTH_BODYCHECKING)
	WARN("FIXME: Security fail");

    HMAC_CTX_cleanup(&hmac_ctx);
    EVP_MD_CTX_cleanup(&body_ctx);
}
Ejemplo n.º 25
0
static __inline__ clash_action get_slots(Stream_t *Dir,
					 dos_name_t *dosname,
					 char *longname,
					 struct scan_state *ssp,
					 ClashHandling_t *ch)
{
	int error;
	clash_action ret;
	int match_pos=0;
	direntry_t entry;
	int isprimary;
	int no_overwrite;
	int reason;
	int pessimisticShortRename;
	doscp_t *cp = GET_DOSCONVERT(Dir);

	pessimisticShortRename = (ch->action[0] == NAMEMATCH_AUTORENAME);

	entry.Dir = Dir;
	no_overwrite = 1;
	if((is_reserved(longname,1)) ||
	   longname[strspn(longname,". ")] == '\0'){
		reason = RESERVED;
		isprimary = 1;
	} else if(contains_illegals(longname,long_illegals,1024)) {
		reason = ILLEGALS;
		isprimary = 1;
	} else if(is_reserved(dosname->base,0)) {
		reason = RESERVED;
		ch->use_longname = 1;
		isprimary = 0;
	} else if(contains_illegals(dosname->base,short_illegals,11)) {
		reason = ILLEGALS;
		ch->use_longname = 1;
		isprimary = 0;
	} else {
		reason = EXISTS;
		switch (lookupForInsert(Dir,
					&entry,
					dosname, longname, ssp,
					ch->ignore_entry,
					ch->source_entry,
					pessimisticShortRename &&
					ch->use_longname,
					ch->use_longname)) {
			case -1:
				return NAMEMATCH_ERROR;
				
			case 0:
				return NAMEMATCH_SKIP;
				/* Single-file error error or skip request */
				
			case 5:
				return NAMEMATCH_GREW;
				/* Grew directory, try again */
				
			case 6:
				return NAMEMATCH_SUCCESS; /* Success */
		}	
		match_pos = -2;
		if (ssp->longmatch > -1) {
			/* Primary Long Name Match */
#ifdef debug
			fprintf(stderr,
				"Got longmatch=%d for name %s.\n",
				longmatch, longname);
#endif			
			match_pos = ssp->longmatch;
			isprimary = 1;
		} else if ((ch->use_longname & 1) && (ssp->shortmatch != -1)) {
			/* Secondary Short Name Match */
#ifdef debug
			fprintf(stderr,
				"Got secondary short name match for name %s.\n",
				longname);
#endif

			match_pos = ssp->shortmatch;
			isprimary = 0;
		} else if (ssp->shortmatch >= 0) {
			/* Primary Short Name Match */
#ifdef debug
			fprintf(stderr,
				"Got primary short name match for name %s.\n",
				longname);
#endif
			match_pos = ssp->shortmatch;
			isprimary = 1;
		} else
			return NAMEMATCH_RENAME;

		if(match_pos > -1) {
			entry.entry = match_pos;
			dir_read(&entry, &error);
			if (error)
			    return NAMEMATCH_ERROR;
			/* if we can't overwrite, don't propose it */
			no_overwrite = (match_pos == ch->source || IS_DIR(&entry));
		}
	}
	ret = process_namematch(cp, dosname, longname,
				isprimary, ch, no_overwrite, reason);
	
	if (ret == NAMEMATCH_OVERWRITE && match_pos > -1){
		if((entry.dir.attr & 0x5) &&
		   (ask_confirmation("file is read only, overwrite anyway (y/n) ? ")))
			return NAMEMATCH_RENAME;
		/* Free up the file to be overwritten */
		if(fatFreeWithDirentry(&entry))
			return NAMEMATCH_ERROR;
		
#if 0
		if(isprimary &&
		   match_pos - ssp->match_free + 1 >= ssp->size_needed){
			/* reuse old entry and old short name for overwrite */
			ssp->free_start = match_pos - ssp->size_needed + 1;
			ssp->free_size = ssp->size_needed;
			ssp->slot = match_pos;
			ssp->got_slots = 1;
			strncpy(dosname, dir.name, 3);
			strncpy(dosname + 8, dir.ext, 3);
			return ret;
		} else
#endif
			{
			wipeEntry(&entry);
			return NAMEMATCH_RENAME;
		}
	}

	return ret;
}
Ejemplo n.º 26
0
static int ftp_init_transfer(void)
{
  if (!ftp_connected())
    return -1;

  if (!sock_dup(ftp->ctrl, &ftp->data))
    return -1;

  if (ftp_is_passive())
  {
    ftp_trace("Initializing passive connection.\n");

    struct sockaddr_storage sa;
    memcpy(&sa, sock_remote_addr(ftp->ctrl), sizeof(struct sockaddr_storage));

    unsigned char pac[6] = { 0 };
    unsigned short ipv6_port = { 0 };
    if (!ftp_pasv(sa.ss_family != AF_INET, pac, &ipv6_port))
    {
      ftp_trace("PASV/EPSV failed.\n");
      sock_destroy(ftp->data);
      ftp->data = NULL;
      return -1;
    }

    socklen_t len = sizeof(struct sockaddr_in);
    if (sa.ss_family == AF_INET)
    {
      memcpy(&((struct sockaddr_in*)&sa)->sin_addr, pac, (size_t)4);
      memcpy(&((struct sockaddr_in*)&sa)->sin_port, pac+4, (size_t)2);
    }
#ifdef HAVE_IPV6
    else if (sa.ss_family == AF_INET6)
    {
      ((struct sockaddr_in6*)&sa)->sin6_port = htons(ipv6_port);
      len = sizeof(struct sockaddr_in6);
    }
#endif
    else
    {
      ftp_trace("Do not know how to handle family %d.\n", sa.ss_family);
      sock_destroy(ftp->data);
      ftp->data = NULL;
      return -1;
    }

    struct sockaddr_storage tmp;
    memcpy(&tmp, sock_remote_addr(ftp->ctrl), sizeof(struct sockaddr_storage));
    if (is_reserved((struct sockaddr*) &sa) ||
         is_multicast((struct sockaddr*) &sa)  ||
         (is_private((struct sockaddr*) &sa) != is_private((struct sockaddr*) &tmp)) ||
         (is_loopback((struct sockaddr*) &sa) != is_loopback((struct sockaddr*) &tmp)))
    {
      // Invalid address returned by PASV. Replace with address from control
      // socket.
      ftp_err(_("Address returned by PASV seems to be incorrect.\n"));
      ((struct sockaddr_in*)&sa)->sin_addr = ((struct sockaddr_in*)&tmp)->sin_addr;
    }

    if (!sock_connect_addr(ftp->data, (struct sockaddr*) &sa, len))
    {
      ftp_trace("Could not connect to address from PASV/EPSV.\n");
      perror("connect()");
      sock_destroy(ftp->data);
      ftp->data = NULL;
      return -1;
    }
  } else {
    ftp_trace("Initializing active connection.\n");

    const struct sockaddr* local = sock_local_addr(ftp->data);
    sock_listen(ftp->data, local->sa_family);

    if (local->sa_family == AF_INET)
    {
      struct sockaddr_in* tmp = (struct sockaddr_in*)local;
      unsigned char* a = (unsigned char *)&tmp->sin_addr;
      unsigned char* p = (unsigned char *)&tmp->sin_port;

      ftp_set_tmp_verbosity(vbError);
      ftp_cmd("PORT %d,%d,%d,%d,%d,%d",
          a[0], a[1], a[2], a[3], p[0], p[1]);
    }
#ifdef HAVE_IPV6
    else if (local->sa_family == AF_INET6)
    {
      char* addr = printable_address(local);

      ftp_set_tmp_verbosity(vbError);
      ftp_cmd("EPRT |2|%s|%u|", addr, ntohs(((struct sockaddr_in6*)local)->sin6_port));
      free(addr);
    }
#endif
    else
    {
      ftp_trace("Do not know how to handle family %d.\n", local->sa_family);
      sock_destroy(ftp->data);
      ftp->data = NULL;
      return -1;
    }

    if(ftp->code != ctComplete)
    {
      ftp_trace("PORT/EPRT not successful\n");
      sock_destroy(ftp->data);
      ftp->data = NULL;
      return -1;
    }
  }

  sock_throughput(ftp->data);
  return 0;
}
Ejemplo n.º 27
0
static void
doit (void)
{
    u_char buf[BUFSIZ];
    u_char *p;
    struct sockaddr_storage thisaddr_ss;
    struct sockaddr *thisaddr = (struct sockaddr *)&thisaddr_ss;
    struct sockaddr_storage thataddr_ss;
    struct sockaddr *thataddr = (struct sockaddr *)&thataddr_ss;
    struct sockaddr_storage erraddr_ss;
    struct sockaddr *erraddr = (struct sockaddr *)&erraddr_ss;
    socklen_t thisaddr_len, thataddr_len;
    int port;
    int errsock = -1;
    char *client_user = NULL, *server_user = NULL, *cmd = NULL;
    struct passwd *pwd;
    int s = STDIN_FILENO;
    char **env;
    int ret;
    char that_host[NI_MAXHOST];

    thisaddr_len = sizeof(thisaddr_ss);
    if (getsockname (s, thisaddr, &thisaddr_len) < 0)
	syslog_and_die("getsockname: %s", strerror(errno));
    thataddr_len = sizeof(thataddr_ss);
    if (getpeername (s, thataddr, &thataddr_len) < 0)
	syslog_and_die ("getpeername: %s", strerror(errno));

    /* check for V4MAPPED addresses? */

    if (do_kerberos == 0 && !is_reserved(socket_get_port(thataddr)))
	fatal(s, NULL, "Permission denied.");

    p = buf;
    port = 0;
    for(;;) {
	if (net_read (s, p, 1) != 1)
	    syslog_and_die ("reading port number: %s", strerror(errno));
	if (*p == '\0')
	    break;
	else if (isdigit(*p))
	    port = port * 10 + *p - '0';
	else
	    syslog_and_die ("non-digit in port number: %c", *p);
    }

    if (do_kerberos  == 0 && !is_reserved(htons(port)))
	fatal(s, NULL, "Permission denied.");

    if (port) {
	int priv_port = IPPORT_RESERVED - 1;

	/*
	 * There's no reason to require a ``privileged'' port number
	 * here, but for some reason the brain dead rsh clients
	 * do... :-(
	 */

	erraddr->sa_family = thataddr->sa_family;
	socket_set_address_and_port (erraddr,
				     socket_get_address (thataddr),
				     htons(port));

	/*
	 * we only do reserved port for IPv4
	 */

	if (erraddr->sa_family == AF_INET)
	    errsock = rresvport (&priv_port);
	else
	    errsock = socket (erraddr->sa_family, SOCK_STREAM, 0);
	if (errsock < 0)
	    syslog_and_die ("socket: %s", strerror(errno));
	if (connect (errsock,
		     erraddr,
		     socket_sockaddr_size (erraddr)) < 0) {
	    syslog (LOG_WARNING, "connect: %s", strerror(errno));
	    close (errsock);
	}
    }

    if(do_kerberos) {
	if (net_read (s, buf, 4) != 4)
	    syslog_and_die ("reading auth info: %s", strerror(errno));

#ifdef KRB5
	    if((do_kerberos & DO_KRB5) &&
	       recv_krb5_auth (s, buf, thisaddr, thataddr,
			       &client_user,
			       &server_user,
			       &cmd) == 0)
		auth_method = AUTH_KRB5;
	    else
#endif /* KRB5 */
		syslog_and_die ("unrecognized auth protocol: %x %x %x %x",
				buf[0], buf[1], buf[2], buf[3]);
    } else {
	if(recv_bsd_auth (s, buf,
			  (struct sockaddr_in *)thisaddr,
			  (struct sockaddr_in *)thataddr,
			  &client_user,
			  &server_user,
			  &cmd) == 0) {
	    auth_method = AUTH_BROKEN;
	    if(do_vacuous) {
		printf("Remote host requires Kerberos authentication\n");
		exit(0);
	    }
	} else
	    syslog_and_die("recv_bsd_auth failed");
    }

    if (client_user == NULL || server_user == NULL || cmd == NULL)
	syslog_and_die("mising client/server/cmd");

    pwd = getpwnam (server_user);
    if (pwd == NULL)
	fatal (s, NULL, "Login incorrect.");

    if (*pwd->pw_shell == '\0')
	pwd->pw_shell = _PATH_BSHELL;

    if (pwd->pw_uid != 0 && access (_PATH_NOLOGIN, F_OK) == 0)
	fatal (s, NULL, "Login disabled.");


    ret = getnameinfo_verified (thataddr, thataddr_len,
				that_host, sizeof(that_host),
				NULL, 0, 0);
    if (ret)
	fatal (s, NULL, "getnameinfo: %s", gai_strerror(ret));

    if (login_access(pwd, that_host) == 0) {
	syslog(LOG_NOTICE, "Kerberos rsh denied to %s from %s",
	       server_user, that_host);
	fatal(s, NULL, "Permission denied.");
    }

#ifdef HAVE_GETSPNAM
    {
	struct spwd *sp;
	long    today;

	sp = getspnam(server_user);
	if (sp != NULL) {
	    today = time(0)/(24L * 60 * 60);
	    if (sp->sp_expire > 0)
		if (today > sp->sp_expire)
		    fatal(s, NULL, "Account has expired.");
	}
    }
#endif


#ifdef HAVE_SETLOGIN
    if (setlogin(pwd->pw_name) < 0)
	syslog(LOG_ERR, "setlogin() failed: %s", strerror(errno));
#endif

#ifdef HAVE_SETPCRED
    if (setpcred (pwd->pw_name, NULL) == -1)
	syslog(LOG_ERR, "setpcred() failure: %s", strerror(errno));
#endif /* HAVE_SETPCRED */

    /* Apply limits if not root */
    if(pwd->pw_uid != 0) {
	 const char *file = _PATH_LIMITS_CONF;
	 read_limits_conf(file, pwd);
    }

    if (initgroups (pwd->pw_name, pwd->pw_gid) < 0)
	fatal (s, "initgroups", "Login incorrect.");

    if (setgid(pwd->pw_gid) < 0)
	fatal (s, "setgid", "Login incorrect.");

    if (setuid (pwd->pw_uid) < 0)
	fatal (s, "setuid", "Login incorrect.");

    if (chdir (pwd->pw_dir) < 0)
	fatal (s, "chdir", "Remote directory.");

    if (errsock >= 0) {
	if (dup2 (errsock, STDERR_FILENO) < 0)
	    fatal (s, "dup2", "Cannot dup stderr.");
	close (errsock);
    } else {
	if (dup2 (STDOUT_FILENO, STDERR_FILENO) < 0)
	    fatal (s, "dup2", "Cannot dup stderr.");
    }

#ifdef KRB5
    {
	int fd;

	if (!do_unique_tkfile)
	    snprintf(tkfile,sizeof(tkfile),"FILE:/tmp/krb5cc_%lu",
		     (unsigned long)pwd->pw_uid);
	else if (*tkfile=='\0') {
	    snprintf(tkfile,sizeof(tkfile),"FILE:/tmp/krb5cc_XXXXXX");
	    fd = mkstemp(tkfile+5);
	    close(fd);
	    unlink(tkfile+5);
	}

	if (kerberos_status)
	    krb5_start_session();
    }
#endif

    setup_environment (&env, pwd);

    if (do_encrypt) {
	setup_copier (errsock >= 0);
    } else {
	if (net_write (s, "", 1) != 1)
	    fatal (s, "net_write", "write failed");
    }

#if defined(KRB5)
    if(k_hasafs()) {
	char cell[64];

	if(do_newpag)
	    k_setpag();

	/* XXX */
       if (kerberos_status) {
	   krb5_ccache ccache;
	   krb5_error_code status;

	   status = krb5_cc_resolve (context, tkfile, &ccache);
	   if (!status) {
	       if (k_afs_cell_of_file (pwd->pw_dir, cell, sizeof(cell)) == 0)
		   krb5_afslog_uid_home(context, ccache, cell, NULL,
					pwd->pw_uid, pwd->pw_dir);
	       krb5_afslog_uid_home(context, ccache, NULL, NULL,
				    pwd->pw_uid, pwd->pw_dir);
	       krb5_cc_close (context, ccache);
	   }
       }
    }
#endif /* KRB5 */
    execle (pwd->pw_shell, pwd->pw_shell, "-c", cmd, NULL, env);
    err(1, "exec %s", pwd->pw_shell);
}
Ejemplo n.º 28
0
extern codes_ty lexi(void)
{
   int             unary_delim = false; /* this is set to 1 if the current token
                                         * forces a following operator to be unary */
   static codes_ty last_code = code_eof; /* the last token type returned */
   static int      l_struct  = 0;        /* set to 1 if the last token was 'struct' */
   static int      l_enum    = 0;        /* set to 1 if the last token was `enum' */
   codes_ty        code;                 /* internal code to be returned */
   char            qchar;                /* the delimiter character for a string */

   static int      count = 0;            /* debugging counter */

   count++;

  /* tell world that this token started in column 1 iff the last
   * thing scanned was nl */
    
   parser_state_tos->col_1       = parser_state_tos->last_nl;
   parser_state_tos->last_saw_nl = parser_state_tos->last_nl;
   parser_state_tos->last_nl     = false;

   if (buf_ptr >= buf_end)
   {
      fill_buffer();
   }

   if (*buf_ptr == ' ' || *buf_ptr == TAB)
   {
      parser_state_tos->col_1 = false;

      skip_buffered_space(); /* adjusts buf_ptr */
   }

  /* INCREDIBLY IMPORTANT WARNING!!!
   *
   * Note that subsequent calls to `fill_buffer ()' may switch `buf_ptr'
   * to a different buffer.  Thus when `token_end' gets set later, it
   * may be pointing into a different buffer than `token'. */
    
   token = buf_ptr;

  /* Scan an alphanumeric token */
    
   if ((!((buf_ptr[0] == 'L') && 
         ((buf_ptr[1] == '"') || (buf_ptr[1] == '\''))) && /* Not a wide string */
        !(settings.gettext_strings && (buf_ptr[0] == '_') && 
          (buf_ptr[1] == '(') && (buf_ptr[2] == '"')) &&   /* Not a gettext string */
        !(settings.gettext_strings && (buf_ptr[0] == 'N') && 
          (buf_ptr[1] == '_') && (buf_ptr[2] == '(') &&
          (buf_ptr[3] == '"')) &&                          /* Not a gettext noop string */
        (chartype[0xff & (int) *buf_ptr] == alphanum)) ||
       ((buf_ptr[0] == '.') && isdigit (buf_ptr[1])))
   {
     /* we have a character or number */
      templ_ty *p;

     /* Because the influence of a return on indenting (different from standard
      * identifiers) extends only to permitting a cast just after it, the next
      * string or number found after the return should remove its influence to 
      * prevent mistaken identification of casts later on.
      */
      if (parser_state_tos->last_rw == rw_return)
          parser_state_tos->last_rw = rw_none;

      if (isdigit (*buf_ptr) ||
          ((buf_ptr[0] == '.') && isdigit (buf_ptr[1])))
      {
         int seendot = 0, seenexp = 0;

         if ((*buf_ptr == '0') && ((buf_ptr[1] == 'x') || (buf_ptr[1] == 'X')))
         {
            buf_ptr += 2;
            while (isxdigit (*buf_ptr))
            {
               buf_ptr++;
            }
         }
         else
         {
            while (1)
            {
               if (*buf_ptr == '.')
               {
                  if (seendot)
                  {
                     break;
                  }
                  else
                  {
                     seendot++;
                  }
               }

               buf_ptr++;
                    
               if (!isdigit (*buf_ptr) && *buf_ptr != '.')
               {
                  if ((*buf_ptr != 'E' && *buf_ptr != 'e') || seenexp)
                  {
                     break;
                  }
                  else
                  {
                     seenexp++;
                     seendot++;
                     buf_ptr++;

                     if (*buf_ptr == '+' || *buf_ptr == '-')
                     {
                        buf_ptr++;
                     }
                  }
               }
            }
         }

         if (*buf_ptr == 'F' || *buf_ptr == 'f' || *buf_ptr == 'i' || *buf_ptr == 'j')
         {
            buf_ptr++;
         }
         else if (*buf_ptr == 'D' || *buf_ptr == 'd')
         {
           if (buf_ptr[1] == 'F' || buf_ptr[1] == 'f' ||
               buf_ptr[1] == 'D' || buf_ptr[1] == 'd' ||
               buf_ptr[1] == 'L' || buf_ptr[1] == 'l')
           {
             buf_ptr+=2;
           }
         }
         else
         {
            while (*buf_ptr == 'U' || *buf_ptr == 'u' || *buf_ptr == 'L' || *buf_ptr == 'l')
            {
               buf_ptr++;
            }
         }
      }
      else
      while (chartype[0xff & (int) *buf_ptr] == alphanum)
      {                 /* copy it over */
         buf_ptr++;

         if (buf_ptr >= buf_end)
         {
            fill_buffer();
         }
      }

      token_end = buf_ptr;

      if (token_end - token == 13 && !strncmp (token, "__attribute__", 13))
      {
         last_code = decl;
         parser_state_tos->last_u_d = true;
         return (attribute);
      }

      skip_buffered_space(); /* adjusts buf_ptr */

     /* Handle operator declarations. */

      if (token_end - token == 8 && !strncmp (token, "operator", 8))
      {
         while (chartype[0xff & (int) *buf_ptr] == opchar)
         {
            buf_ptr++;
                
            if (buf_ptr >= buf_end)
            {
               fill_buffer();
            }
         }

         token_end = buf_ptr;

         skip_buffered_space(); /* adjusts buf_ptr */
            
      }

      parser_state_tos->its_a_keyword = false;
      parser_state_tos->sizeof_keyword = false;

     /* if last token was 'struct', then this token should be treated
        as a declaration */
      if (l_struct)
      {
         l_struct = false;
         last_code = ident;
         parser_state_tos->last_u_d = true;
            
         if (parser_state_tos->last_token == cpp_operator)
         {
            return overloaded;
         }
         return (decl);
      }

     /* Operator after indentifier is binary */

      parser_state_tos->last_u_d = false;
      last_code = ident;

     /* Check whether the token is a reserved word.  Use perfect hashing... */
        
      if (settings.c_plus_plus)
      {
         p = is_reserved_cc (token, token_end - token);
      }
      else
      {
         p = is_reserved (token, token_end - token);
      }

      if ((p == NULL) && (user_specials != 0))
      {
         for (p = &user_specials[0]; p < &user_specials[0] + user_specials_idx; p++)
         {
            char *q = token;
            char *r = p->rwd;

           /* This string compare is a little nonstandard because token
            * ends at the character before token_end and p->rwd is
            * null-terminated.  */
                
            while (1)
            {
              /* If we have come to the end of both the keyword in
               * user_specials and the keyword in token they are equal.  */
                    
               if (q >= token_end && !*r)
               {
                  goto found_keyword;
               }

              /* If we have come to the end of just one, they are not
               * equal.  */
                    
               if (q >= token_end || !*r)
               {
                  break;
               }

              /* If the characters in corresponding characters are not
               * equal, the strings are not equal.  */
                    
               if (*q++ != *r++)
               {
                  break;
               }
            }
         }

        /* Didn't find anything in user_specials.  */

         p = NULL;
      }

found_keyword:

      if (p)
      {                 /* we have a keyword */
         codes_ty value;

         value = ident;
         parser_state_tos->its_a_keyword = true;
         parser_state_tos->last_u_d      = true;
         parser_state_tos->last_rw       = p->rwcode;
         parser_state_tos->last_rw_depth = parser_state_tos->paren_depth;
            
         switch (p->rwcode)
         {
         case rw_operator:      /* C++ operator overloading. */
            value = cpp_operator;
            parser_state_tos->in_parameter_declaration = 1;
            break;
         case rw_switch:        /* it is a switch */
            value = (swstmt);
            break;
         case rw_case:          /* a case or default */
            value = (casestmt);
            break;
         case rw_enum:
            l_enum = true;      /* reset on '(' ')' '{' '}' or ';' */
           /* fall through */
         case rw_struct_like:   /* a "struct" */
            if (parser_state_tos->p_l_follow && 
                !(parser_state_tos->noncast_mask & 1 << parser_state_tos->p_l_follow))
           /* inside parens: cast */
            {
               parser_state_tos->cast_mask |= 1 << parser_state_tos->p_l_follow;
               break;
            }

            l_struct = true;

           /* Next time around, we will want to know that we have had a
              'struct' */
         case rw_decl:          /* one of the declaration keywords */
            if (parser_state_tos->p_l_follow && 
                !(parser_state_tos->noncast_mask & 1 << parser_state_tos->p_l_follow))
           /* inside parens: cast */
            {
               parser_state_tos->cast_mask |= 1 << parser_state_tos->p_l_follow;
               break;
            }
                    
            last_code = decl;
            value = (decl);
            break;

         case rw_sp_paren:      /* if, while, for */
            value = (sp_paren);
            if (*token == 'i' && parser_state_tos->last_token == sp_else)
            {
               parser_state_tos->i_l_follow -= settings.ind_size;
            }
                    
            break;

         case rw_sp_nparen:     /* do */
            value = (sp_nparen);
            break;

         case rw_sp_else:       /* else */
            value = (sp_else);
            break;

         case rw_sizeof:
            parser_state_tos->sizeof_keyword = true;
            value = (ident);
            break;

         case rw_return:
         case rw_break:
         default:               /* all others are treated like any other
                                   identifier */
            value = (ident);
         }                      /* end of switch */

         if (parser_state_tos->last_token == cpp_operator)
         {
            return overloaded;
         }
            
         return value;
      }                         /* end of if (found_it) */
      else if ((*buf_ptr == '(') && (parser_state_tos->tos <= 1) &&
               (parser_state_tos->ind_level == 0) &&
               (parser_state_tos->paren_depth == 0))
      {
        /* We have found something which might be the name in a function
         * definition.  */
            
         char *tp;
         int paren_count = 1;

        /* If the return type of this function definition was not defined
         * with a -T commandline option, then the output of indent would
         * alternate on subsequent calls.  In order to avoid that we try
         * to detect that case here and make a minimal change to cause
         * the correct behaviour.
         */
            
         if (parser_state_tos->last_token == ident && parser_state_tos->last_saw_nl)
         {
            parser_state_tos->in_decl = true;
         }

        /* Skip to the matching ')'.  */
            
         for (tp = buf_ptr + 1; (paren_count > 0) && (tp < in_prog + in_prog_size); tp++)
         {
            if (*tp == '(')
            {
               paren_count++;
            }
                
            if (*tp == ')')
            {
               paren_count--;
            }
                
           /* Can't occur in parameter list; this way we don't search the
            * whole file in the case of unbalanced parens.  */
                
            if (*tp == ';')
            {
               goto not_proc;
            }
         }

         if (paren_count == 0)
         {
            parser_state_tos->procname = token;
            parser_state_tos->procname_end = token_end;

            while (isspace (*tp))
            {
               tp++;
            }

            if ((*tp == '_') && (in_prog + in_prog_size - tp >= 13) &&
                !strncmp (tp, "__attribute__", 13))
            {
              /* Found an __attribute__ after a function declaration */
              /* Must be a declaration */
            }
            else
            {
              /* If the next char is ';' or ',' or '(' we have a function
               * declaration, not a definition.
               *
               * I've added '=' to this list to keep from breaking
               * a non-valid C macro from libc.  -jla */
                    
               if (*tp != ';' && *tp != ',' && *tp != '(' && *tp != '=')
               {
                  parser_state_tos->in_parameter_declaration = 1;
               }
            }
         }
      }
      else if ((*buf_ptr == ':') && (*(buf_ptr + 1) == ':') &&
               (parser_state_tos->tos <= 1) &&
               (parser_state_tos->ind_level == 0) &&
               (parser_state_tos->paren_depth == 0))
      {
         parser_state_tos->classname = token;
         parser_state_tos->classname_end = token_end;
      }
        
     /* The following hack attempts to guess whether or not the
      * current token is in fact a declaration keyword -- one that
      * has been typedef'd */
        
      else if ( ( ((*buf_ptr == '*') && (buf_ptr[1] != '=')) ||
                  isalpha (*buf_ptr) || (*buf_ptr == '_')) &&
                !parser_state_tos->p_l_follow && !parser_state_tos->block_init &&
                ( (parser_state_tos->last_token == rparen)    ||
                  (parser_state_tos->last_token == semicolon) ||
                  (parser_state_tos->last_token == rbrace)    ||
                  (parser_state_tos->last_token == decl)      ||
                  (parser_state_tos->last_token == lbrace)    ||
                  (parser_state_tos->last_token == start_token)))
      {
         parser_state_tos->its_a_keyword = true;
         parser_state_tos->last_u_d = true;
         last_code = decl;
            
         if (parser_state_tos->last_token == cpp_operator)
         {
            return overloaded;
         }

         return decl;
      }
      else
      {
        /* what ? */
      }

/* Escape from loop checking for procedure name in if statement above. */
not_proc:

      if (last_code == decl)
      {
        /* if this is a declared variable, then
           following sign is unary */
         parser_state_tos->last_u_d = true;     /* will make "int a -1" work */
      }
        
      last_code = ident;
        
      if (parser_state_tos->last_token == cpp_operator)
      {
         return overloaded;
      }

      return (ident);                /* the ident is not in the list */
   }                                /* end of procesing for alpanum character */

  /* Scan a non-alphanumeric token */

  /* If it is not a one character token, token_end will get changed later.  */

   token_end = buf_ptr + 1;

  /* THIS MAY KILL YOU!!!
   *
   * Note that it may be possible for this to kill us--if `fill_buffer'
   * at any time switches `buf_ptr' to the other input buffer, `token'
   * and `token_end' will point to different storage areas!!! */
    
   if (++buf_ptr >= buf_end)
   {
      fill_buffer();
   }

  /* If it is a backslash new-line, just eat the backslash */

   if ((*token == '\\') && (buf_ptr[0] == EOL))
   {
      token = buf_ptr;
        
      if (++buf_ptr >= buf_end)
      {
         fill_buffer();
      }
   }

   switch (*token)
   {
   case '\0':
      code = code_eof;
      break;

   case EOL:
      parser_state_tos->matching_brace_on_same_line = -1;
      unary_delim = parser_state_tos->last_u_d;
      parser_state_tos->last_nl = true;
      code = newline;
      break;

   /* Handle gettext strings. */
   case '_':
      if (!settings.gettext_strings || 
          buf_ptr[0] != '(' || 
          buf_ptr[1] != '"')
      {
         token_end = buf_ptr;
         code = ident;
         break;
      }

      qchar = buf_ptr[1];
      buf_ptr++;
      buf_ptr++;
      goto handle_string;

   /* Handle gettext noop strings. */
   case 'N':
      if (!settings.gettext_strings || 
          buf_ptr[0] != '_' || 
          buf_ptr[1] != '(' || 
          buf_ptr[2] != '"')
      {
         token_end = buf_ptr;
         code = ident;
         break;
      }

      qchar = buf_ptr[2];
      buf_ptr++;
      buf_ptr++;
      buf_ptr++;
      goto handle_string;

     /* Handle wide strings and chars. */
   case 'L':
      if (buf_ptr[0] != '"' && buf_ptr[0] != '\'')
      {
         token_end = buf_ptr;
         code = ident;
         break;
      }

      qchar = buf_ptr[0];
      buf_ptr++;
      goto handle_string;

   case '\'':                   /* start of quoted character */
   case '"':                    /* start of string */
      qchar = *token;

   handle_string:
     /* Find out how big the literal is so we can set token_end.  */

     /* Invariant:  before loop test buf_ptr points to the next
      * character that we have not yet checked. */
            
      while ((*buf_ptr != qchar) && (*buf_ptr != 0)) /* && *buf_ptr != EOL) */
      {
         if (*buf_ptr == EOL)
         {
            ++line_no;
         }
                    
         if (*buf_ptr == '\\')
         {
            buf_ptr++;
                    
            if (buf_ptr >= buf_end)
            {
               fill_buffer();
            }
                    
            if (*buf_ptr == EOL)
            {
               ++line_no;
            }
                    
            if (*buf_ptr == 0)
            {
               break;
            }
         }

         buf_ptr++;
                
         if (buf_ptr >= buf_end)
         {
            fill_buffer();
         }
      }

      if (*buf_ptr == EOL || *buf_ptr == 0)
      {
         WARNING ((qchar == '\'' ? _("Unterminated character constant") :
                   _("Unterminated string constant")), 0, 0);
      }
      else
      {
        /* Advance over end quote char.  */
         buf_ptr++;
                
         if (buf_ptr >= buf_end)
         {
            fill_buffer();
         }
      }

      if (settings.gettext_strings && 
          (token[0] == '_' || (token[0] == 'N' && token[1] == '_')))
      {
        /* In the gettext situation, the string ends with ") */
        if (*buf_ptr != ')')
        {
           WARNING (_("Unterminated string constant"), 0, 0);
        }
        else
        {
          /* Advance over closing paren.  */
           buf_ptr++;
                
           if (buf_ptr >= buf_end)
           {
              fill_buffer();
           }
        }
      }

      token_end = buf_ptr;
      code = ident;
      break;

   case '(':
       l_enum = false;
       unary_delim = true;
       code = lparen;
       break;

   case '[':
       if (parser_state_tos->in_or_st)
       {
           parser_state_tos->in_or_st++;
       }
            
       unary_delim = true;
       code = lparen;
       break;

   case ')':
       l_enum = false;
       code = rparen;
       break;

   case ']':
       if (parser_state_tos->in_or_st > 1)
       {
           parser_state_tos->in_or_st--;
       }
            
       code = rparen;
       break;

   case '#':
      unary_delim = parser_state_tos->last_u_d;
      code = preesc;

     /* Make spaces between '#' and the directive be part of
      * the token if user specified "-lps" */
      while (*buf_ptr == ' ' && buf_ptr < buf_end)
      {
          buf_ptr++;
      }
                
      if (settings.leave_preproc_space)
      {
         token_end = buf_ptr;
      }
      break;

   case '?':
      unary_delim = true;
      code = question;
      break;

   case ':':
      /* Deal with C++ class::method */
       
       if (*buf_ptr == ':')
       {
           code = doublecolon;
           buf_ptr++;
           token_end = buf_ptr;
           break;
       }
       
       code = colon;
       unary_delim = true;
       if (squest && *e_com != ' ')
       {
           if (e_code == s_code)
           {
               parser_state_tos->want_blank = false;
           }
           
           else
           {
               parser_state_tos->want_blank = true;
           }
       }
       break;
       
   case ';':
       l_enum = false;
       unary_delim = true;
       code = semicolon;
       break;
       
   case '{':
       if (parser_state_tos->matching_brace_on_same_line < 0)
       {
           parser_state_tos->matching_brace_on_same_line = 1;
       }
       else
       {
           parser_state_tos->matching_brace_on_same_line++;
       }
       
       if (l_enum)
       {
          /* Keep all variables in the same column:
           *   ONE,
           *   TWO, etc
           * instead of
           *   ONE,
           *     TWO,
           * Use a special code for `block_init' however, because we still
           * want to do the line breaks when `settings.braces_on_struct_decl_line'
           * is not set.
           */
           parser_state_tos->block_init = 2;
           parser_state_tos->block_init_level = 0;
           l_enum = false;
       }
            
       unary_delim = true;
       code = lbrace;
       break;

   case '}':
      parser_state_tos->matching_brace_on_same_line--;
      l_enum = false;
      unary_delim = true;
      code = rbrace;
      break;

   case 014:                    /* a form feed */
      unary_delim = parser_state_tos->last_u_d;
      parser_state_tos->last_nl = true; /* remember this so we can set
                                           'parser_state_tos->col_1' right */
      code = form_feed;
      break;

   case ',':
      unary_delim = true;
      code = comma;
      break;

   case '.':
      if ((buf_ptr[0] == '.') && 
          (buf_ptr[1] == '.'))
      {
         /* '...' */

          if ((buf_ptr += 2) >= buf_end)
          {
              fill_buffer();
          }

          unary_delim = true;
          token_end = buf_ptr;

          if (parser_state_tos->in_decl)
          {
             /* '...' in a declaration */
              code = decl;
          }
          else
          {
              code = binary_op;
          }
      }
      else
      {
          unary_delim = false;
          code = struct_delim;
          
          if (*buf_ptr == '*')  /* object .* pointer-to-member */
          {
              ++buf_ptr;
              token_end = buf_ptr;
          }
      }
      break;

   case '-':
   case '+':                    /* check for -, +, --, ++ */
      code = (parser_state_tos->last_u_d ? unary_op : binary_op);
      unary_delim = true;

      if (*buf_ptr == token[0])
      {
        /* check for doubled character */
         buf_ptr++;
        /* buffer overflow will be checked at end of loop */
         if (last_code == ident || last_code == rparen)
         {
            code = (parser_state_tos->last_u_d ? unary_op : postop);
           /* check for following ++ or -- */
            unary_delim = false;
         }
      }
      else if (*buf_ptr == '=')
      {
        /* check for operator += */
         buf_ptr++;
      }
      else if (*buf_ptr == '>')
      {
        /* check for operator -> */
         buf_ptr++;
         code = struct_delim;
        /* check for operator ->* */

         if (*buf_ptr == '*')
         {
            buf_ptr++;
         }
      }
      else
      {
        /* what ? */
      }

      token_end = buf_ptr;
      break;            /* buffer overflow will be checked at end of
                           switch */

   case '=':
      if (parser_state_tos->in_or_st && 
          (parser_state_tos->last_token != cpp_operator))
      {
         parser_state_tos->block_init = 1;
         parser_state_tos->block_init_level = 0;
      }

      if (*buf_ptr == '=')      /* == */
      {
         buf_ptr++;
      }
      else if ((*buf_ptr == '-') ||
               (*buf_ptr == '+') ||
               (*buf_ptr == '*') ||
               (*buf_ptr == '&'))
      {
        /* Something like x=-1, which can mean x -= 1 ("old style" in K&R1)
         * or x = -1 (ANSI).  Note that this is only an ambiguity if the
         * character can also be a unary operator.  If not, just produce
         * output code that produces a syntax error (the theory being that
         * people want to detect and eliminate old style assignments but
         * they don't want indent to silently change the meaning of their
         * code).  */
                
         WARNING (_("old style assignment ambiguity in \"=%c\".  Assuming \"= %c\"\n"),
                  (unsigned long) *((unsigned char *) buf_ptr), (unsigned long) *((unsigned char *) buf_ptr));
      }
      else
      {
        /* what ? */
      }

      code = binary_op;
      unary_delim = true;
      token_end = buf_ptr;
      break;
     /* can drop thru!!! */

   case '>':
   case '<':
   case '!':
     /* ops like <, <<, <=, !=, <<=, etc */
     /* This will of course scan sequences like "<=>", "!=>", "<<>", etc. as
      * one token, but I don't think that will cause any harm.  */
     /* in C++ mode also scan <?[=], >?[=] GNU C++ operators 
      * maybe some flag to them ? */
            
      while (*buf_ptr == '>' || *buf_ptr == '<' || *buf_ptr == '=' || (settings.c_plus_plus && *buf_ptr == '?'))
      {
         if (++buf_ptr >= buf_end)
         {
            fill_buffer();
         }
                
         if (*buf_ptr == '=')
         {
            if (++buf_ptr >= buf_end)
            {
               fill_buffer();
            }
         }
      }

      code = (parser_state_tos->last_u_d ? unary_op : binary_op);
      unary_delim = true;
      token_end = buf_ptr;
      break;

   default:
      if (token[0] == '/' && (*buf_ptr == '*' || *buf_ptr == '/'))
      {
        /* A C or C++ comment */

         if (*buf_ptr == '*')
         {
            code = comment;
         }
         else
         {
            code = cplus_comment;
         }

         if (++buf_ptr >= buf_end)
         {
            fill_buffer();
         }

         if (code == comment)
         {
           /* Threat comments of type / *UPPERCASE* / not as comments */
            char *p = buf_ptr;

            while (isupper (*p++))
            {
              /* There is always at least one
               * newline in the buffer; so no
               * need to check for buf_end. */
            }
                    
            if (p < buf_end && p[-1] == '*' && *p == '/')
            {
               buf_ptr = p + 1;
               code = ident;
               parser_state_tos->want_blank = true;
            }
         }
                
         unary_delim = parser_state_tos->last_u_d;
      }
      else if (parser_state_tos->last_token == cpp_operator)
      {
        /* For C++ overloaded operators. */
         code = overloaded;
         last_code = overloaded;
      }
      else
      {
         while (*(buf_ptr - 1) == *buf_ptr || *buf_ptr == '=')
         {
           /* handle ||, &&, etc, and also things as in int *****i */
            if (++buf_ptr >= buf_end)
            {
               fill_buffer();
            }
         }
         code = (parser_state_tos->last_u_d ? unary_op : binary_op);
         unary_delim = true;
      }

      token_end = buf_ptr;

   }                            /* end of switch */

   if (code != newline)
   {
      l_struct = false;
      last_code = code;
   }

   if (buf_ptr >= buf_end)
   {
      fill_buffer();
   }
    
   parser_state_tos->last_u_d = unary_delim;

   if (parser_state_tos->last_token == cpp_operator)
   {
      return overloaded;
   }
    
   return (code);
}
Ejemplo n.º 29
0
/*
 * Shared between the interface class declaration and the NS_DECL_IFOO macro
 * provided to aid declaration of implementation classes.  
 * mode...
 */
static gboolean
write_method_signature(IDL_tree method_tree, FILE *outfile, const char *className)
{
    struct _IDL_OP_DCL *op = &IDL_OP_DCL(method_tree);
    gboolean no_generated_args = TRUE;
    gboolean op_notxpcom =
        (IDL_tree_property_get(op->ident, "notxpcom") != NULL);
    const char *name;
    IDL_tree iter;

    if (op_notxpcom && !op->op_type_spec)
        fputs("procedure ", outfile);
    else
        fputs("function ", outfile);

    name = IDL_IDENT(op->ident).str;
    if( is_reserved(name) )
        fputc('_', outfile);
    fprintf(outfile, "%c%s(", toupper(*name), name + 1);

    for (iter = op->parameter_dcls; iter; iter = IDL_LIST(iter).next) {
        if (!write_param(IDL_LIST(iter).data, outfile))
            return FALSE;
        if ((IDL_LIST(iter).next ||
             (!op_notxpcom && op->op_type_spec) || op->f_varargs))
            fputs("; ", outfile);
        no_generated_args = FALSE;
    }

    /* make IDL return value into trailing out argument */
    if (op->op_type_spec && !op_notxpcom) {
        IDL_tree fake_param = IDL_param_dcl_new(IDL_PARAM_OUT,
                                                op->op_type_spec,
                                                IDL_ident_new("_retval"));
        if (!fake_param)
            return FALSE;
        if (!write_param(fake_param, outfile))
            return FALSE;
        if (op->f_varargs)
            fputs("; ", outfile);
        no_generated_args = FALSE;
    }

    /* varargs go last */
    if (op->f_varargs) {
        fputs("_varargs : PVarArgs", outfile);
        no_generated_args = FALSE;
    }

    fputc(')', outfile);

    if (op_notxpcom) {
        if (!interface_write_type(op->op_type_spec, FALSE, FALSE, FALSE, FALSE, NULL, outfile))
            return FALSE;
    } else {
        fputs(": nsresult", outfile);
    }
    fputs("; stdcall", outfile);

    return TRUE;
}