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; }
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); }
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; }