Esempio n. 1
0
File: dopdu.c Progetto: aeppert/pcp
static int
do_request(__pmPDU *pb)
{
    int		sts;
    int		type;

    if ((sts = __pmDecodeLogRequest(pb, &type)) < 0) {
	__pmNotifyErr(LOG_ERR, "do_request: error decoding PDU: %s\n", pmErrStr(sts));
	return PM_ERR_IPC;
    }

    switch (type) {
	case LOG_REQUEST_STATUS:
	    /*
	     * Don't need to check [access] as you have to have _some_
	     * permission (at least one of PM_OP_LOG_ADV or PM_OP_LOG_MAND
	     * and PM_OP_LOG_ENQ) to make a connection ... and if you
	     * have either PM_OP_LOG_ADV or PM_OP_LOG_MAND it makes no
	     * sense to deny LOG_REQUEST_STATUS operations.
	     * Also, this is needed internally by pmlc to discover pmcd's
	     * hostname.
	     */
	    sts = sendstatus();
	    break;

	case LOG_REQUEST_NEWVOLUME:
	    if (denyops & PM_OP_LOG_MAND)
		sts = __pmSendError(clientfd, FROM_ANON, PM_ERR_PERMISSION);
	    else {
		sts = newvolume(VOL_SW_PMLC);
		if (sts >= 0)
		    sts = logctl.l_label.ill_vol;
		sts = __pmSendError(clientfd, FROM_ANON, sts);
	    }
	    break;

	case LOG_REQUEST_SYNC:
	    /*
	     * Don't need to check access controls, as this is now
	     * a no-op with unbuffered I/O from pmlogger.
	     *
	     * Do nothing, simply send status 0 back to pmlc.
	     */
	    sts = __pmSendError(clientfd, FROM_ANON, 0);
	    break;

	/*
	 * QA support ... intended for error injection
	 * If the request is > QA_OFF then this is a code to enable
	 * a specific style of error behaviour.  If the request
	 * is QA_OFF, this disables the error behaviour.
	 *
	 * Supported behaviours.
	 * QA_SLEEPY
	 *	After this exchange with pmlc, sleep for 5 seconds
	 * 	after each incoming pmlc request ... allows testing
	 * 	of timeout logic in pmlc
	 */

	case QA_OFF:
	    if (denyops & PM_OP_LOG_MAND)
		sts = __pmSendError(clientfd, FROM_ANON, PM_ERR_PERMISSION);
	    else {
		qa_case = 0;
		sts = __pmSendError(clientfd, FROM_ANON, 0);
	    }
	    break;

	case QA_SLEEPY:
	    if (denyops & PM_OP_LOG_MAND)
		sts = __pmSendError(clientfd, FROM_ANON, PM_ERR_PERMISSION);
	    else {
		qa_case = type;
		sts = __pmSendError(clientfd, FROM_ANON, 0);
	    }
	    break;

	default:
	    fprintf(stderr, "do_request: bad request type %d\n", type);
	    sts = PM_ERR_IPC;
	    break;
    }
    return sts;
}
Esempio n. 2
0
int main(int argc, char **argv, char **envp)
{
    int c;
    char *file, *sp;
    struct charvbuf prog;
    int inpath, addfile, cd;
    int infd, outfd;
    FILE *in, *out;
    char **headers;
    pid_t child;
    int estat;
    
    environ = envp;
    signal(SIGPIPE, SIG_IGN);
    
    bufinit(prog);
    inpath = 0;
    addfile = 1;
    cd = 0;
    while((c = getopt(argc, argv, "cp:P:")) >= 0) {
	switch(c) {
	case 'c':
	    cd = 1;
	    break;
	case 'p':
	    bufadd(prog, optarg);
	    inpath = 1;
	    break;
	case 'P':
	    prog.d = 0;
	    bufadd(prog, optarg);
	    while(1) {
		if(optind >= argc) {
		    flog(LOG_ERR, "callcgi: unterminated argument list for -P");
		    exit(1);
		}
		if(!strcmp(argv[optind], ";")) {
		    optind++;
		    break;
		}
		bufadd(prog, argv[optind++]);
	    }
	    if(prog.d == 0) {
		flog(LOG_ERR, "callcgi: -P option needs at least a program name");
		exit(1);
	    }
	    inpath = 1;
	    addfile = 0;
	    break;
	default:
	    usage();
	    exit(1);
	}
    }
    
    if(argc - optind < 3) {
	usage();
	exit(1);
    }
    if(((file = getenv("REQ_X_ASH_FILE")) == NULL) && (prog.d == 0)) {
	flog(LOG_ERR, "callcgi: needs to be called with the X-Ash-File header");
	exit(1);
    }
    
    if(cd) {
	/* This behavior is encouraged by the CGI specification (RFC 3875, 7.2),
	 * but not strictly required, and I get the feeling it might break some
	 * relative paths here or there, so it's not the default for now. */
	if((sp = strrchr(file, '/')) != NULL) {
	    *sp = 0;
	    if(chdir(file)) {
		*sp = '/';
	    } else {
		file = sp + 1;
	    }
	}
    }
    
    if(prog.d == 0)
	bufadd(prog, file);
    if(addfile && (file != NULL))
	bufadd(prog, file);
    bufadd(prog, NULL);
    child = forkchild(inpath, prog.b, file, argv[optind], argv[optind + 1], argv[optind + 2], &infd, &outfd);
    in = fdopen(infd, "w");
    passdata(stdin, in);	/* Ignore errors, perhaps? */
    fclose(in);
    out = fdopen(outfd, "r");
    if((headers = parsecgiheaders(out)) == NULL) {
	flog(LOG_WARNING, "CGI handler returned invalid headers");
	exit(1);
    }
    sendstatus(headers, stdout);
    sendheaders(headers, stdout);
    printf("\n");
    if(passdata(out, stdout))
	kill(child, SIGINT);
    fclose(out);
    if(waitpid(child, &estat, 0) == child) {
	if(WCOREDUMP(estat))
	    flog(LOG_WARNING, "CGI handler `%s' dumped core", prog.b[0]);
	if(WIFEXITED(estat) && !WEXITSTATUS(estat))
	    return(0);
	else
	    return(1);
    }
    flog(LOG_WARNING, "could not wait for CGI handler: %s", strerror(errno));
    return(1);
}
Esempio n. 3
0
int getfileseg()
{
  struct pollfd fds[1];
  struct uftp_h *header;
  struct fileinfo *info;
  struct sockaddr_in sin;
  char buf[PACKETSIZE],*data;
  int i,done,wait,addr_len;
  long nak_count,last;
  off_t prev_offset,offset,ret_val;

  header=(struct uftp_h *)&(buf[0]);
  info=(struct fileinfo *)&(buf[sizeof(struct uftp_h)]);
  data=&(buf[sizeof(struct uftp_h)]);
  naklist=(char *)malloc(numblocks);
  for (i=0;i<numblocks;i++)
    naklist[i]=1;
  fds[0].fd=receiver;
  fds[0].events=POLLIN;
  done=0;
  wait=1;
  last=-1;
  prev_offset=0;
  timeout*=1000;
  lseek(file,0,SEEK_SET);
  while (!done) {
    if ((ret_val=poll(fds,1,timeout))==-1) {
      fprintf(stderr,"[%d]: ",getpid());
      perror("Poll failed");
      continue;
    }
    if (ret_val==0) {
      fprintf(stderr,"[%d]: Transfer timed out\n",getpid());
      abort_msg(receiver,&dest,txID,"Transfer timed out");
      free(naklist);
      if (unicast)
        return 0;
      else
        exit(1);
    }
    if (fds[0].revents & (POLLERR|POLLHUP|POLLNVAL)) {
      fprintf(stderr,"[%d]: poll error, revents = 0x%X\n",getpid(),fds[0].revents);
      continue;
    }
    if (fds[0].revents & POLLIN) {
      bzero(buf,sizeof(buf));
      addr_len=sizeof(sin);
      if (recvfrom(receiver,buf,sizeof(buf),0,(struct sockaddr *)&sin,&addr_len)!=PACKETSIZE) {
        fprintf(stderr,"[%d]: ",getpid());
        perror("Error receiving FILESEG");
        continue;
      }
    } else {
      fprintf(stderr,"[%d]: unknown poll return\n",getpid());
      continue;
    }
    head_ntoh(header);
    if (header->uftp_id!=UFTP_ID) { 
      fprintf(stderr,"[%d]: error receiving file: not uftp packet\n",getpid());
      continue;
    }
    if (header->tx_id!=txID) {
      if (unicast&&(header->func==ANNOUNCE)) {
        abort_msg(receiver,&sin,header->tx_id,"Currently receiving unicast file, can't receive others until complete");
        fprintf(stderr,"[%d]: Denied transfer from %08X, unicast in progress\n",getpid(),header->tx_id);
      } else {
        fprintf(stderr,"[%d]: Invalid txID: %08X, should be %08X\n",getpid(),header->tx_id,txID);
      }
      continue;
    }
    if (header->func==FILESEG) { 
      if (verbose>=2) {
        if (header->pass!=1)
          fprintf(stderr,"[%d]: Got packet %d\n",getpid(),header->seq_num);
      } else if (verbose==1) {
        if (header->seq_num!=last+1)
          fprintf(stderr,"[%d]: Got packet %d, last was %d\n",getpid(),header->seq_num,last);
        last=header->seq_num;
      }
      offset=(off_t)header->seq_num*BLOCKSIZE;
      if ((ret_val=lseek(file,offset-prev_offset,SEEK_CUR))==-1) {
        fprintf(stderr,"[%d]: ",getpid());
        perror("lseek failed for file");
      }
      if (ret_val!=offset) {
        if (sizeof(off_t)>4)
          fprintf(stderr,"[%d]: offset is %lld, should be %lld\n",getpid(),ret_val,offset);
        else
          fprintf(stderr,"[%d]: offset is %d, should be %d\n",getpid(),ret_val,offset);
        continue;
      }
      if ((header->blsize!=BLOCKSIZE)&&(header->seq_num!=numblocks-1)) {
        fprintf(stderr,"[%d]: Bad block size: %d\n",getpid(),header->blsize);
        continue;
      }
      if ((ret_val=write(file,data,header->blsize))==-1) {
        fprintf(stderr,"[%d]: Write failed for segment %d\n",getpid(),header->seq_num);
        continue;
      }
      prev_offset=offset+ret_val;
      if (ret_val!=header->blsize) {
        fprintf(stderr,"[%d]: Write failed for segment %d, only wrote %d bytes\n",getpid(),header->seq_num,ret_val);
        continue;
      }
      naklist[header->seq_num]=0;
    } else if (header->func==DONE) { 
      fprintf(stderr,"[%d]: Got DONE message for pass %d section %d\n",getpid(),header->pass,header->section_num);
      i=0;
      while (info->addr_list[i].s_addr!=0) {
        if (info->addr_list[i].s_addr==m_interface.s_addr) {
          if ((nak_count=sendstatus(header->pass,header->section_num,wait))==-2) {
            fprintf(stderr,"[%d]: Error sending NAKs",getpid());
            wait=1;
          } else if (nak_count==-3) {
            fprintf(stderr,"[%d]: Waiting for last packet in section...\n",getpid());
            wait=0;
          } else if (nak_count==-1) {
            fprintf(stderr,"[%d]: File transfer complete\n",getpid());
            done=1;
          } else {
            fprintf(stderr,"[%d]: Sent %d NAKs for pass %d section %d\n",getpid(),nak_count,header->pass,header->section_num);
          }
          break;
        }
        i++;
      }
    } else if (header->func==ABORT) { 
      fprintf(stderr,"[%d]: Error: Transfer aborted by server: %s\n",getpid(),data);
      free(naklist);
      if (unicast)
        return 0;
      else
        exit(1);
    } else if ((header->func==REG_CONF)||(header->func==DONE_CONF)) {
      if (info->addr_list[0].s_addr==m_interface.s_addr) {
        fprintf(stderr,"[%d]: Error receiving file: wrong func: %s\n",getpid(),strfunc(header->func));
      }
    } else {
      fprintf(stderr,"[%d]: Error receiving file: wrong func: %s\n",getpid(),strfunc(header->func));
    }
  }
  free(naklist);
  return 1;
}