void UserManagementAPI::handleUserResetPasswordPost(HttpRequest &request, HttpResponse &response) { QByteArray rawData = request.getRawData(); QJsonParseError error; QJsonDocument data = QJsonDocument::fromJson(rawData, &error); if (error.error != QJsonParseError::NoError) { respondJsonParseError(response, error); return; } QJsonObject dataObject = data.object(); //not checking if user is activated or not here might be ok. //because this api call has to be sent from the ui, as it needs recaptcha //and the ui checks if user is activated if (dataObject.contains("email") && dataObject.contains("password") && dataObject.contains("g_recaptcha_response")) { QString email = dataObject["email"].toString(); QByteArray password = dataObject["password"].toString().toLatin1(); QString g_recaptcha_response = dataObject["g_recaptcha_response"].toString(); if (!ReCAPTCHAVerifier::getSingleton().verify(g_recaptcha_response, request.getFromIPAddress())) { respond(response, StatusCode::reCAPTCHAFailed, "reCAPTCHA check failed!"); return; } if (dataObject.contains("reset_code")) { QByteArray reset_code = dataObject["reset_code"].toString().toLatin1(); QString errorMessage; if (!m_userManager.resetPassword(email, password, reset_code, false, errorMessage)) { respond(response, StatusCode::PasswordResetFailed, "Password reset failed: " % errorMessage); } } else if(dataObject.contains("old_password")) { QByteArray old_password = dataObject["old_password"].toString().toLatin1(); QString errorMessage; if (!m_userManager.resetPassword(email, password, old_password, true, errorMessage)) { respond(response, StatusCode::PasswordResetFailed, "Password reset failed: " % errorMessage); } } else { respondParameterMissing(response); } respondSuccess(response); } else { respondParameterMissing(response); } }
void follow_master(void) { object *objs; int i; int nMasterHere; nMasterHere = 0; objs = query_environment()->query_inventory(); for (i = 0; i < sizeof(objs); i++) { if (objs[i] == master) { nMasterHere = 1; } } if (nMasterHere == 0) { if (!master) { remove_call_out(nFollow); respond("say It seems " + master_name + " no longer has a need for me."); die(); destruct_object(this_object()); return; } if (query_environment() != master->query_environment()) { switch (random(10)) { case 0: query_environment()->tell_room(nil, my_name + " leaves."); break; case 1: query_environment()->tell_room(nil, my_name + " tries to follow his master."); break; case 2: query_environment()->tell_room(nil, my_name + " follows his master."); break; case 3: query_environment()->tell_room(nil, my_name + " disappears in a cloud of smoke."); break; case 4: query_environment()->tell_room(nil, my_name + " suddenly vanishes."); break; case 5: query_environment()->tell_room(nil, my_name + " fades out of view."); break; case 6: query_environment()->tell_room(nil, my_name + " runs off after his master."); break; case 7: query_environment()->tell_room(nil, my_name + " suddenly notices that his master has left, and runs off."); break; case 8: query_environment()->tell_room(nil, my_name + " fades into the shadows, and is gone."); break; case 9: query_environment()->tell_room(nil, my_name + " snaps his fingers, and is gone."); break; } move(master->query_environment()->base_name()); switch (random(10)) { case 0: query_environment()->tell_room(nil, my_name + " follows the light of his life."); break; case 1: query_environment()->tell_room(nil, my_name + " follows in his masters footsteps."); break; case 2: query_environment()->tell_room(nil, my_name + " appears next to his master in a cloud of smoke."); break; case 3: query_environment()->tell_room(nil, my_name + " enters."); break; case 4: query_environment()->tell_room(nil, my_name + " appears."); break; case 5: query_environment()->tell_room(nil, my_name + " arrives shortly after his master."); break; case 6: query_environment()->tell_room(nil, my_name + " comes running, tying to keep up with his master."); break; case 7: query_environment()->tell_room(nil, "A humble page enters."); break; case 8: query_environment()->tell_room(nil, "A humble person wearing a robe enters."); break; case 9: query_environment()->tell_room(nil, my_name + " catches up with his master."); break; } } } nFollow = call_out("follow_master", 2); }
void TabletServer::mainScreen(QTcpSocket *socket, const QStringList &path, const QStringMap &query) { Document * doc = mw->currentDocument(); if(!doc) { generic404(socket,path,query); return; } QStringList pathCopy = path; pathCopy.takeFirst(); // should be "tablet", but could be anything - /tablet/ is canonized for use in the tablet cache manifest for sfari QString control = pathCopy.isEmpty() ? "" : pathCopy.takeFirst().toLower(); //bool flag = pathCopy.isEmpty() ? 0 : pathCopy.takeFirst().toInt(); //qDebug() << "TabletServer::mainScreen(): control: "<<control; HttpUser *user = HttpUserUtil::instance()->currentUser(); if(control != "login") { if(!user) { QString from = QUrl::toPercentEncoding(toPathString(path,query).toAscii()).replace(" ", "+"); redirect(socket, "/tablet/login?from=" + from); return; } // I've decided to allow guests "view-only" access // else // if(user->level() == HttpUser::Guest) // { // Http_Send_Ok(socket) << "<html><head><title>Not Allowed</title></head><body><h1>Not Allowed</h1>Sorry, you're not allowed to access this site. (<a href='/tablet/login'>Login again</a>)</body></html"; // return; // } } if(control.isEmpty()) { SimpleTemplate tmpl("data/http/tablet.tmpl"); tmpl.param("user_name", user->user()); tmpl.param("user_level", (int)user->level()); tmpl.param("is_admin", user->level() == HttpUser::Admin); tmpl.param("is_user", user->level() == HttpUser::User); tmpl.param("is_guest", user->level() == HttpUser::Guest); // tmpl.param("list",outputGroupList); // // OutputControl * outputControl = mw->outputControl(liveId); // tmpl.param("black_toggled", outputControl->isBlackToggled()); // tmpl.param("clear_toggled", outputControl->isClearToggled()); // // SlideGroupViewControl *viewControl = mw->viewControl(liveId); // tmpl.param("qslide_toggled", viewControl->isQuickSlideToggled()); // // if(doc->filename().isEmpty()) // tmpl.param("docfile",tr("New File")); // else // tmpl.param("docfile",QFileInfo(doc->filename()).baseName()); // Http_Send_Ok(socket) << // "Content-Type: text/html\n\n" << // tmpl.toString(); QHttpResponseHeader header(QString("HTTP/1.0 200 OK")); header.setValue("Content-Type", "text/html"); respond(socket, header); QTextStream output(socket); output.setAutoDetectUnicode(true); output << tmpl.toString(); } else if(control == "login") { loginPage(socket, path, query, "/tablet/login"); } else if(control == "list") { QString filter = query["filter"]; // Can be empty // Don't allow non-admins to search because it would interfere with the main UI if(!filter.isEmpty() && user->level() < HttpUser::Admin) { Http_Send_500txt(socket, "Not Authorized"); return; } QString mode = query["mode"]; // Either "db" or "file" bool pollingFlag = query["poll"] == "true"; QString clientMD5 = query["md5"]; // the md5 of the list contents to use to check for changes if pollingFlag == true // Compile list of results matching mode (from db or from current sched) and the filter, and return as json string // TODO add button to search online //qDebug() << "TabletServer::mainScreen(): list: mode: "<<mode<<", filter: "<<filter; QVariantMap result; QVariantList resultList; bool moreResults = false; int listCutoffLimit = 10; // included in results even though only relevant to 'db' mode // Buffer for compiling MD5 hash QStringList md5sigList; if(mode == "db") { bool isChanged = true; if(pollingFlag) { int currentChangeSequence = m_songListModel->currentChangeSequence(); QString seqString = QString::number(currentChangeSequence); // md5sigList is used to generate the md5 to send back to the client md5sigList << seqString; QString seqMd5 = MD5::md5sum(md5sigList.join("")); isChanged = false; if(seqMd5 != clientMD5) isChanged = true; } // Only regen list if 'isChanged' - and isChanged is only set to 'false' if: // - Client is in polling mode // - Client MD5 matches the MD5 of current sequence number // We do this because generating the list makes a call to filter() // which can cause trouble if the filter string is empty and the user // in the DViz main UI is trying to search for something (which would NOT change // the sequence number above, but would change the filter) if(isChanged) { // List cutoff limit only relevant when searching/quering database. // Cutoff not honored or implemented for file schedule QString maxResults = query["max"]; if(!maxResults.isEmpty()) listCutoffLimit = maxResults.toInt(); if(listCutoffLimit < 1) listCutoffLimit = 1; m_songListModel->filter(filter); moreResults = m_songListModel->rowCount() > listCutoffLimit; int resultCount = qMin(listCutoffLimit, m_songListModel->rowCount()); for(int i=0; i<resultCount; i++) { SongRecord *song = m_songListModel->songAt(i); if(!song) { qDebug() << "TabletServer::mainScreen(): list: db: No song at index: "<<i; continue; } QVariantMap line; line["id"] = song->songId(); line["title"] = song->title(); line["text"] = song->text(); line["arr"] = song->defaultArrangement()->arrangement().join(", "); resultList << line; // We use the sequence md5 (above) for the md5 sig instead of the list contents now // md5sigList.append(QString::number(song->songId())); // md5sigList.append(song->title()); // md5sigList.append(song->text()); } } } else { // int liveId = AppSettings::taggedOutput("live")->id(); // SlideGroup *liveGroup = mw->outputInst(liveId)->slideGroup(); DocumentListModel * model = mw->documentListModel(); //uint secs = QDateTime::currentDateTime().toTime_t(); QString lowerFilter = filter.toLower(); for(int idx = 0; idx < model->rowCount(); idx++) { SlideGroup * group = model->groupAt(idx); SongSlideGroup *songGroup = dynamic_cast<SongSlideGroup*>(group); if(songGroup && ( songGroup->groupTitle().toLower().contains(lowerFilter) || songGroup->text().toLower().contains(lowerFilter))) { QVariantMap row; QVariant tooltip = model->data(model->index(group->groupNumber(),0), Qt::ToolTipRole); QString viewText = group->assumedName(); if(tooltip.isValid()) viewText = tooltip.toString(); row["id"] = idx; //songGroup->groupId(); row["title"] = viewText; row["text"] = songGroup->text(); row["arr"] = songGroup->arrangement().join(", "); row["mapping"] = genArrMapping(songGroup->text(), songGroup->arrangement()); resultList << row; md5sigList.append(QString::number(songGroup->groupId())); md5sigList.append(viewText); md5sigList.append(songGroup->text()); } // We don't limit the number of results in the document results moreResults = false; } } QString currentMD5 = MD5::md5sum(md5sigList.join("")); bool isChanged = true; if(pollingFlag && currentMD5 == clientMD5) isChanged = false; if(isChanged) { result["num"] = resultList.size(); result["list"] = QVariant(resultList); result["more"] = moreResults; result["cutoff"] = listCutoffLimit; } else result["nochange"] = true; result["md5"] = currentMD5; QString jsonString = m_toJson.serialize(result); //qDebug() << "TabletServer::mainScreen(): list: result: "<<result; //qDebug() << "TabletServer::mainScreen(): list: json: "<<jsonString; // Http_Send_Ok(socket) << // "Content-Type: application/json\n\n" << // jsonString; QHttpResponseHeader header(QString("HTTP/1.0 200 OK")); header.setValue("Content-Type", "application/json"); respond(socket, header); QTextStream output(socket); output.setAutoDetectUnicode(true); output << jsonString; } else if(control == "save_song") { if(user->level() < HttpUser::Admin) { Http_Send_500txt(socket, "Not Authorized"); return; } QString mode = query["mode"]; // Either "db" or "file" int itemid = query["itemid"].toInt(); // If mode is db, itemid is a songid, otherwise, it's a group index QString title = query["title"]; QString text = query["text"]; QString arrTxt = query["arr"]; QStringList newArrList = arrTxt.split(QRegExp("\\s*,\\s*")); SongRecord *song; if(mode == "file") { DocumentListModel * model = mw->documentListModel(); SlideGroup * group = model->groupAt(itemid); SongSlideGroup *songGroup = dynamic_cast<SongSlideGroup*>(group); // Update the document model songGroup->setArrangement(newArrList); songGroup->setGroupTitle(title); songGroup->setText(text); // automatically regenerates slides in document song = songGroup->song(); } else { song = SongRecord::retrieve(itemid); } if(!song) { Http_Send_404(socket) << "Invalid songid"; } song->setTitle(title); song->setText(text); SongArrangement *arr = song->defaultArrangement(); arr->setArrangement(newArrList); // Changes automatically committed to database QVariantMap result; result["mapping"] = genArrMapping(song->text(), arr->arrangement()); QString jsonString = m_toJson.serialize(result); QHttpResponseHeader header(QString("HTTP/1.0 200 OK")); header.setValue("Content-Type", "application/json"); respond(socket, header); QTextStream output(socket); output.setAutoDetectUnicode(true); output << jsonString; } else if(control == "add_song") { if(user->level() < HttpUser::Admin) { Http_Send_500txt(socket, "Not Authorized"); return; } int songid = query["songid"].toInt(); QVariantMap result; SongRecord *song = SongRecord::retrieve(songid); if(!song) { Http_Send_404(socket) << "Invalid songid"; } else { SlideGroup *group = mw->songBrowser()->createSlideGroup(song); group->setGroupNumber(mw->currentDocument()->numGroups()); mw->currentDocument()->addGroup(group); result["groupnum"] = group->groupNumber(); } QString jsonString = m_toJson.serialize(result); QHttpResponseHeader header(QString("HTTP/1.0 200 OK")); header.setValue("Content-Type", "application/json"); respond(socket, header); QTextStream output(socket); output.setAutoDetectUnicode(true); output << jsonString; } else if(control == "del_song") { if(user->level() < HttpUser::Admin) { Http_Send_500txt(socket, "Not Authorized"); return; } QString mode = query["mode"]; // Either "db" or "file" int itemid = query["itemid"].toInt(); if(mode == "file") { DocumentListModel * model = mw->documentListModel(); SlideGroup * group = model->groupAt(itemid); SongSlideGroup *songGroup = dynamic_cast<SongSlideGroup*>(group); if(!songGroup) { Http_Send_404(socket) << "Invalid songid"; } mw->currentDocument()->removeGroup(songGroup); } else { SongRecord *song = SongRecord::retrieve(itemid); if(!song) { Http_Send_404(socket) << "Invalid songid"; } SongRecord::deleteSong(song); } QVariantMap result; // Nothing to see here, move along. QString jsonString = m_toJson.serialize(result); QHttpResponseHeader header(QString("HTTP/1.0 200 OK")); header.setValue("Content-Type", "application/json"); respond(socket, header); QTextStream output(socket); output.setAutoDetectUnicode(true); output << jsonString; } else if(control == "show_slide") { if(user->level() < HttpUser::User) { Http_Send_500txt(socket, "Not Authorized"); return; } int groupIdx = query["group"].toInt(); Document * doc = mw->currentDocument(); if(!doc) { generic404(socket,path,query); return; } if(groupIdx < 0 || groupIdx >= doc->numGroups()) { generic404(socket,path,query); return; } DocumentListModel * docModel = mw->documentListModel(); SlideGroup *group = docModel->groupAt(groupIdx); if(!group) { generic404(socket,path,query); return; } int liveId = AppSettings::taggedOutput("live")->id(); SlideGroup *liveGroup = mw->outputInst(liveId)->slideGroup(); Slide * liveSlide = mw->outputInst(liveId)->slide(); //SlideGroupViewControl *viewControl = mw->viewControl(liveId); //Slide * liveSlide = viewControl->selectedSlide(); int idx = query.value("slide").toInt(); if(idx < 0 || idx > group->numSlides()) { generic404(socket,path,query); return; } Slide *slide = group->at(idx); if(liveGroup != group || liveSlide != slide) mw->setLiveGroup(group, ! slide ? liveSlide : slide); // prevent changing slides when loading the group page if group already live on different slide if(liveGroup == group && liveSlide != slide/* && nextPathElement != "icon"*/) { // this is JUST a change slide request mw->setLiveGroup(liveGroup,slide); // 204 = HTTP No Content, ("...[the browser] SHOULD NOT change its document view...") Http_Send_Response(socket,"HTTP/1.0 204 Changed Slide") << ""; // BlackBerry Internet Browser doesnt honor HTTP 204, so we have to use javascript to make it not change the current document return; } else Http_Send_Response(socket,"HTTP/1.0 204 No Change") << ""; } else if(control == "poll_live_slide") { if(user->level() < HttpUser::Guest) { Http_Send_500txt(socket, "Not Authorized"); return; } DocumentListModel * docModel = mw->documentListModel(); QVariantMap result; bool ok = true; int liveId = AppSettings::taggedOutput("live")->id(); SlideGroup *liveGroup = mw->outputInst(liveId)->slideGroup(); Slide *liveSlide = mw->outputInst(liveId)->slide(); if(!liveGroup) { ok = false; result["error"] = "NLG"; } // SlideGroupViewControl *viewControl = mw->viewControl(liveId); // Slide * liveSlide = viewControl->selectedSlide(); if(!liveSlide && ok) { ok = false; result["error"] = "NLS"; } if(ok) { int groupIdx = docModel->indexForGroup(liveGroup).row(); int slideIdx = liveGroup->indexOf(liveSlide); result["groupIdx"] = groupIdx; result["slideIdx"] = slideIdx; } QString jsonString = m_toJson.serialize(result); QHttpResponseHeader header(QString("HTTP/1.0 200 OK")); header.setValue("Content-Type", "application/json"); respond(socket, header); QTextStream output(socket); output.setAutoDetectUnicode(true); output << jsonString; } else { generic404(socket,path,query); } }
void Client::componentComplete() { server = Server::server(m_connectionName); connect(server, SIGNAL(respond(QVariantMap)), this, SIGNAL(respond(QVariantMap))); }
static void fsopen(Req *r) { int t; uvlong path; Aux *a; Fid *fid; Whist *wh; fid = r->fid; path = fid->qid.path; t = qidtype(fid->qid.path); if((r->ifcall.mode != OREAD && t != Fnew && t != Fmap) || (r->ifcall.mode&ORCLOSE)){ respond(r, "permission denied"); return; } a = fid->aux; switch(t){ case Droot: currentmap(0); rlock(&maplock); a->map = map; incref(map); runlock(&maplock); respond(r, nil); break; case D1st: if((wh = gethistory(qidnum(path))) == nil){ respond(r, "file does not exist"); return; } closewhist(a->w); a->w = wh; a->n = a->w->ndoc-1; r->ofcall.qid.vers = wh->doc[a->n].time; r->fid->qid = r->ofcall.qid; respond(r, nil); break; case D2nd: respond(r, nil); break; case Fnew: a->s = s_copy(""); respond(r, nil); break; case Fmap: case F1st: case F2nd: respond(r, nil); break; default: respond(r, "programmer error"); break; } }
void ctlwrite(Req *r) { int i; Cmdbuf *cb; vlong start, end; r->ofcall.count = r->ifcall.count; cb = parsecmd(r->ifcall.data, r->ifcall.count); if(cb->nf < 1){ respond(r, "empty control message"); free(cb); return; } if(strcmp(cb->f[0], "part") == 0){ if(cb->nf != 4){ respondcmderror(r, cb, "part takes 3 args"); free(cb); return; } start = strtoll(cb->f[2], 0, 0); end = strtoll(cb->f[3], 0, 0); if(addpart(cb->f[1], start, end) < 0){ respondcmderror(r, cb, "%r"); free(cb); return; } } else if(strcmp(cb->f[0], "delpart") == 0){ if(cb->nf != 2){ respondcmderror(r, cb, "delpart takes 1 arg"); free(cb); return; } if(delpart(cb->f[1]) < 0){ respondcmderror(r, cb, "%r"); free(cb); return; } } else if(strcmp(cb->f[0], "inquiry") == 0){ if(cb->nf != 2){ respondcmderror(r, cb, "inquiry takes 1 arg"); free(cb); return; } free(inquiry); inquiry = estrdup9p(cb->f[1]); } else if(strcmp(cb->f[0], "geometry") == 0){ if(cb->nf != 6){ respondcmderror(r, cb, "geometry takes 5 args"); free(cb); return; } nsect = strtoll(cb->f[1], 0, 0); sectsize = strtoll(cb->f[2], 0, 0); c = strtoll(cb->f[3], 0, 0); h = strtoll(cb->f[4], 0, 0); s = strtoll(cb->f[5], 0, 0); if(tab[0].inuse && strcmp(tab[0].name, "data") == 0 && tab[0].vers == 0){ tab[0].offset = 0; tab[0].length = nsect; } for(i=0; i<nelem(tab); i++){ if(tab[i].inuse && tab[i].offset+tab[i].length > nsect){ tab[i].inuse = 0; free(tab[i].name); tab[i].name = 0; } } } else{ respondcmderror(r, cb, "unknown control message"); free(cb); return; } free(cb); respond(r, nil); }
void respondError(int code, const QString &status, const QString &errorString) { respond(code, status, errorString.toUtf8() + '\n'); }
// no operation; only responds void noop(char **params, short *abor, int fd, struct state *cstate, struct config *configuration) { respond(fd, 2, 2, 0, "OK."); }
int ConnectionHandler::doCommand(QCString buf) { if((uid_t)peerUid() != getuid()) { kdWarning(1205) << "Peer uid not equal to me\n"; kdWarning(1205) << "Peer: " << peerUid() << " Me: " << getuid() << endl; return -1; } QCString key, command, pass, name, user, value, env_check; Data_entry data; Lexer *l = new Lexer(buf); int tok = l->lex(); switch(tok) { case Lexer::Tok_pass: // "PASS password:string timeout:int\n" tok = l->lex(); if(tok != Lexer::Tok_str) goto parse_error; m_Pass.fill('x'); m_Pass = l->lval(); tok = l->lex(); if(tok != Lexer::Tok_num) goto parse_error; m_Timeout = l->lval().toInt(); if(l->lex() != '\n') goto parse_error; if(m_Pass.isNull()) m_Pass = ""; kdDebug(1205) << "Password set!\n"; respond(Res_OK); break; case Lexer::Tok_host: // "HOST host:string\n" tok = l->lex(); if(tok != Lexer::Tok_str) goto parse_error; m_Host = l->lval(); if(l->lex() != '\n') goto parse_error; kdDebug(1205) << "Host set to " << m_Host << endl; respond(Res_OK); break; case Lexer::Tok_prio: // "PRIO priority:int\n" tok = l->lex(); if(tok != Lexer::Tok_num) goto parse_error; m_Priority = l->lval().toInt(); if(l->lex() != '\n') goto parse_error; kdDebug(1205) << "priority set to " << m_Priority << endl; respond(Res_OK); break; case Lexer::Tok_sched: // "SCHD scheduler:int\n" tok = l->lex(); if(tok != Lexer::Tok_num) goto parse_error; m_Scheduler = l->lval().toInt(); if(l->lex() != '\n') goto parse_error; kdDebug(1205) << "Scheduler set to " << m_Scheduler << endl; respond(Res_OK); break; case Lexer::Tok_exec: // "EXEC command:string user:string [options:string (env:string)*]\n" { QCString options; KStringList env; tok = l->lex(); if(tok != Lexer::Tok_str) goto parse_error; command = l->lval(); tok = l->lex(); if(tok != Lexer::Tok_str) goto parse_error; user = l->lval(); tok = l->lex(); if(tok != '\n') { if(tok != Lexer::Tok_str) goto parse_error; options = l->lval(); tok = l->lex(); while(tok != '\n') { if(tok != Lexer::Tok_str) goto parse_error; QCString env_str = l->lval(); env.append(env_str); if(strncmp(env_str, "DESKTOP_STARTUP_ID=", strlen("DESKTOP_STARTUP_ID=")) != 0) env_check += "*" + env_str; tok = l->lex(); } } QCString auth_user; if((m_Scheduler != SuProcess::SchedNormal) || (m_Priority > 50)) auth_user = "******"; else auth_user = user; key = makeKey(2, m_Host, auth_user, command); // We only use the command if the environment is the same. if(repo->find(key) == env_check) { key = makeKey(0, m_Host, auth_user, command); pass = repo->find(key); } if(pass.isNull()) // isNull() means no password, isEmpty() can mean empty password { if(m_Pass.isNull()) { respond(Res_NO); break; } data.value = env_check; data.timeout = m_Timeout; key = makeKey(2, m_Host, auth_user, command); repo->add(key, data); data.value = m_Pass; data.timeout = m_Timeout; key = makeKey(0, m_Host, auth_user, command); repo->add(key, data); pass = m_Pass; } // Execute the command asynchronously kdDebug(1205) << "Executing command: " << command << endl; pid_t pid = fork(); if(pid < 0) { kdDebug(1205) << "fork(): " << strerror(errno) << endl; respond(Res_NO); break; } else if(pid > 0) { m_pid = pid; respond(Res_OK); break; } // Ignore SIGCHLD because "class SuProcess" needs waitpid() signal(SIGCHLD, SIG_DFL); int ret; if(m_Host.isEmpty()) { SuProcess proc; proc.setCommand(command); proc.setUser(user); if(options.contains('x')) proc.setXOnly(true); if(options.contains('f')) proc.setDCOPForwarding(true); proc.setPriority(m_Priority); proc.setScheduler(m_Scheduler); proc.setEnvironment(env); ret = proc.exec(pass.data()); } else { SshProcess proc; proc.setCommand(command); proc.setUser(user); proc.setHost(m_Host); ret = proc.exec(pass.data()); } kdDebug(1205) << "Command completed: " << command << endl; _exit(ret); } case Lexer::Tok_delCmd: // "DEL command:string user:string\n" tok = l->lex(); if(tok != Lexer::Tok_str) goto parse_error; command = l->lval(); tok = l->lex(); if(tok != Lexer::Tok_str) goto parse_error; user = l->lval(); if(l->lex() != '\n') goto parse_error; key = makeKey(0, m_Host, user, command); if(repo->remove(key) < 0) { kdDebug(1205) << "Unknown command: " << command << endl; respond(Res_NO); } else { kdDebug(1205) << "Deleted command: " << command << ", user = "******"DELV name:string \n" { tok = l->lex(); if(tok != Lexer::Tok_str) goto parse_error; name = l->lval(); tok = l->lex(); if(tok != '\n') goto parse_error; key = makeKey(1, name); if(repo->remove(key) < 0) { kdDebug(1205) << "Unknown name: " << name << endl; respond(Res_NO); } else { kdDebug(1205) << "Deleted name: " << name << endl; respond(Res_OK); } break; } case Lexer::Tok_delGroup: // "DELG group:string\n" tok = l->lex(); if(tok != Lexer::Tok_str) goto parse_error; name = l->lval(); if(repo->removeGroup(name) < 0) { kdDebug(1205) << "No keys found under group: " << name << endl; respond(Res_NO); } else { kdDebug(1205) << "Removed all keys under group: " << name << endl; respond(Res_OK); } break; case Lexer::Tok_delSpecialKey: // "DELS special_key:string\n" tok = l->lex(); if(tok != Lexer::Tok_str) goto parse_error; name = l->lval(); if(repo->removeSpecialKey(name) < 0) respond(Res_NO); else respond(Res_OK); break; case Lexer::Tok_set: // "SET name:string value:string group:string timeout:int\n" tok = l->lex(); if(tok != Lexer::Tok_str) goto parse_error; name = l->lval(); tok = l->lex(); if(tok != Lexer::Tok_str) goto parse_error; data.value = l->lval(); tok = l->lex(); if(tok != Lexer::Tok_str) goto parse_error; data.group = l->lval(); tok = l->lex(); if(tok != Lexer::Tok_num) goto parse_error; data.timeout = l->lval().toInt(); if(l->lex() != '\n') goto parse_error; key = makeKey(1, name); repo->add(key, data); kdDebug(1205) << "Stored key: " << key << endl; respond(Res_OK); break; case Lexer::Tok_get: // "GET name:string\n" tok = l->lex(); if(tok != Lexer::Tok_str) goto parse_error; name = l->lval(); if(l->lex() != '\n') goto parse_error; key = makeKey(1, name); kdDebug(1205) << "Request for key: " << key << endl; value = repo->find(key); if(!value.isEmpty()) respond(Res_OK, value); else respond(Res_NO); break; case Lexer::Tok_getKeys: // "GETK groupname:string\n" tok = l->lex(); if(tok != Lexer::Tok_str) goto parse_error; name = l->lval(); if(l->lex() != '\n') goto parse_error; kdDebug(1205) << "Request for group key: " << name << endl; value = repo->findKeys(name); if(!value.isEmpty()) respond(Res_OK, value); else respond(Res_NO); break; case Lexer::Tok_chkGroup: // "CHKG groupname:string\n" tok = l->lex(); if(tok != Lexer::Tok_str) goto parse_error; name = l->lval(); if(l->lex() != '\n') goto parse_error; kdDebug(1205) << "Checking for group key: " << name << endl; if(repo->hasGroup(name) < 0) respond(Res_NO); else respond(Res_OK); break; case Lexer::Tok_ping: // "PING\n" tok = l->lex(); if(tok != '\n') goto parse_error; respond(Res_OK); break; case Lexer::Tok_exit: // "EXIT\n" tok = l->lex(); if(tok != '\n') goto parse_error; m_needExitCode = true; if(m_hasExitCode) sendExitCode(); break; case Lexer::Tok_stop: // "STOP\n" tok = l->lex(); if(tok != '\n') goto parse_error; kdDebug(1205) << "Stopping by command" << endl; respond(Res_OK); kdesud_cleanup(); exit(0); default: kdWarning(1205) << "Unknown command: " << l->lval() << endl; respond(Res_NO); goto parse_error; } delete l; return 0; parse_error: kdWarning(1205) << "Parse error" << endl; delete l; return -1; }
// system info void syst(char **params, short *abor, int fd, struct state *cstate, struct config *configuration) { respond(fd, 2, 1, 5, "UNIX Type: L8"); }
// should give information about unusual commands supported by the server void feat(char **params, short *abor, int fd, struct state *cstate, struct config *configuration) { respond(fd, 2, 1, 1, "Sorry."); write(fd, "NONE", 4); respond(fd, 2, 1, 1, "end"); }
// disconnects from the server void quit(char **params, short *abor, int fd, struct state *cstate, struct config *configuration) { pthread_detach(cstate->data_thread); respond(fd, 2, 2, 1, "Closing connection."); *abor = 1; }
static Xfid* fsysread(Xfid *x, Fid *f) { Fcall t; uchar *b; int i, id, n, o, e, j, k, *ids, nids; Dirtab *d, dt; Column *c; uint clock, len; char buf[16]; if(f->qid.type & QTDIR){ if(FILE(f->qid) == Qacme){ /* empty dir */ t.data = nil; t.count = 0; respond(x, &t, nil); return x; } o = x->fcall.offset; e = x->fcall.offset+x->fcall.count; clock = getclock(); b = emalloc(messagesize); id = WIN(f->qid); n = 0; if(id > 0) d = dirtabw; else d = dirtab; d++; /* first entry is '.' */ for(i=0; d->name!=nil && i<e; i+=len){ len = dostat(WIN(x->f->qid), d, b+n, x->fcall.count-n, clock); if(len <= BIT16SZ) break; if(i >= o) n += len; d++; } if(id == 0){ qlock(&row.lk); nids = 0; ids = nil; for(j=0; j<row.ncol; j++){ c = row.col[j]; for(k=0; k<c->nw; k++){ ids = realloc(ids, (nids+1)*sizeof(int)); ids[nids++] = c->w[k]->id; } } qunlock(&row.lk); qsort(ids, nids, sizeof ids[0], idcmp); j = 0; dt.name = buf; for(; j<nids && i<e; i+=len){ k = ids[j]; sprint(dt.name, "%d", k); dt.qid = QID(k, Qdir); dt.type = QTDIR; dt.perm = DMDIR|0700; len = dostat(k, &dt, b+n, x->fcall.count-n, clock); if(len == 0) break; if(i >= o) n += len; j++; } free(ids); } t.data = (char*)b; t.count = n; respond(x, &t, nil); free(b); return x; } sendp(x->c, (void*)xfidread); return nil; }
static Xfid* fsyswalk(Xfid *x, Fid *f) { Fcall t; int c, i, j, id; Qid q; uchar type; ulong path; Fid *nf; Dirtab *d, *dir; Window *w; char *err; nf = nil; w = nil; if(f->open) return respond(x, &t, "walk of open file"); if(x->fcall.fid != x->fcall.newfid){ nf = newfid(x->fcall.newfid); if(nf->busy) return respond(x, &t, "newfid already in use"); nf->busy = TRUE; nf->open = FALSE; nf->mntdir = f->mntdir; if(f->mntdir) f->mntdir->ref++; nf->dir = f->dir; nf->qid = f->qid; nf->w = f->w; nf->nrpart = 0; /* not open, so must be zero */ if(nf->w) incref(&nf->w->ref); f = nf; /* walk f */ } t.nwqid = 0; err = nil; dir = nil; id = WIN(f->qid); q = f->qid; if(x->fcall.nwname > 0){ for(i=0; i<x->fcall.nwname; i++){ if((q.type & QTDIR) == 0){ err = Enotdir; break; } if(strcmp(x->fcall.wname[i], "..") == 0){ type = QTDIR; path = Qdir; id = 0; if(w){ winclose(w); w = nil; } Accept: if(i == MAXWELEM){ err = "name too long"; break; } q.type = type; q.vers = 0; q.path = QID(id, path); t.wqid[t.nwqid++] = q; continue; } /* is it a numeric name? */ for(j=0; (c=x->fcall.wname[i][j]); j++) if(c<'0' || '9'<c) goto Regular; /* yes: it's a directory */ if(w) /* name has form 27/23; get out before losing w */ break; id = atoi(x->fcall.wname[i]); qlock(&row.lk); w = lookid(id, FALSE); if(w == nil){ qunlock(&row.lk); break; } incref(&w->ref); /* we'll drop reference at end if there's an error */ path = Qdir; type = QTDIR; qunlock(&row.lk); dir = dirtabw; goto Accept; Regular: if(strcmp(x->fcall.wname[i], "new") == 0){ if(w) error("w set in walk to new"); sendp(cnewwindow, nil); /* signal newwindowthread */ w = recvp(cnewwindow); /* receive new window */ incref(&w->ref); type = QTDIR; path = QID(w->id, Qdir); id = w->id; dir = dirtabw; goto Accept; } if(id == 0) d = dirtab; else d = dirtabw; d++; /* skip '.' */ for(; d->name; d++) if(strcmp(x->fcall.wname[i], d->name) == 0){ path = d->qid; type = d->type; dir = d; goto Accept; } break; /* file not found */ } if(i==0 && err == nil) err = Eexist; } if(err!=nil || t.nwqid<x->fcall.nwname){ if(nf){ nf->busy = FALSE; fsysdelid(nf->mntdir); } }else if(t.nwqid == x->fcall.nwname){ if(w){ f->w = w; w = nil; /* don't drop the reference */ } if(dir) f->dir = dir; f->qid = q; } if(w != nil) winclose(w); return respond(x, &t, err); }
string Kernel::respond(const string &input, const string &id, Responder *r, bool srai, const string &prefix) { return respond(input, id, r, 1, srai, prefix); }
/* This parser is rather liberal in what it accepts: The IMAP standard mandates seperate character sets for tags, commands, unquoted strings. Since they all must be seperated by spaces, this parser allows all non-whitespace characters for each of the above. */ static int parse_line(void) { #define RESPOND(T,S) do{ respond(T,S); return 0; }while(0) unsigned i; unsigned len; const char* ptr; str* arg; /* Parse out the command tag */ str_truncate(&tag, 0); for (i = 0, ptr = line.s; i < line.len && isspace(*ptr); ++i, ++ptr) ; for (; i < line.len && !isspace(*ptr); ++i, ++ptr) str_catc(&tag, line.s[i]); if (!tag.len) RESPOND(NOTAG, "BAD Syntax error"); if (i >= line.len) RESPOND(0, "BAD Syntax error"); /* Parse out the command itself */ str_truncate(&cmd, 0); for (; i < line.len && isspace(*ptr); ++i, ++ptr) ; for (; i < line.len && !isspace(*ptr); ++i, ++ptr) str_catc(&cmd, line.s[i]); if (!cmd.len) RESPOND(0, "BAD Syntax error"); /* Parse out the command-line args */ for (line_argc = 0; line_argc < MAX_ARGC; ++line_argc) { arg = &line_args[line_argc]; str_truncate(arg, 0); for (; i < line.len && isspace(*ptr); ++i, ++ptr) ; if (i >= line.len) break; switch (*ptr) { case LBRACE: /* Handle a string literal */ ++i, ++ptr; if (!isdigit(*ptr)) RESPOND(0, "BAD Syntax error: missing integer"); for (len = 0; i < line.len && *ptr != RBRACE; ++i, ++ptr) { if (!isdigit(*ptr)) RESPOND(0, "BAD Syntax error: invalid integer"); len = len * 10 + *ptr - '0'; } ++i, ++ptr; if (*ptr != 0) RESPOND(0, "BAD Syntax error: missing LF after integer"); str_ready(arg, len); respond(CONT, "OK"); if (len > 0) ibuf_read(&inbuf, arg->s, len); arg->s[arg->len = len] = 0; ibuf_getstr_crlf(&inbuf, &line); i = 0; ptr = line.s; break; case QUOTE: /* Handle a quoted string */ for (++i, ++ptr; i < line.len && *ptr != QUOTE; ++i, ++ptr) { if (*ptr == ESCAPE) { if (++i >= line.len) break; ++ptr; } str_catc(arg, *ptr); } if (i >= line.len || *ptr != QUOTE) RESPOND(0, "BAD Syntax error: unterminated quoted string"); ++i, ++ptr; break; default: /* Normal case is very simple */ for (; i < line.len && !isspace(*ptr); ++i, ++ptr) str_catc(arg, *ptr); } } for (; i < line.len && isspace(*ptr); ++i, ++ptr) ; if (i < line.len) RESPOND(0, "BAD Too many command arguments"); return 1; }
RequestHandler::RequestHandler(string m,QTcpSocket* client,DatabaseController &db){ msg =m; respond(client,db); }
void cmd_noop(void) { respond(0, "OK NOOP completed"); }
int rdwrpart(Req *r) { int q, nonzero; Part *p; vlong offset; long count, tot, n, o; uchar *blk, *dat; void *(*move)(void*, void*, ulong); q = r->fid->qid.path-Qpart; if(q < 0 || q > nelem(tab) || !tab[q].inuse || tab[q].vers != r->fid->qid.vers){ respond(r, "unknown partition"); return -1; } p = &tab[q]; offset = r->ifcall.offset; count = r->ifcall.count; if(offset < 0){ respond(r, "negative offset"); return -1; } if(count < 0){ respond(r, "negative count"); return -1; } if(offset > p->length*sectsize){ respond(r, "offset past end of partition"); return -1; } if(offset+count > p->length*sectsize) count = p->length*sectsize - offset; offset += p->offset*sectsize; if(r->ifcall.type == Tread) move = memmove; else move = evommem; tot = 0; nonzero = 1; if(r->ifcall.type == Tread) dat = (uchar*)r->ofcall.data; else{ dat = (uchar*)r->ifcall.data; nonzero = isnonzero(dat, r->ifcall.count); } o = offset & (BLKSZ-1); /* left fringe block */ if(o && count){ blk = getblock(offset, r->ifcall.type==Twrite && nonzero); n = BLKSZ - o; if(n > count) n = count; if(r->ifcall.type != Twrite || blk != zero) (*move)(dat, blk+o, n); if(r->ifcall.type == Twrite) dirty(offset, blk); tot += n; } /* full and right fringe blocks */ while(tot < count){ blk = getblock(offset+tot, r->ifcall.type==Twrite && nonzero); n = BLKSZ; if(n > count-tot) n = count-tot; if(r->ifcall.type != Twrite || blk != zero) (*move)(dat+tot, blk, n); if(r->ifcall.type == Twrite) dirty(offset+tot, blk); tot += n; } r->ofcall.count = tot; respond(r, nil); return 0; }
void cmd_logout(void) { respond(NOTAG, "Logging out"); respond(0, "OK LOGOUT completed"); exit(0); }
static int doit (void) { char qtype[2]; char qclass[2]; char header[12]; unsigned int pos = 0; if ((unsigned)len >= sizeof buf) goto NOQ; if (!(pos = dns_packet_copy (buf, len, 0, header, 12))) goto NOQ; if (header[2] & 128) goto NOQ; if (header[4]) goto NOQ; if (header[5] != 1) goto NOQ; if (!(pos = dns_packet_getname (buf, len, pos, &q))) goto NOQ; if (!(pos = dns_packet_copy (buf, len, pos, qtype, 2))) goto NOQ; if (!(pos = dns_packet_copy (buf, len, pos, qclass, 2))) goto NOQ; if (!response_query (q, qtype, qclass)) goto NOQ; response_id (header); qnum++; if (byte_equal (qclass, 2, DNS_C_IN)) response[2] |= 4; else if (byte_diff (qclass, 2, DNS_C_ANY)) goto WEIRDCLASS; response[3] &= ~128; if (!(header[2] & 1)) response[2] &= ~1; if (header[2] & 126) goto NOTIMP; if (byte_equal (qtype, 2, DNS_T_AXFR)) goto NOTIMP; case_lowerb (q, dns_domain_length (q)); if (!respond (q, qtype, ip)) { log_query (qnum, ip, port, header, q, qtype); return 0; } log_query (qnum, ip, port, header, q, qtype); return 1; NOTIMP: response[3] &= ~15; response[3] |= 4; log_query (qnum, ip, port, header, q, qtype); return 1; WEIRDCLASS: response[3] &= ~15; response[3] |= 1; log_query (qnum, ip, port, header, q, qtype); return 1; NOQ: log_query (qnum, ip, port, "\0\0", "", "\0\0"); return 0; }
void TradeHandler::handleMessage(Net::MessageIn &msg) { switch (msg.getId()) { case GPMSG_TRADE_REQUEST: { Being *being = actorSpriteManager->findBeing(msg.readInt16()); if (!being || !mAcceptTradeRequests) { respond(false); break; } mTrading = true; tradePartnerName = being->getName(); tradePartnerID = being->getId(); ConfirmDialog *dlg = new ConfirmDialog(_("Request for Trade"), strprintf(_("%s wants to trade with you, do you accept?"), tradePartnerName.c_str())); dlg->addActionListener(&listener); } break; case GPMSG_TRADE_ADD_ITEM: { int type = msg.readInt16(); int amount = msg.readInt8(); tradeWindow->addItem(type, false, amount); } break; case GPMSG_TRADE_SET_MONEY: tradeWindow->setMoney(msg.readInt32()); break; case GPMSG_TRADE_START: tradeWindow->reset(); tradeWindow->setCaption(strprintf(_("Trading with %s"), tradePartnerName.c_str())); tradeWindow->setVisible(true); break; case GPMSG_TRADE_BOTH_CONFIRM: tradeWindow->receivedOk(false); break; case GPMSG_TRADE_AGREED: tradeWindow->receivedOk(false); break; case GPMSG_TRADE_CANCEL: SERVER_NOTICE(_("Trade canceled.")) tradeWindow->setVisible(false); tradeWindow->reset(); mTrading = false; break; case GPMSG_TRADE_COMPLETE: SERVER_NOTICE(_("Trade completed.")) tradeWindow->setVisible(false); tradeWindow->reset(); mTrading = false; break; } }
int main(int argc, char **argv) { int opt; int len, rc; struct sigaction sigact; char *rest; int oflags = 0; int no_tag; memset(&sigact, 0, sizeof(sigact)); sigact.sa_handler = sighandler; if (sigaction(SIGALRM, &sigact, NULL) == -1) return 1; if (sigaction(SIGPIPE, &sigact, NULL) == -1) return 1; input = stdin; output = stdout; /* now parsing options with getopt */ while ((opt = getopt(argc, argv, options)) != EOF) { switch (opt) { case 'c': rc = chdir(optarg); if (rc == -1) { fprintf(stderr, "Can not change dir to %s errno = %d \"%s\"\n", optarg, errno, strerror(errno)); exit(1); } break; case 'q': quiet = true; break; case 'd': duperrors = true; break; case 's': if (oflags > 7) show_usage(1, "Can not combine -x and -s\n"); oflags |= 1; script = true; strncpy(server, optarg, MAXSTR); break; case 'x': if ((oflags & 7) != 0) show_usage(1, "Can not combine -x and -s/-p/-n\n"); oflags |= 8; script = true; input = fopen(optarg, "r"); if (input == NULL) fatal("Could not open %s\n", optarg); break; case 'n': if (oflags > 7) show_usage(1, "Can not combine -x and -n\n"); oflags |= 2; strncpy(name, optarg, MAXSTR); break; case 'p': if (oflags > 7) show_usage(1, "Can not combine -x and -p\n"); oflags |= 4; strncpy(portstr, optarg, MAXSTR); port = atoi(optarg); break; case '?': case 'h': default: /* display the help */ show_usage(0, "Help\n"); } } if (oflags > 0 && oflags < 7) show_usage(1, "Must specify -s, -p, and -n together\n"); if (oflags == 7) openserver(); while (1) { len = readln(input, line, MAXSTR * 2); if (len < 0) { if (script) fatal("End of file on input\n"); else break; } else { struct response resp; lno++; memset(&resp, 0, sizeof(resp)); rest = SkipWhite(line, REQUIRES_MORE, "Invalid line"); /* Skip totally blank line */ if (rest == NULL) continue; if (script && !quiet) fprintf(stdout, "%s\n", rest); /* If line doesn't start with a tag, that's ok */ no_tag = (!isdigit(*rest) && (*rest != '$')); /* Parse request into response structure */ rest = parse_request(rest, &resp, no_tag); if (rest == NULL) { resp.r_status = STATUS_ERRNO; resp.r_errno = errno; } else { /* Make sure default status is ok */ resp.r_status = STATUS_OK; if (*rest != '\0' && *rest != '#') fprintf_stderr( "Command line not consumed, rest=\"%s\"\n", rest); switch (resp.r_cmd) { case CMD_OPEN: do_open(&resp); break; case CMD_CLOSE: do_close(&resp); break; case CMD_LOCKW: do_lock(&resp); break; case CMD_LOCK: do_lock(&resp); break; case CMD_UNLOCK: do_unlock(&resp); break; case CMD_TEST: do_test(&resp); break; case CMD_LIST: do_list(&resp); break; case CMD_HOP: do_hop(&resp); break; case CMD_UNHOP: do_unhop(&resp); break; case CMD_SEEK: do_seek(&resp); break; case CMD_READ: do_read(&resp); break; case CMD_WRITE: do_write(&resp); break; case CMD_ALARM: do_alarm(&resp); break; case CMD_HELLO: case CMD_COMMENT: case CMD_QUIT: resp.r_status = STATUS_OK; break; case NUM_COMMANDS: fprintf_stderr("Invalid command %s\n", line); continue; } } respond(&resp); if (resp.r_cmd == CMD_QUIT) exit(0); } } return 0; }
void die(const char* msg) { respond(421, 1, msg); exit(111); }
void ctlwrite(Req *r, Client *c) { char *f[3], *s, *p; int nf; s = emalloc(r->ifcall.count+1); memmove(s, r->ifcall.data, r->ifcall.count); s[r->ifcall.count] = '\0'; f[0] = s; p = strchr(s, ' '); if(p == nil) nf = 1; else{ *p++ = '\0'; f[1] = p; nf = 2; } if(f[0][0] == '\0'){ free(s); respond(r, nil); return; } r->ofcall.count = r->ifcall.count; if(strcmp(f[0], "hangup") == 0){ if(c->pid == 0){ respond(r, "connection already hung up"); goto Out; } postnote(PNPROC, c->pid, "kill"); respond(r, nil); goto Out; } if(strcmp(f[0], "connect") == 0){ if(c->cmd != nocmd){ respond(r, "already have connection"); goto Out; } if(nf == 1){ respond(r, "need argument to connect"); goto Out; } c->status = Exec; if(p = strrchr(f[1], '!')) *p = '\0'; c->cmd = emalloc(4+1+strlen(f[1])+1); strcpy(c->cmd, "exec "); strcat(c->cmd, f[1]); c->execreq = r; threadcreate(execthread, c, STACK); goto Out; } respond(r, "bad or inappropriate control message"); Out: free(s); }
int main(/*int argc, char *argv[]*/) { INFO("Started\n"); int server_socket, client_socket, port, res, client_len, n; struct sockaddr_in srv_addr, client_addr; int iSetOption = 1; port = SRVPORT; server_socket = socket(AF_INET, SOCK_STREAM, 0); setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, (char*)&iSetOption, sizeof(iSetOption)); if (server_socket < 0) { ERROR("Error opening socket\n"); IFERROR(perror("")); } INFO("Made server socket\n"); memset((char *) &srv_addr, 0, sizeof(srv_addr)); srv_addr.sin_family = AF_INET; srv_addr.sin_port = htons(port); srv_addr.sin_addr.s_addr = INADDR_ANY; while ((res = bind(server_socket, (struct sockaddr *) &srv_addr, sizeof(srv_addr))) < 0) { ERROR("Error binding socket\n"); IFERROR(perror("")); } listen(server_socket, 5); INFO("Listening on port %d\n", port); client_len = sizeof(client_addr); if (chdir("content")) { ERROR("Could not chdir to the content directory\n"); IFERROR(perror("")); exit(1); } do { client_socket = accept(server_socket, (struct sockaddr *) &client_addr, (socklen_t *) &client_len); INFO("Accepted client socket\n"); if (client_socket < 0) { ERROR("Error on client accept\n"); IFERROR(perror("")); } request *req = request_new(); char line[MAXLEN]; while ((n = fd_readline(client_socket, line, MAXLEN)) > 0) { if (n == MAXLEN-1 && line[MAXLEN-1] != '\n') { WARN("Line length exceeded MAXLEN %d\n", MAXLEN); char c; int dropped = 0; while ((n = read(client_socket, &c, 1)) > 0) { dropped += 1; if (c == '\n') break; } WARN("Skipped to the next line, dropped %d characters\n", dropped); } if (is_crlf(line)) { // We've reached the end of the headers int left_to_read = request_get_content_length(req); int total_read = 0, len; if (left_to_read > 0) { DEBUG("There's %d chars of body to read\n", left_to_read); // There's a Content-Length so there must be a body req->body = malloc(sizeof(char) * (left_to_read+1)); len = MAXLEN < left_to_read ? MAXLEN : left_to_read; len += 1; while (left_to_read && (n = fd_readline(client_socket, line, len)) > 0) { DEBUG("Read %d characters of body: %s\n", n, line); strcpy(&req->body[total_read], line); total_read += n; left_to_read -= n; DEBUG("total_read: %d, left_to_read: %d\n", total_read, left_to_read); len = MAXLEN < left_to_read ? MAXLEN : left_to_read; } req->body[total_read+1] = '\0'; DEBUG("Done reading body in %d chars:\n", total_read); DEBUG("%s\n", req->body); respond(&req, client_socket); continue; } else { DEBUG("No body to read, generating response\n"); respond(&req, client_socket); continue; } } if (request_parse(req, line)) { WARN("An error occurred while parsing the previous line\n"); } } DEBUG("Done with this request! n = %d\n", n); } while (1); close(server_socket); close(client_socket); return 0; }
static void fsread(Req* r) { Query* q; char** toks; int ntoks; int atoks; char* s; int pos; File* f; if(r->fid->qid.type&QTDIR){ respond(r, "bug: write on dir"); return; } f = r->fid->file; if(f == ctlf){ ctlread(r); return; } q = f->aux; /* The first read process the query. * Further reads just retrieve more data, * if any. */ if(q->expr == nil){ atoks = 512; toks = emalloc9p(atoks*sizeof(char*)); do { s = estrdup9p(q->text); ntoks = tokenize(s, toks, atoks); if(ntoks == atoks){ atoks += 512; toks = erealloc9p(toks, atoks*sizeof(char*)); free(s); } }while(ntoks == atoks); pos = 0; if(chatty9p) fprint(2, "compiling %s (%d toks)\n", q->text, ntoks); q->expr = parseexpr(ntoks, toks, &pos); if(q->expr == nil){ free(s); free(toks); respond(r, "syntax error"); return; } if(chatty9p) fprint(2, "evaluating %s (%d toks)\n", q->text, ntoks); evalexpr(trie, q->expr); free(s); free(toks); free(q->text); /* smprintexprval limits the total output to * at most 64K of text */ q->text = smprintexprval(q->expr); if(chatty9p) fprint(2, "result is [%s]\n", q->text); } /* After the query is process, * q->text holds the reply. */ readstr(r, q->text); respond(r, nil); }
string Kernel::respond(const string &input, const string &id, const string &prefix) { return respond(input, id, 1, false, prefix); }
void respond(session* ses, const char* msg) { string resp(msg); respond(ses, resp); }
void respond(Req *r, char *error) { int i, m, n; char errbuf[ERRMAX]; Srv *srv; srv = r->srv; assert(srv != nil); if(r->responded){ assert(r->pool); goto free; } assert(r->responded == 0); r->error = error; switch(r->ifcall.type){ default: assert(0); /* * Flush is special. If the handler says so, we return * without further processing. Respond will be called * again once it is safe. */ case Tflush: if(rflush(r, error)<0) return; break; case Tversion: rversion(r, error); break; case Tauth: rauth(r, error); break; case Tattach: rattach(r, error); break; case Twalk: rwalk(r, error); break; case Topen: ropen(r, error); break; case Tcreate: rcreate(r, error); break; case Tread: rread(r, error); break; case Twrite: rwrite(r, error); break; case Tclunk: rclunk(r, error); break; case Tremove: rremove(r, error, errbuf); break; case Tstat: rstat(r, error); break; case Twstat: rwstat(r, error); break; } r->ofcall.tag = r->ifcall.tag; r->ofcall.type = r->ifcall.type+1; if(r->error) setfcallerror(&r->ofcall, r->error); if(chatty9p) fprint(2, "-%d-> %F\n", srv->outfd, &r->ofcall); qlock(&srv->wlock); n = convS2M(&r->ofcall, srv->wbuf, srv->msize); if(n <= 0){ fprint(2, "n = %d %F\n", n, &r->ofcall); abort(); } assert(n > 2); /* * There is a race here - we must remove the entry before * the write, so that if the client is very fast and reuses the * tag, the read loop won't think it is still in use. * * By removing the entry before the write, we open up a * race with incoming Tflush messages. Specifically, an * incoming Tflush might not see r even though it has not * yet been responded to. It would then send an Rflush * immediately, potentially before we do the write. This can't * happen because we already old srv->wlock, so nothing * is going out on the wire before this write. */ if(r->pool) /* not a fake */ closereq(removereq(r->pool, r->ifcall.tag)); qlock(&r->lk); r->responded = 1; if(r->pool) if(r->ref.ref == 1+r->nflush) if(r->fid){ /* * There are no references other than in our r->flush array, * so no one else should be accessing r concurrently. * Close the fid now, before responding to the message. * * If the client is behaving (there are no outstanding T-messages * that reference r->fid) and the message is a Tclunk or Tremove, * then this closefid will call destroyfid. * * This means destroyfid can't piddle around * indefinitely (we're holding srv->wlock!), but it provides * for tighter semantics as to when destroyfid is called. * * LANL has observed cases where waiting until after the write * can delay a closefid on a Twrite for many 9P transactions, * so that a handful of transactions can happen including a Tclunk * and a Topen, and the original fid will still not be destroyed. */ closefid(r->fid); r->fid = nil; } qunlock(&r->lk); m = write(srv->outfd, srv->wbuf, n); if(m != n) sysfatal("lib9p srv: write %d returned %d on fd %d: %r", n, m, srv->outfd); qunlock(&srv->wlock); free: qlock(&r->lk); /* no one will add flushes now */ for(i=0; i<r->nflush; i++){ r->flush[i]->oldreq = nil; /* so it doesn't try to lock us! */ respond(r->flush[i], nil); } free(r->flush); r->flush = nil; r->nflush = 0; qunlock(&r->lk); if(r->pool) closereq(r); else free(r); }