KStringList KDEsuClient::getKeys(const QCString &group) { QCString cmd = "GETK "; cmd += escape(group); cmd += "\n"; QCString reply; command(cmd, &reply); int index = 0, pos; KStringList list; if(!reply.isEmpty()) { // kdDebug(900) << "Found a matching entry: " << reply << endl; while(1) { pos = reply.find('\007', index); if(pos == -1) { if(index == 0) list.append(reply); else list.append(reply.mid(index)); break; } else { list.append(reply.mid(index, pos - index)); } index = pos + 1; } } return list; }
int main(int argc, char **argv) { int argi = 1; while((argi < argc) && (argv[argi][0] == '-')) { switch(argv[argi][1]) { case 'l': bLaunchApp = true; break; case 'a': bAppIdOnly = true; break; default: usage(); } argi++; } if(argc <= argi) usage(); DCOPClient client; client.attach(); dcop = &client; QCString app; QCString objid; QCString function; char **args = 0; if((argc > argi) && (strncmp(argv[argi], "DCOPRef(", 8)) == 0) { char *delim = strchr(argv[argi], ','); if(!delim) { fprintf(stderr, "Error: '%s' is not a valid DCOP reference.\n", argv[argi]); return 1; } *delim = 0; app = argv[argi++] + 8; delim++; delim[strlen(delim) - 1] = 0; objid = delim; } else { if(argc > argi) app = argv[argi++]; if(argc > argi) objid = argv[argi++]; } if(argc > argi) function = argv[argi++]; if(argc > argi) { args = &argv[argi]; argc = argc - argi; } else { argc = 0; } KStringList params; for(int i = 0; i < argc; i++) params.append(args[i]); bool ok = findObject(app, objid, function, params); if(ok) return 0; if(bLaunchApp) { ok = launchApp(app); if(!ok) return 2; ok = findObject(app, objid, function, params); } return 1; }
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; }
int main(int argc, char **argv) { bool readStdin = false; int numOptions = 0; QString user; Session session = DefaultSession; QString sessionName; bool updateUserTime = true; cin_.setEncoding(QTextStream::Locale); // Scan for command-line options first for(int pos = 1; pos <= argc - 1; pos++) { if(strcmp(argv[pos], "--help") == 0) showHelp(0); else if(strcmp(argv[pos], "--pipe") == 0) { readStdin = true; numOptions++; } else if(strcmp(argv[pos], "--user") == 0) { if(pos <= argc - 2) { user = QString::fromLocal8Bit(argv[pos + 1]); numOptions += 2; pos++; } else { cerr_ << "Missing username for '--user' option!" << endl << endl; showHelp(-1); } } else if(strcmp(argv[pos], "--session") == 0) { if(session == AllSessions) { cerr_ << "ERROR: --session cannot be mixed with --all-sessions!" << endl << endl; showHelp(-1); } else if(pos <= argc - 2) { sessionName = QString::fromLocal8Bit(argv[pos + 1]); numOptions += 2; pos++; } else { cerr_ << "Missing session name for '--session' option!" << endl << endl; showHelp(-1); } } else if(strcmp(argv[pos], "--all-users") == 0) { user = "******"; numOptions++; } else if(strcmp(argv[pos], "--list-sessions") == 0) { session = QuerySessions; numOptions++; } else if(strcmp(argv[pos], "--all-sessions") == 0) { if(!sessionName.isEmpty()) { cerr_ << "ERROR: --session cannot be mixed with --all-sessions!" << endl << endl; showHelp(-1); } session = AllSessions; numOptions++; } else if(strcmp(argv[pos], "--no-user-time") == 0) { updateUserTime = false; numOptions++; } else if(argv[pos][0] == '-') { cerr_ << "Unknown command-line option '" << argv[pos] << "'." << endl << endl; showHelp(-1); } else break; // End of options } argc -= numOptions; KStringList args; #ifdef DCOPQUIT if(argc > 1) { QCString prog = argv[numOptions + 1]; if(!prog.isEmpty()) { args.append(prog); // Pass as-is if it ends with a wildcard if(prog[prog.length() - 1] != '*') { // Strip a trailing -<PID> part. int i = prog.findRev('-'); if((i >= 0) && prog.mid(i + 1).toLong()) { prog = prog.left(i); } args.append("qt/" + prog); args.append("quit()"); } } } #else for(int i = numOptions; i < argc + numOptions - 1; i++) args.append(argv[i + 1]); #endif if(readStdin && args.count() < 3) { cerr_ << "--pipe option only supported for function calls!" << endl << endl; showHelp(-1); } if(user == "*" && args.count() < 3 && session != QuerySessions) { cerr_ << "ERROR: The --all-users option is only supported for function calls!" << endl << endl; showHelp(-1); } if(session == QuerySessions && !args.isEmpty()) { cerr_ << "ERROR: The --list-sessions option cannot be used for actual DCOP calls!" << endl << endl; showHelp(-1); } if(session == QuerySessions && user.isEmpty()) { cerr_ << "ERROR: The --list-sessions option can only be used with the --user or" << endl << "--all-users options!" << endl << endl; showHelp(-1); } if(session != DefaultSession && session != QuerySessions && args.count() < 3) { cerr_ << "ERROR: The --session and --all-sessions options are only supported for function" << endl << "calls!" << endl << endl; showHelp(-1); } UserList users; if(user == "*") users = userList(); else if(!user.isEmpty()) users[user] = userList()[user]; int retval = runDCOP(args, users, session, sessionName, readStdin, updateUserTime); return retval; }