bool conf_update_from_environment(struct conf *conf, char **errmsg) { char **p; char *q; char *key; char *errmsg2; const struct env_to_conf_item *env_to_conf_item; bool negate; size_t key_start; for (p = environ; *p; ++p) { if (!str_startswith(*p, "CCACHE_")) { continue; } q = strchr(*p, '='); if (!q) { continue; } if (str_startswith(*p + 7, "NO")) { negate = true; key_start = 9; } else { negate = false; key_start = 7; } key = x_strndup(*p + key_start, q - *p - key_start); ++q; /* Now points to the value. */ env_to_conf_item = find_env_to_conf(key); if (!env_to_conf_item) { free(key); continue; } if (!handle_conf_setting( conf, env_to_conf_item->conf_name, q, &errmsg2, true, negate, "environment")) { *errmsg = format("%s: %s", key, errmsg2); free(errmsg2); free(key); return false; } free(key); } return true; }
/* Some files should always be built locally... */ int dcc_source_needs_local(const char *filename) { const char *p; p = dcc_find_basename(filename); if (str_startswith("conftest.", p) || str_startswith("tmp.conftest.", p)) { rs_trace("autoconf tests are run locally: %s", filename); return EXIT_DISTCC_FAILED; } return 0; }
/* * Convert any "-Wp," options into regular gcc options. * We do this because it simplifies the command-line * option handling elsewhere; this is the only place * that needs to parse "-Wp," options. * Returns 0 on success, nonzero for error (out of memory). * * The argv array pointed to by argv_ptr when this function * is called must have been dynamically allocated. It remains * the caller's responsibility to deallocate it. */ int dcc_expand_preprocessor_options(char ***argv_ptr) { int i, j, ret; char **argv = *argv_ptr; char **new_argv; int argc = dcc_argv_len(argv); for (i = 0; argv[i]; i++) { if (str_startswith("-Wp,", argv[i])) { /* First, calculate how many extra arguments we'll need. */ int extra_args = count_extra_args(argv[i]); assert(extra_args >= 1); new_argv = calloc(argc + extra_args, sizeof(char *)); if (!new_argv) { return EXIT_OUT_OF_MEMORY; } for (j = 0; j < i; j++) { new_argv[j] = argv[j]; } if ((ret = copy_extra_args(new_argv + i, argv[i], extra_args)) != 0) { free(new_argv); return ret; } for (j = i + 1; j <= argc; j++) { new_argv[j + extra_args - 1] = argv[j]; } free(argv); *argv_ptr = argv = new_argv; } } return 0; }
/* performs an HTTP post to the given URL, with callback */ int netio_http_post(char *url, char *content_type, char *data, int data_len, void (*func) (char *url, int respcode, char *data, int data_len, void *pkg), void *pkg) { char *host = 0, *path = 0; int hostlen, ret = -1; /* parse url */ ASSERT_TRUE(str_startswith(url, "http://"), err); url += 7; path = strchr(url, '/'); if (!path) { hostlen = strlen(url); path = strdup("/"); } else { hostlen = path - url; path = strdup(path); } ASSERT_TRUE(host = strndup((const char*)url, (size_t)hostlen), err); ret = netio_http_post_host(host, path, url-7, content_type, data, data_len, func, pkg); err: freez(host); freez(path); return ret; }
END_TEST START_TEST (test_encode_zeros) { struct latlon_double lls[4] = {{0, 0}, { 40.700, -120.950}, { 40.700, -120.950}, { 40.700, -120.950}}; encode (lls, 4); ck_assert (str_endswith(polyline_result(), "????")); ck_assert (str_startswith(polyline_result(), "??")); }
/* Subroutine of dcc_expand_preprocessor_options(). * Calculate how many extra arguments we'll need to convert * a "-Wp,..." option into regular gcc options. * Returns the number of extra arguments needed. */ static int count_extra_args(char *dash_Wp_option) { int extra_args = 0; char *comma = dash_Wp_option + strlen("-Wp"); while (comma != NULL) { char *opt = comma + 1; comma = strchr(opt, ','); if (str_startswith("-MD,", opt) || str_startswith("-MMD,", opt)) { char *filename = comma + 1; comma = strchr(filename, ','); extra_args += 3; /* "-MD", "-MF", filename. */ } else { extra_args++; } } return extra_args; }
virtual IOHANDLE OpenFile(const char *pFilename, int Flags, int Type, char *pBuffer = 0, int BufferSize = 0) { char aBuffer[MAX_PATH_LENGTH]; if(!pBuffer) { pBuffer = aBuffer; BufferSize = sizeof(aBuffer); } if(Type == TYPE_ABSOLUTE) { return io_open(pFilename, Flags); } if(str_startswith(pFilename, "mapres/../skins/")) { pFilename = pFilename + 10; // just start from skins/ } if(pFilename[0] == '/' || pFilename[0] == '\\' || str_find(pFilename, "../") != NULL || str_find(pFilename, "..\\") != NULL #ifdef CONF_FAMILY_WINDOWS || (pFilename[0] && pFilename[1] == ':') #endif ) { // don't escape base directory } else if(Flags&IOFLAG_WRITE) { return io_open(GetPath(TYPE_SAVE, pFilename, pBuffer, BufferSize), Flags); } else { IOHANDLE Handle = 0; if(Type <= TYPE_ALL) { // check all available directories for(int i = 0; i < m_NumPaths; ++i) { Handle = io_open(GetPath(i, pFilename, pBuffer, BufferSize), Flags); if(Handle) return Handle; } } else if(Type >= 0 && Type < m_NumPaths) { // check wanted directory Handle = io_open(GetPath(Type, pFilename, pBuffer, BufferSize), Flags); if(Handle) return Handle; } } pBuffer[0] = 0; return 0; }
int assets_list(const char *url, void *user, int (*f)(int i, const char *path, void *user)) { int i, j = 0; for (i = 0; ASSETS[i].path; i++) { if (str_startswith(ASSETS[i].path, url)) { if (!f || f(j, ASSETS[i].path, user) == 0) j++; } } return j; }
const void *assets_get(const char *url, int *size) { int i; if (str_startswith(url, "asset://")) url += 8; // Skip asset:// for (i = 0; ASSETS[i].path; i++) { if (str_equ(ASSETS[i].path, url)) { if (size) *size = ASSETS[i].size; return ASSETS[i].data; } } return NULL; }
const char * hy_advisory_get_id(HyAdvisory advisory) { const char *id; id = pool_lookup_str(advisory->pool, advisory->a_id, SOLVABLE_NAME); assert(str_startswith(id, SOLVABLE_NAME_ADVISORY_PREFIX)); //remove the prefix id += strlen(SOLVABLE_NAME_ADVISORY_PREFIX); return id; }
void interactive_kernel_loop() { char *buff = (char*) 0x10000; uint32_t len = 0x20000 - 0x10000; char *decodebuff = (char*) 0x20000; uint32_t decodebufflen = 0x30000 - 0x20000; int status = 0; while (1) { status = uart_getln(buff, len); if (status == 0) { uart_puts(uart_newline); if (str_startswith(buff, "b64 ")) { uint32_t bytes_decoded = b64_decode(buff+4, decodebuff, decodebufflen); uart_puts("base64 decoded #bytes: "); char tmp[32]; uint32_t tmplen = ARR_LEN(tmp); uart_puts(str_int_to_str(bytes_decoded, tmp, tmplen)); uart_puts(uart_newline); // Copy the code of bootstrap_decoded_binary somewhere safe. uint32_t func_len = 64; // wild guess mem_cpy((uint32_t)bootstrap_decoded_binary, 0x30000, func_len); // Call bootstrap_decoded_binary from that safe location BRANCHTO(0x30000); } else if (str_startswith(buff, "m ")) { inspect_memory(buff+2); } else if (str_startswith(buff, "r ")) { inspect_reg(buff+2); } else if (str_startswith(buff, "icky")) { uart_puts(yoo); } else if (str_startswith(buff, "usr0")) { if (pr0) { switch_to_user_process(pr0); } } else if (str_startswith(buff, "freloc")) { char tmp[32]; uint32_t tmplen = ARR_LEN(tmp); uint32_t func_len = ((uint32_t) str_parse_int) - ((uint32_t) str_len); mem_cpy((uint32_t)str_len, 0x30000, func_len); uart_puts(str_int_to_str(CALL_1(0x30000, "xyz"), tmp, tmplen)); } else if (str_startswith(buff, "version")) { uart_puts(version); uart_puts("\r\n"); } else { int strlen = str_len(buff) - 1; int j = 0; for (; strlen != -1; --strlen, ++j) { decodebuff[j] = buff[strlen]; } decodebuff[j] = 0; uart_puts(decodebuff); } } uart_puts(uart_newline); } }
/** * Read in @p filename from inside @p dirname, and try to parse it as * a status file. * * If a new entry is read, a pointer to it is returned in @p lp. **/ static int dcc_mon_do_file(char *dirname, char *filename, struct dcc_task_state **lp) { int fd; char *fullpath; int ret; *lp = NULL; /* Is this a file we want to see */ if (!str_startswith(dcc_state_prefix, filename)) { /* rs_trace("skipped"); */ return 0; } checked_asprintf(&fullpath, "%s/%s", dirname, filename); if (fullpath == NULL) { return EXIT_OUT_OF_MEMORY; } rs_trace("process %s", fullpath); /* Remember that the file might disappear at any time, so open it * now so that we can hang on. */ if ((fd = open(fullpath, O_RDONLY|O_BINARY, 0)) == -1) { if (errno == ENOENT) { rs_trace("%s disappeared", fullpath); ret = 0; goto out_free; } else { /* hm */ rs_log_warning("failed to open %s: %s", fullpath, strerror(errno)); ret = EXIT_IO_ERROR; goto out_free; } } if ((ret = dcc_mon_kill_old(fd, fullpath))) { /* closes fd on failure */ goto out_free; } ret = dcc_mon_load_state(fd, fullpath, lp); dcc_close(fd); out_free: free(fullpath); return ret; /* ok */ }
// Strip any arguments beginning with the specified prefix. void args_strip(struct args *args, const char *prefix) { for (int i = 0; i < args->argc;) { if (str_startswith(args->argv[i], prefix)) { free(args->argv[i]); memmove(&args->argv[i], &args->argv[i+1], (args->argc - i) * sizeof(args->argv[i])); args->argc--; } else { i++; } } }
/* this builds the list of files in the cache */ static void traverse_fn(const char *fname, struct stat *st) { char *p; if (!S_ISREG(st->st_mode)) { return; } p = basename(fname); if (str_eq(p, "stats")) { goto out; } if (str_startswith(p, ".nfs")) { /* Ignore temporary NFS files that may be left for open but deleted * files. */ goto out; } if (strstr(p, ".tmp.")) { /* delete any tmp files older than 1 hour */ if (st->st_mtime + 3600 < time(NULL)) { x_unlink(fname); goto out; } } if (strstr(p, "CACHEDIR.TAG")) { goto out; } if (num_files == allocated) { allocated = 10000 + num_files*2; files = (struct files **)x_realloc(files, sizeof(struct files *)*allocated); } files[num_files] = (struct files *)x_malloc(sizeof(struct files)); files[num_files]->fname = x_strdup(fname); files[num_files]->mtime = st->st_mtime; files[num_files]->size = file_size(st); cache_size += files[num_files]->size; files_in_cache++; num_files++; out: free(p); }
void LoadPaths(const char *pArgv0) { // check current directory IOHANDLE File = io_open("storage.cfg", IOFLAG_READ); if(!File) { // check usable path in argv[0] unsigned int Pos = ~0U; for(unsigned i = 0; pArgv0[i]; i++) if(pArgv0[i] == '/' || pArgv0[i] == '\\') Pos = i; if(Pos < MAX_PATH_LENGTH) { char aBuffer[MAX_PATH_LENGTH]; str_copy(aBuffer, pArgv0, Pos+1); str_append(aBuffer, "/storage.cfg", sizeof(aBuffer)); File = io_open(aBuffer, IOFLAG_READ); } if(Pos >= MAX_PATH_LENGTH || !File) { dbg_msg("storage", "couldn't open storage.cfg"); return; } } char *pLine; CLineReader LineReader; LineReader.Init(File); while((pLine = LineReader.Get())) { const char *pLineWithoutPrefix = str_startswith(pLine, "add_path "); if(pLineWithoutPrefix) { AddPath(pLineWithoutPrefix); } } io_close(File); if(!m_NumPaths) dbg_msg("storage", "no paths found in storage.cfg"); }
static char * path_from_uri(WebdavBackendFs *pbctx, const char *real_uri) { char *toret = NULL; assert(str_startswith(real_uri, "/")); toret = davfuse_util_strdup(pbctx->base_path); if (!toret) goto err; if (str_equals(real_uri, "/")) return toret; const char *start_of_dirname = real_uri; while (*start_of_dirname) { start_of_dirname += 1; const char *next = strchr(start_of_dirname, '/'); if (!next) next = start_of_dirname + strlen(start_of_dirname); char *path_comp = malloc(next - start_of_dirname + 1); if (!path_comp) goto err; memcpy(path_comp, start_of_dirname, next - start_of_dirname); path_comp[next - start_of_dirname] = '\0'; char *newtoret = util_fs_path_join(pbctx->fs, toret, path_comp); free(path_comp); if (!newtoret) goto err; free(toret); toret = newtoret; start_of_dirname = next; } if (false) { err: free(toret); toret = NULL; } return toret; }
/** * Remove "-o" options from argument list. * * This is used when running the preprocessor, when we just want it to write * to stdout, which is the default when no -o option is specified. * * Structurally similar to dcc_strip_local_args() **/ int dcc_strip_dasho(char **from, char ***out_argv) { char **to; int from_i, to_i; int from_len; from_len = dcc_argv_len(from); *out_argv = to = malloc((from_len + 1) * sizeof (char *)); if (!to) { rs_log_error("failed to allocate space for arguments"); return EXIT_OUT_OF_MEMORY; } /* skip through argv, copying all arguments but skipping ones that * ought to be omitted */ for (from_i = to_i = 0; from[from_i]; ) { if (!strcmp(from[from_i], "-o")) { /* skip "-o FILE" */ from_i += 2; } else if (str_startswith("-o", from[from_i])) { /* skip "-oFILE" */ from_i++; } else { to[to_i++] = from[from_i++]; } } /* NULL-terminate */ to[to_i] = NULL; dcc_trace_argv("result", to); return 0; }
void CAutoMapper::Load(const char* pTileName) { char aPath[256]; str_format(aPath, sizeof(aPath), "editor/%s.rules", pTileName); IOHANDLE RulesFile = m_pEditor->Storage()->OpenFile(aPath, IOFLAG_READ, IStorage::TYPE_ALL); if(!RulesFile) return; CLineReader LineReader; LineReader.Init(RulesFile); CConfiguration *pCurrentConf = 0; CRun *pCurrentRun = 0; CIndexRule *pCurrentIndex = 0; char aBuf[256]; // read each line while(char *pLine = LineReader.Get()) { // skip blank/empty lines as well as comments if(str_length(pLine) > 0 && pLine[0] != '#' && pLine[0] != '\n' && pLine[0] != '\r' && pLine[0] != '\t' && pLine[0] != '\v' && pLine[0] != ' ') { if(pLine[0]== '[') { // new configuration, get the name pLine++; CConfiguration NewConf; NewConf.m_StartX = 0; NewConf.m_StartY = 0; NewConf.m_EndX = 0; NewConf.m_EndY = 0; int ConfigurationID = m_lConfigs.add(NewConf); pCurrentConf = &m_lConfigs[ConfigurationID]; str_copy(pCurrentConf->m_aName, pLine, str_length(pLine)); // add start run CRun NewRun; NewRun.m_AutomapCopy = true; int RunID = pCurrentConf->m_aRuns.add(NewRun); pCurrentRun = &pCurrentConf->m_aRuns[RunID]; } else if(str_startswith(pLine, "NewRun")) { // add new run CRun NewRun; NewRun.m_AutomapCopy = true; int RunID = pCurrentConf->m_aRuns.add(NewRun); pCurrentRun = &pCurrentConf->m_aRuns[RunID]; } else if(str_startswith(pLine, "Index") && pCurrentRun) { // new index int ID = 0; char aOrientation1[128] = ""; char aOrientation2[128] = ""; char aOrientation3[128] = ""; sscanf(pLine, "Index %d %127s %127s %127s", &ID, aOrientation1, aOrientation2, aOrientation3); CIndexRule NewIndexRule; NewIndexRule.m_ID = ID; NewIndexRule.m_Flag = 0; NewIndexRule.m_RandomProbability = 1.0; NewIndexRule.m_DefaultRule = true; NewIndexRule.m_SkipEmpty = false; NewIndexRule.m_SkipFull = false; if(str_length(aOrientation1) > 0) { if(!str_comp(aOrientation1, "XFLIP")) NewIndexRule.m_Flag |= TILEFLAG_VFLIP; else if(!str_comp(aOrientation1, "YFLIP")) NewIndexRule.m_Flag |= TILEFLAG_HFLIP; else if(!str_comp(aOrientation1, "ROTATE")) NewIndexRule.m_Flag |= TILEFLAG_ROTATE; } if(str_length(aOrientation2) > 0) { if(!str_comp(aOrientation2, "XFLIP")) NewIndexRule.m_Flag |= TILEFLAG_VFLIP; else if(!str_comp(aOrientation2, "YFLIP")) NewIndexRule.m_Flag |= TILEFLAG_HFLIP; else if(!str_comp(aOrientation2, "ROTATE")) NewIndexRule.m_Flag |= TILEFLAG_ROTATE; } if(str_length(aOrientation3) > 0) { if(!str_comp(aOrientation3, "XFLIP")) NewIndexRule.m_Flag |= TILEFLAG_VFLIP; else if(!str_comp(aOrientation3, "YFLIP")) NewIndexRule.m_Flag |= TILEFLAG_HFLIP; else if(!str_comp(aOrientation3, "ROTATE")) NewIndexRule.m_Flag |= TILEFLAG_ROTATE; } // add the index rule object and make it current int IndexRuleID = pCurrentRun->m_aIndexRules.add(NewIndexRule); pCurrentIndex = &pCurrentRun->m_aIndexRules[IndexRuleID]; } else if(str_startswith(pLine, "Pos") && pCurrentIndex) { int x = 0, y = 0; char aValue[128]; int Value = CPosRule::NORULE; array<CIndexInfo> NewIndexList; sscanf(pLine, "Pos %d %d %127s", &x, &y, aValue); if(!str_comp(aValue, "EMPTY")) { Value = CPosRule::INDEX; CIndexInfo NewIndexInfo = {0, 0, false}; NewIndexList.add(NewIndexInfo); } else if(!str_comp(aValue, "FULL")) { Value = CPosRule::NOTINDEX; CIndexInfo NewIndexInfo1 = {0, 0, false}; //CIndexInfo NewIndexInfo2 = {-1, 0}; NewIndexList.add(NewIndexInfo1); //NewIndexList.add(NewIndexInfo2); } else if(!str_comp(aValue, "INDEX") || !str_comp(aValue, "NOTINDEX")) { if(!str_comp(aValue, "INDEX")) Value = CPosRule::INDEX; else Value = CPosRule::NOTINDEX; int pWord = 4; while(true) { int ID = 0; char aOrientation1[128] = ""; char aOrientation2[128] = ""; char aOrientation3[128] = ""; char aOrientation4[128] = ""; sscanf(str_trim_words(pLine, pWord), "%d %127s %127s %127s %127s", &ID, aOrientation1, aOrientation2, aOrientation3, aOrientation4); CIndexInfo NewIndexInfo; NewIndexInfo.m_ID = ID; NewIndexInfo.m_Flag = 0; NewIndexInfo.m_TestFlag = false; if(!str_comp(aOrientation1, "OR")) { NewIndexList.add(NewIndexInfo); pWord += 2; continue; } else if(str_length(aOrientation1) > 0) { NewIndexInfo.m_TestFlag = true; if(!str_comp(aOrientation1, "XFLIP")) NewIndexInfo.m_Flag = TILEFLAG_VFLIP; else if(!str_comp(aOrientation1, "YFLIP")) NewIndexInfo.m_Flag = TILEFLAG_HFLIP; else if(!str_comp(aOrientation1, "ROTATE")) NewIndexInfo.m_Flag = TILEFLAG_ROTATE; else if(!str_comp(aOrientation1, "NONE")) NewIndexInfo.m_Flag = 0; else NewIndexInfo.m_TestFlag = false; } else { NewIndexList.add(NewIndexInfo); break; } if(!str_comp(aOrientation2, "OR")) { NewIndexList.add(NewIndexInfo); pWord += 3; continue; } else if(str_length(aOrientation2) > 0 && NewIndexInfo.m_Flag != 0) { if(!str_comp(aOrientation2, "XFLIP")) NewIndexInfo.m_Flag |= TILEFLAG_VFLIP; else if(!str_comp(aOrientation2, "YFLIP")) NewIndexInfo.m_Flag |= TILEFLAG_HFLIP; else if(!str_comp(aOrientation2, "ROTATE")) NewIndexInfo.m_Flag |= TILEFLAG_ROTATE; } else { NewIndexList.add(NewIndexInfo); break; } if(!str_comp(aOrientation3, "OR")) { NewIndexList.add(NewIndexInfo); pWord += 4; continue; } else if(str_length(aOrientation3) > 0 && NewIndexInfo.m_Flag != 0) { if(!str_comp(aOrientation3, "XFLIP")) NewIndexInfo.m_Flag |= TILEFLAG_VFLIP; else if(!str_comp(aOrientation3, "YFLIP")) NewIndexInfo.m_Flag |= TILEFLAG_HFLIP; else if(!str_comp(aOrientation3, "ROTATE")) NewIndexInfo.m_Flag |= TILEFLAG_ROTATE; } else { NewIndexList.add(NewIndexInfo); break; } if(!str_comp(aOrientation4, "OR")) { NewIndexList.add(NewIndexInfo); pWord += 5; continue; } else { NewIndexList.add(NewIndexInfo); break; } } } if(Value != CPosRule::NORULE) { CPosRule NewPosRule = {x, y, Value, NewIndexList}; pCurrentIndex->m_aRules.add(NewPosRule); pCurrentConf->m_StartX = min(pCurrentConf->m_StartX, NewPosRule.m_X); pCurrentConf->m_StartY = min(pCurrentConf->m_StartY, NewPosRule.m_Y); pCurrentConf->m_EndX = max(pCurrentConf->m_EndX, NewPosRule.m_X); pCurrentConf->m_EndY = max(pCurrentConf->m_EndY, NewPosRule.m_Y); if(x == 0 && y == 0) { for(int i = 0; i < NewIndexList.size(); ++i) { if(Value == CPosRule::INDEX && NewIndexList[i].m_ID == 0) pCurrentIndex->m_SkipFull = true; else pCurrentIndex->m_SkipEmpty = true; } } } } else if(str_startswith(pLine, "Random") && pCurrentIndex) { float Value; char Specifier = ' '; sscanf(pLine, "Random %f%c", &Value, &Specifier); if(Specifier == '%') { pCurrentIndex->m_RandomProbability = Value / 100.0; } else { pCurrentIndex->m_RandomProbability = 1.0 / Value; } } else if(str_startswith(pLine, "NoDefaultRule") && pCurrentIndex) { pCurrentIndex->m_DefaultRule = false; } else if(!str_comp_num(pLine, "NoLayerCopy", 11) && pCurrentRun) { pCurrentRun->m_AutomapCopy = false; } } } // add default rule for Pos 0 0 if there is none for (int g = 0; g < m_lConfigs.size(); ++g) { for (int h = 0; h < m_lConfigs[g].m_aRuns.size(); ++h) { for(int i = 0; i < m_lConfigs[g].m_aRuns[h].m_aIndexRules.size(); ++i) { CIndexRule *pIndexRule = &m_lConfigs[g].m_aRuns[h].m_aIndexRules[i]; bool Found = false; for(int j = 0; j < pIndexRule->m_aRules.size(); ++j) { CPosRule *pRule = &pIndexRule->m_aRules[j]; if(pRule && pRule->m_X == 0 && pRule->m_Y == 0) { Found = true; break; } } if(!Found && pIndexRule->m_DefaultRule) { array<CIndexInfo> NewIndexList; CIndexInfo NewIndexInfo = {0, 0, false}; NewIndexList.add(NewIndexInfo); CPosRule NewPosRule = {0, 0, CPosRule::NOTINDEX, NewIndexList}; pIndexRule->m_aRules.add(NewPosRule); pIndexRule->m_SkipEmpty = true; pIndexRule->m_SkipFull = false; } if(pIndexRule->m_SkipEmpty && pIndexRule->m_SkipFull) { pIndexRule->m_SkipFull = false; } } } } io_close(RulesFile); str_format(aBuf, sizeof(aBuf),"loaded %s", aPath); m_pEditor->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "editor", aBuf); m_FileLoaded = true; }
/* Client program */ int main(int argc, char *argv[]) { char server[256]; char fullhostname[64]; char domain[256]; char shell[256]; char directory[256]; RD_BOOL prompt_password, deactivated; struct passwd *pw; uint32 flags, ext_disc_reason = 0; char *p; int c; char *locale = NULL; int username_option = 0; RD_BOOL geometry_option = False; #ifdef WITH_RDPSND char *rdpsnd_optarg = NULL; #endif #ifdef HAVE_LOCALE_H /* Set locale according to environment */ locale = setlocale(LC_ALL, ""); if (locale) { locale = xstrdup(locale); } #endif /* Ignore SIGPIPE, since we are using popen() */ struct sigaction act; memset(&act, 0, sizeof(act)); act.sa_handler = SIG_IGN; sigemptyset(&act.sa_mask); act.sa_flags = 0; sigaction(SIGPIPE, &act, NULL); /* setup default flags for TS_INFO_PACKET */ flags = RDP_INFO_MOUSE | RDP_INFO_DISABLECTRLALTDEL | RDP_INFO_UNICODE | RDP_INFO_MAXIMIZESHELL | RDP_INFO_ENABLEWINDOWSKEY; prompt_password = False; g_seamless_spawn_cmd[0] = domain[0] = g_password[0] = shell[0] = directory[0] = 0; g_embed_wnd = 0; g_num_devices = 0; #ifdef RDP2VNC #define VNCOPT "V:Q:" #else #define VNCOPT #endif while ((c = getopt(argc, argv, VNCOPT "A:u:L:d:s:c:p:n:k:g:o:fbBeEitmzCDKS:T:UNX:a:x:Pr:045h?")) != -1) { switch (c) { #ifdef RDP2VNC case 'V': rfb_port = strtol(optarg, NULL, 10); if (rfb_port < 100) rfb_port += 5900; break; case 'Q': defer_time = strtol(optarg, NULL, 10); if (defer_time < 0) defer_time = 0; break; #endif case 'A': g_seamless_rdp = True; STRNCPY(g_seamless_shell, optarg, sizeof(g_seamless_shell)); break; case 'u': g_username = (char *) xmalloc(strlen(optarg) + 1); STRNCPY(g_username, optarg, strlen(optarg) + 1); username_option = 1; break; case 'L': #ifdef HAVE_ICONV STRNCPY(g_codepage, optarg, sizeof(g_codepage)); #else error("iconv support not available\n"); #endif break; case 'd': STRNCPY(domain, optarg, sizeof(domain)); break; case 's': STRNCPY(shell, optarg, sizeof(shell)); g_seamless_persistent_mode = False; break; case 'c': STRNCPY(directory, optarg, sizeof(directory)); break; case 'p': if ((optarg[0] == '-') && (optarg[1] == 0)) { prompt_password = True; break; } STRNCPY(g_password, optarg, sizeof(g_password)); flags |= RDP_INFO_AUTOLOGON; /* try to overwrite argument so it won't appear in ps */ p = optarg; while (*p) *(p++) = 'X'; break; #ifdef WITH_SCARD case 'i': flags |= RDP_INFO_PASSWORD_IS_SC_PIN; g_use_password_as_pin = True; break; #endif case 't': g_use_ctrl = False; break; case 'n': STRNCPY(g_hostname, optarg, sizeof(g_hostname)); break; case 'k': STRNCPY(g_keymapname, optarg, sizeof(g_keymapname)); break; case 'g': geometry_option = True; g_fullscreen = False; if (!strcmp(optarg, "workarea")) { g_sizeopt = 1; break; } g_width = strtol(optarg, &p, 10); if (g_width <= 0) { error("invalid geometry\n"); return EX_USAGE; } if (*p == 'x') g_height = strtol(p + 1, &p, 10); if (g_height <= 0) { error("invalid geometry\n"); return EX_USAGE; } if (*p == '%') { g_sizeopt = -g_width; g_width = 800; p++; } if (*p == '+' || *p == '-') { g_pos |= (*p == '-') ? 2 : 1; g_xpos = strtol(p, &p, 10); } if (*p == '+' || *p == '-') { g_pos |= (*p == '-') ? 4 : 1; g_ypos = strtol(p, NULL, 10); } break; case 'f': g_fullscreen = True; break; case 'b': g_bitmap_cache = False; break; case 'B': g_ownbackstore = False; break; case 'e': g_encryption_initial = g_encryption = False; break; case 'E': g_packet_encryption = False; break; case 'm': g_sendmotion = False; break; case 'C': g_owncolmap = True; break; case 'D': g_hide_decorations = True; break; case 'K': g_grab_keyboard = False; break; case 'U': g_ungrab_on_ctrlalt = True; break; case 'S': if (!strcmp(optarg, "standard")) { g_win_button_size = 18; break; } g_win_button_size = strtol(optarg, &p, 10); if (*p) { error("invalid button size\n"); return EX_USAGE; } break; case 'T': STRNCPY(g_title, optarg, sizeof(g_title)); break; case 'N': g_numlock_sync = True; break; case 'X': g_embed_wnd = strtol(optarg, NULL, 0); break; case 'a': g_server_depth = strtol(optarg, NULL, 10); if (g_server_depth != 8 && g_server_depth != 16 && g_server_depth != 15 && g_server_depth != 24 && g_server_depth != 32) { error("Invalid server colour depth.\n"); return EX_USAGE; } break; case 'z': DEBUG(("rdp compression enabled\n")); flags |= (RDP_INFO_COMPRESSION | RDP_INFO_COMPRESSION2); break; case 'x': if (str_startswith(optarg, "m")) /* modem */ { g_rdp5_performanceflags = RDP5_NO_CURSOR_SHADOW | RDP5_NO_WALLPAPER | RDP5_NO_FULLWINDOWDRAG | RDP5_NO_MENUANIMATIONS | RDP5_NO_THEMING; } else if (str_startswith(optarg, "b")) /* broadband */ { g_rdp5_performanceflags = RDP5_NO_CURSOR_SHADOW | RDP5_NO_WALLPAPER; } else if (str_startswith(optarg, "l")) /* lan */ { g_rdp5_performanceflags = RDP5_NO_CURSOR_SHADOW | RDP5_DISABLE_NOTHING; } else { g_rdp5_performanceflags = RDP5_NO_CURSOR_SHADOW | strtol(optarg, NULL, 16); } break; case 'P': g_bitmap_cache_persist_enable = True; break; case 'r': if (str_startswith(optarg, "sound")) { optarg += 5; if (*optarg == ':') { optarg++; while ((p = next_arg(optarg, ','))) { if (str_startswith(optarg, "remote")) flags |= RDP_INFO_REMOTE_CONSOLE_AUDIO; if (str_startswith(optarg, "local")) #ifdef WITH_RDPSND { rdpsnd_optarg = next_arg(optarg, ':'); g_rdpsnd = True; } #else warning("Not compiled with sound support\n"); #endif if (str_startswith(optarg, "off")) #ifdef WITH_RDPSND g_rdpsnd = False; #else warning("Not compiled with sound support\n"); #endif optarg = p; } } else { #ifdef WITH_RDPSND g_rdpsnd = True; #else warning("Not compiled with sound support\n"); #endif } } else if (str_startswith(optarg, "disk")) { /* -r disk:h:=/mnt/floppy */ disk_enum_devices(&g_num_devices, optarg + 4); } else if (str_startswith(optarg, "comport")) { serial_enum_devices(&g_num_devices, optarg + 7); } else if (str_startswith(optarg, "lspci")) { g_lspci_enabled = True; } else if (str_startswith(optarg, "lptport")) { parallel_enum_devices(&g_num_devices, optarg + 7); } else if (str_startswith(optarg, "printer")) { printer_enum_devices(&g_num_devices, optarg + 7); } else if (str_startswith(optarg, "clientname")) { g_rdpdr_clientname = xmalloc(strlen(optarg + 11) + 1); strcpy(g_rdpdr_clientname, optarg + 11); } else if (str_startswith(optarg, "clipboard")) { optarg += 9; if (*optarg == ':') { optarg++; if (str_startswith(optarg, "off")) g_rdpclip = False; else cliprdr_set_mode(optarg); } else g_rdpclip = True; } else if (strncmp("scard", optarg, 5) == 0) { #ifdef WITH_SCARD scard_enum_devices(&g_num_devices, optarg + 5); #else warning("Not compiled with smartcard support\n"); #endif } else { warning("Unknown -r argument\n\n\tPossible arguments are: comport, disk, lptport, printer, sound, clipboard, scard\n"); } break; case '0': g_console_session = True; break; case '4': g_rdp_version = RDP_V4; break; case '5': g_rdp_version = RDP_V5; break; #if WITH_SCARD case 'o': { char *p = strchr(optarg, '='); if (p == NULL) { warning("Skipping option '%s' specified, lacks name=value format.\n"); continue; } if (strncmp(optarg, "sc-csp-name", strlen("sc-scp-name")) == 0) g_sc_csp_name = strdup(p + 1); else if (strncmp (optarg, "sc-reader-name", strlen("sc-reader-name")) == 0) g_sc_reader_name = strdup(p + 1); else if (strncmp (optarg, "sc-card-name", strlen("sc-card-name")) == 0) g_sc_card_name = strdup(p + 1); else if (strncmp (optarg, "sc-container-name", strlen("sc-container-name")) == 0) g_sc_container_name = strdup(p + 1); } break; #endif case 'h': case '?': default: usage(argv[0]); return EX_USAGE; } } if (argc - optind != 1) { usage(argv[0]); return EX_USAGE; } STRNCPY(server, argv[optind], sizeof(server)); parse_server_and_port(server); if (g_seamless_rdp) { if (shell[0]) STRNCPY(g_seamless_spawn_cmd, shell, sizeof(g_seamless_spawn_cmd)); STRNCPY(shell, g_seamless_shell, sizeof(shell)); if (g_win_button_size) { error("You cannot use -S and -A at the same time\n"); return EX_USAGE; } g_rdp5_performanceflags &= ~RDP5_NO_FULLWINDOWDRAG; if (geometry_option) { error("You cannot use -g and -A at the same time\n"); return EX_USAGE; } if (g_fullscreen) { error("You cannot use -f and -A at the same time\n"); return EX_USAGE; } if (g_hide_decorations) { error("You cannot use -D and -A at the same time\n"); return EX_USAGE; } if (g_embed_wnd) { error("You cannot use -X and -A at the same time\n"); return EX_USAGE; } if (g_rdp_version < RDP_V5) { error("You cannot use -4 and -A at the same time\n"); return EX_USAGE; } g_sizeopt = -100; g_grab_keyboard = False; } if (!username_option) { pw = getpwuid(getuid()); if ((pw == NULL) || (pw->pw_name == NULL)) { error("could not determine username, use -u\n"); return EX_OSERR; } /* +1 for trailing \0 */ int pwlen = strlen(pw->pw_name) + 1; g_username = (char *) xmalloc(pwlen); STRNCPY(g_username, pw->pw_name, pwlen); } #ifdef HAVE_ICONV if (g_codepage[0] == 0) { if (setlocale(LC_CTYPE, "")) { STRNCPY(g_codepage, nl_langinfo(CODESET), sizeof(g_codepage)); } else { STRNCPY(g_codepage, DEFAULT_CODEPAGE, sizeof(g_codepage)); } } #endif if (g_hostname[0] == 0) { if (gethostname(fullhostname, sizeof(fullhostname)) == -1) { error("could not determine local hostname, use -n\n"); return EX_OSERR; } p = strchr(fullhostname, '.'); if (p != NULL) *p = 0; STRNCPY(g_hostname, fullhostname, sizeof(g_hostname)); } if (g_keymapname[0] == 0) { if (locale && xkeymap_from_locale(locale)) { fprintf(stderr, "Autoselected keyboard map %s\n", g_keymapname); } else { STRNCPY(g_keymapname, "en-us", sizeof(g_keymapname)); } } if (locale) xfree(locale); if (prompt_password && read_password(g_password, sizeof(g_password))) flags |= RDP_INFO_AUTOLOGON; if (g_title[0] == 0) { strcpy(g_title, "rdesktop - "); strncat(g_title, server, sizeof(g_title) - sizeof("rdesktop - ")); } #ifdef RDP2VNC rdp2vnc_connect(server, flags, domain, g_password, shell, directory); return EX_OK; #else /* Only startup ctrl functionality is seamless are used for now. */ if (g_use_ctrl && g_seamless_rdp) { if (ctrl_init(server, domain, g_username) < 0) { error("Failed to initialize ctrl mode."); exit(1); } if (ctrl_is_slave()) { fprintf(stdout, "rdesktop in slave mode sending command to master process.\n"); if (g_seamless_spawn_cmd[0]) return ctrl_send_command("seamless.spawn", g_seamless_spawn_cmd); fprintf(stdout, "No command specified to be spawn in seamless mode.\n"); return EX_USAGE; } } if (!ui_init()) return EX_OSERR; #ifdef WITH_RDPSND if (!rdpsnd_init(rdpsnd_optarg)) warning("Initializing sound-support failed!\n"); #endif if (g_lspci_enabled) lspci_init(); rdpdr_init(); g_reconnect_loop = False; while (1) { rdesktop_reset_state(); if (g_redirect) { STRNCPY(domain, g_redirect_domain, sizeof(domain)); xfree(g_username); g_username = (char *) xmalloc(strlen(g_redirect_username) + 1); STRNCPY(g_username, g_redirect_username, strlen(g_redirect_username) + 1); STRNCPY(server, g_redirect_server, sizeof(server)); flags |= RDP_INFO_AUTOLOGON; fprintf(stderr, "Redirected to %s@%s session %d.\n", g_redirect_username, g_redirect_server, g_redirect_session_id); /* A redirect on SSL from a 2003 WTS will result in a 'connection reset by peer' and therefor we just clear this error before we connect to redirected server. */ g_network_error = False; g_redirect = False; } ui_init_connection(); if (!rdp_connect (server, flags, domain, g_password, shell, directory, g_reconnect_loop)) { g_network_error = False; if (g_reconnect_loop == False) return EX_PROTOCOL; /* check if auto reconnect cookie has timed out */ if (time(NULL) - g_reconnect_random_ts > RECONNECT_TIMEOUT) { fprintf(stderr, "Tried to reconnect for %d minutes, giving up.\n", RECONNECT_TIMEOUT / 60); return EX_PROTOCOL; } sleep(4); continue; } if (g_redirect) { rdp_disconnect(); continue; } /* By setting encryption to False here, we have an encrypted login packet but unencrypted transfer of other packets */ if (!g_packet_encryption) g_encryption_initial = g_encryption = False; DEBUG(("Connection successful.\n")); rd_create_ui(); tcp_run_ui(True); deactivated = False; g_reconnect_loop = False; rdp_main_loop(&deactivated, &ext_disc_reason); tcp_run_ui(False); DEBUG(("Disconnecting...\n")); rdp_disconnect(); if (g_redirect) continue; /* handle network error and start autoreconnect */ if (g_network_error && !deactivated) { fprintf(stderr, "Disconnected due to network error, retrying to reconnect for %d minutes.\n", RECONNECT_TIMEOUT / 60); g_network_error = False; g_reconnect_loop = True; continue; } ui_seamless_end(); ui_destroy_window(); /* Enter a reconnect loop if we have a pending resize request */ if (g_pending_resize) { g_pending_resize = False; g_reconnect_loop = True; continue; } break; } cache_save_state(); ui_deinit(); if (g_user_quit) return EXRD_WINDOW_CLOSED; return handle_disconnect_reason(deactivated, ext_disc_reason); #endif if (g_redirect_username) xfree(g_redirect_username); xfree(g_username); }
static int rhizome_server_parse_http_request(rhizome_http_request *r) { /* Switching to writing, so update the call-back */ r->alarm.poll.events=POLLOUT; watch(&r->alarm); // Start building up a response. r->request_type = 0; // Parse the HTTP "GET" line. char *path = NULL; size_t pathlen = 0; if (str_startswith(r->request, "GET ", &path)) { char *p; // This loop is guaranteed to terminate before the end of the buffer, because we know that the // buffer contains at least "\n\n" and maybe "\r\n\r\n" at the end of the header block. for (p = path; !isspace(*p); ++p) ; pathlen = p - path; if ( str_startswith(p, " HTTP/1.", &p) && (str_startswith(p, "0", &p) || str_startswith(p, "1", &p)) && (str_startswith(p, "\r\n", &p) || str_startswith(p, "\n", &p)) ) path[pathlen] = '\0'; else path = NULL; } if (path) { char *id = NULL; INFOF("RHIZOME HTTP SERVER, GET %s", alloca_toprint(1024, path, pathlen)); if (strcmp(path, "/favicon.ico") == 0) { r->request_type = RHIZOME_HTTP_REQUEST_FAVICON; rhizome_server_http_response_header(r, 200, "image/vnd.microsoft.icon", favicon_len); } else if (strcmp(path, "/rhizome/groups") == 0) { /* Return the list of known groups */ rhizome_server_sql_query_http_response(r, "id", "groups", "from groups", 32, 1); } else if (strcmp(path, "/rhizome/files") == 0) { /* Return the list of known files */ rhizome_server_sql_query_http_response(r, "id", "files", "from files", 32, 1); } else if (strcmp(path, "/rhizome/bars") == 0) { /* Return the list of known BARs */ rhizome_server_sql_query_http_response(r, "bar", "manifests", "from manifests", 32, 0); } else if (str_startswith(path, "/rhizome/file/", &id)) { /* Stream the specified payload */ if (!rhizome_str_is_file_hash(id)) { rhizome_server_simple_http_response(r, 400, "<html><h1>Invalid payload ID</h1></html>\r\n"); } else { // TODO: Check for Range: header and return 206 if returning partial content str_toupper_inplace(id); long long rowid = -1; sqlite_exec_int64(&rowid, "select rowid from files where id='%s';", id); if (rowid >= 0 && sqlite3_blob_open(rhizome_db, "main", "files", "data", rowid, 0, &r->blob) != SQLITE_OK) rowid = -1; if (rowid == -1) { rhizome_server_simple_http_response(r, 404, "<html><h1>Payload not found</h1></html>\r\n"); } else { r->source_index = 0; r->blob_end = sqlite3_blob_bytes(r->blob); rhizome_server_http_response_header(r, 200, "application/binary", r->blob_end - r->source_index); r->request_type |= RHIZOME_HTTP_REQUEST_BLOB; } } } else if (str_startswith(path, "/rhizome/manifest/", &id)) { // TODO: Stream the specified manifest rhizome_server_simple_http_response(r, 500, "<html><h1>Not implemented</h1></html>\r\n"); } else { rhizome_server_simple_http_response(r, 404, "<html><h1>Not found</h1></html>\r\n"); } } else { if (debug & DEBUG_RHIZOME_TX) DEBUGF("Received malformed HTTP request: %s", alloca_toprint(120, (const char *)r->request, r->request_length)); rhizome_server_simple_http_response(r, 400, "<html><h1>Malformed request</h1></html>\r\n"); } /* Try sending data immediately. */ rhizome_server_http_send_bytes(r); return 0; }
bool hash_command_output(struct mdfour *hash, const char *command, const char *compiler) { #ifdef _WIN32 SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE }; HANDLE pipe_out[2]; PROCESS_INFORMATION pi; STARTUPINFO si; DWORD exitcode; bool cmd = false; char *sh = NULL; char *win32args; char *path; BOOL ret; bool ok; int fd; #else pid_t pid; int pipefd[2]; #endif #ifdef _WIN32 /* trim leading space */ while (isspace(*command)) { command++; } /* add "echo" command */ if (str_startswith(command, "echo")) { command = format("cmd.exe /c \"%s\"", command); cmd = true; } else if (str_startswith(command, "%compiler%") && str_eq(compiler, "echo")) { command = format("cmd.exe /c \"%s%s\"", compiler, command + 10); cmd = true; } else { command = x_strdup(command); } #endif struct args *args = args_init_from_string(command); int i; for (i = 0; i < args->argc; i++) { if (str_eq(args->argv[i], "%compiler%")) { args_set(args, i, compiler); } } cc_log_argv("Executing compiler check command ", args->argv); #ifdef _WIN32 memset(&pi, 0x00, sizeof(pi)); memset(&si, 0x00, sizeof(si)); path = find_executable(args->argv[0], NULL); if (!path) { path = args->argv[0]; } sh = win32getshell(path); if (sh) { path = sh; } si.cb = sizeof(STARTUPINFO); CreatePipe(&pipe_out[0], &pipe_out[1], &sa, 0); SetHandleInformation(pipe_out[0], HANDLE_FLAG_INHERIT, 0); si.hStdOutput = pipe_out[1]; si.hStdError = pipe_out[1]; si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); si.dwFlags = STARTF_USESTDHANDLES; if (!cmd) { win32args = win32argvtos(sh, args->argv); } else { win32args = (char *) command; /* quoted */ } ret = CreateProcess(path, win32args, NULL, NULL, 1, 0, NULL, NULL, &si, &pi); CloseHandle(pipe_out[1]); args_free(args); free(win32args); if (cmd) { free((char *) command); /* original argument was replaced above */ } if (ret == 0) { stats_update(STATS_COMPCHECK); return false; } fd = _open_osfhandle((intptr_t) pipe_out[0], O_BINARY); ok = hash_fd(hash, fd); if (!ok) { cc_log("Error hashing compiler check command output: %s", strerror(errno)); stats_update(STATS_COMPCHECK); } WaitForSingleObject(pi.hProcess, INFINITE); GetExitCodeProcess(pi.hProcess, &exitcode); CloseHandle(pipe_out[0]); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); if (exitcode != 0) { cc_log("Compiler check command returned %d", (int) exitcode); stats_update(STATS_COMPCHECK); return false; } return ok; #else if (pipe(pipefd) == -1) { fatal("pipe failed"); } pid = fork(); if (pid == -1) { fatal("fork failed"); } if (pid == 0) { /* Child. */ close(pipefd[0]); close(0); dup2(pipefd[1], 1); dup2(pipefd[1], 2); _exit(execvp(args->argv[0], args->argv)); return false; /* Never reached. */ } else { /* Parent. */ int status; bool ok; args_free(args); close(pipefd[1]); ok = hash_fd(hash, pipefd[0]); if (!ok) { cc_log("Error hashing compiler check command output: %s", strerror(errno)); stats_update(STATS_COMPCHECK); } close(pipefd[0]); if (waitpid(pid, &status, 0) != pid) { cc_log("waitpid failed"); return false; } if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { cc_log("Compiler check command returned %d", WEXITSTATUS(status)); stats_update(STATS_COMPCHECK); return false; } return ok; } #endif }
/* Client program */ int main(int argc, char *argv[]) { char server[64]; char fullhostname[64]; char domain[16]; char password[64]; char shell[256]; char directory[256]; RD_BOOL prompt_password, deactivated; struct passwd *pw; uint32 flags, ext_disc_reason = 0; char *p; int c; char *locale = NULL; int username_option = 0; RD_BOOL geometry_option = False; int run_count = 0; /* Session Directory support */ RD_BOOL continue_connect = True; /* Session Directory support */ #ifdef WITH_RDPSND char *rdpsnd_optarg = NULL; #endif #ifdef HAVE_LOCALE_H /* Set locale according to environment */ locale = setlocale(LC_ALL, ""); if (locale) { locale = xstrdup(locale); } #endif flags = RDP_LOGON_NORMAL; prompt_password = False; domain[0] = password[0] = shell[0] = directory[0] = 0; g_embed_wnd = 0; g_num_devices = 0; #ifdef RDP2VNC #define VNCOPT "V:Q:" #else #define VNCOPT #endif while ((c = getopt(argc, argv, VNCOPT "Au:L:d:s:c:p:n:k:g:fbBeEmzCDKS:T:NX:a:x:Pr:045h?")) != -1) { switch (c) { #ifdef RDP2VNC case 'V': rfb_port = strtol(optarg, NULL, 10); if (rfb_port < 100) rfb_port += 5900; break; case 'Q': defer_time = strtol(optarg, NULL, 10); if (defer_time < 0) defer_time = 0; break; #endif case 'A': g_seamless_rdp = True; break; case 'u': STRNCPY(g_username, optarg, sizeof(g_username)); username_option = 1; break; case 'L': #ifdef HAVE_ICONV STRNCPY(g_codepage, optarg, sizeof(g_codepage)); #else error("iconv support not available\n"); #endif break; case 'd': STRNCPY(domain, optarg, sizeof(domain)); break; case 's': STRNCPY(shell, optarg, sizeof(shell)); break; case 'c': STRNCPY(directory, optarg, sizeof(directory)); break; case 'p': if ((optarg[0] == '-') && (optarg[1] == 0)) { prompt_password = True; break; } STRNCPY(password, optarg, sizeof(password)); flags |= RDP_LOGON_AUTO; /* try to overwrite argument so it won't appear in ps */ p = optarg; while (*p) *(p++) = 'X'; break; case 'n': STRNCPY(g_hostname, optarg, sizeof(g_hostname)); break; case 'k': STRNCPY(g_keymapname, optarg, sizeof(g_keymapname)); break; case 'g': geometry_option = True; g_fullscreen = False; if (!strcmp(optarg, "workarea")) { g_width = g_height = 0; break; } g_width = strtol(optarg, &p, 10); if (g_width <= 0) { error("invalid geometry\n"); return 1; } if (*p == 'x') g_height = strtol(p + 1, &p, 10); if (g_height <= 0) { error("invalid geometry\n"); return 1; } if (*p == '%') { g_width = -g_width; p++; } if (*p == '+' || *p == '-') { g_pos |= (*p == '-') ? 2 : 1; g_xpos = strtol(p, &p, 10); } if (*p == '+' || *p == '-') { g_pos |= (*p == '-') ? 4 : 1; g_ypos = strtol(p, NULL, 10); } break; case 'f': g_fullscreen = True; break; case 'b': g_bitmap_cache = False; break; case 'B': g_ownbackstore = False; break; case 'e': g_encryption = False; break; case 'E': g_packet_encryption = False; break; case 'm': g_sendmotion = False; break; case 'C': g_owncolmap = True; break; case 'D': g_hide_decorations = True; break; case 'K': g_grab_keyboard = False; break; case 'S': if (!strcmp(optarg, "standard")) { g_win_button_size = 18; break; } g_win_button_size = strtol(optarg, &p, 10); if (*p) { error("invalid button size\n"); return 1; } break; case 'T': STRNCPY(g_title, optarg, sizeof(g_title)); break; case 'N': g_numlock_sync = True; break; case 'X': g_embed_wnd = strtol(optarg, NULL, 0); break; case 'a': g_server_depth = strtol(optarg, NULL, 10); if (g_server_depth != 8 && g_server_depth != 16 && g_server_depth != 15 && g_server_depth != 24 && g_server_depth != 32) { error("Invalid server colour depth.\n"); return 1; } break; case 'z': DEBUG(("rdp compression enabled\n")); flags |= (RDP_LOGON_COMPRESSION | RDP_LOGON_COMPRESSION2); break; case 'x': if (str_startswith(optarg, "m")) /* modem */ { g_rdp5_performanceflags = RDP5_NO_WALLPAPER | RDP5_NO_FULLWINDOWDRAG | RDP5_NO_MENUANIMATIONS | RDP5_NO_THEMING; } else if (str_startswith(optarg, "b")) /* broadband */ { g_rdp5_performanceflags = RDP5_NO_WALLPAPER; } else if (str_startswith(optarg, "l")) /* lan */ { g_rdp5_performanceflags = RDP5_DISABLE_NOTHING; } else { g_rdp5_performanceflags = strtol(optarg, NULL, 16); } break; case 'P': g_bitmap_cache_persist_enable = True; break; case 'r': if (str_startswith(optarg, "sound")) { optarg += 5; if (*optarg == ':') { optarg++; while ((p = next_arg(optarg, ','))) { if (str_startswith(optarg, "remote")) flags |= RDP_LOGON_LEAVE_AUDIO; if (str_startswith(optarg, "local")) #ifdef WITH_RDPSND { rdpsnd_optarg = next_arg(optarg, ':'); g_rdpsnd = True; } #else warning("Not compiled with sound support\n"); #endif if (str_startswith(optarg, "off")) #ifdef WITH_RDPSND g_rdpsnd = False; #else warning("Not compiled with sound support\n"); #endif optarg = p; } } else { #ifdef WITH_RDPSND g_rdpsnd = True; #else warning("Not compiled with sound support\n"); #endif } } else if (str_startswith(optarg, "disk")) { /* -r disk:h:=/mnt/floppy */ disk_enum_devices(&g_num_devices, optarg + 4); } else if (str_startswith(optarg, "comport")) { serial_enum_devices(&g_num_devices, optarg + 7); } else if (str_startswith(optarg, "lspci")) { g_lspci_enabled = True; } else if (str_startswith(optarg, "lptport")) { parallel_enum_devices(&g_num_devices, optarg + 7); } else if (str_startswith(optarg, "printer")) { printer_enum_devices(&g_num_devices, optarg + 7); } else if (str_startswith(optarg, "clientname")) { g_rdpdr_clientname = xmalloc(strlen(optarg + 11) + 1); strcpy(g_rdpdr_clientname, optarg + 11); } else if (str_startswith(optarg, "clipboard")) { optarg += 9; if (*optarg == ':') { optarg++; if (str_startswith(optarg, "off")) g_rdpclip = False; else cliprdr_set_mode(optarg); } else g_rdpclip = True; } else if (strncmp("scard", optarg, 5) == 0) { #ifdef WITH_SCARD scard_enum_devices(&g_num_devices, optarg + 5); #else warning("Not compiled with smartcard support\n"); #endif } else { warning("Unknown -r argument\n\n\tPossible arguments are: comport, disk, lptport, printer, sound, clipboard, scard\n"); } break; case '0': g_console_session = True; break; case '4': g_use_rdp5 = False; break; case '5': g_use_rdp5 = True; break; case 'h': case '?': default: usage(argv[0]); return 1; } } if (argc - optind != 1) { usage(argv[0]); return 1; } STRNCPY(server, argv[optind], sizeof(server)); parse_server_and_port(server); if (g_seamless_rdp) { if (g_win_button_size) { error("You cannot use -S and -A at the same time\n"); return 1; } g_rdp5_performanceflags &= ~RDP5_NO_FULLWINDOWDRAG; if (geometry_option) { error("You cannot use -g and -A at the same time\n"); return 1; } if (g_fullscreen) { error("You cannot use -f and -A at the same time\n"); return 1; } if (g_hide_decorations) { error("You cannot use -D and -A at the same time\n"); return 1; } if (g_embed_wnd) { error("You cannot use -X and -A at the same time\n"); return 1; } if (!g_use_rdp5) { error("You cannot use -4 and -A at the same time\n"); return 1; } g_width = -100; g_grab_keyboard = False; } if (!username_option) { pw = getpwuid(getuid()); if ((pw == NULL) || (pw->pw_name == NULL)) { error("could not determine username, use -u\n"); return 1; } STRNCPY(g_username, pw->pw_name, sizeof(g_username)); } #ifdef HAVE_ICONV if (g_codepage[0] == 0) { if (setlocale(LC_CTYPE, "")) { STRNCPY(g_codepage, nl_langinfo(CODESET), sizeof(g_codepage)); } else { STRNCPY(g_codepage, DEFAULT_CODEPAGE, sizeof(g_codepage)); } } #endif if (g_hostname[0] == 0) { if (gethostname(fullhostname, sizeof(fullhostname)) == -1) { error("could not determine local hostname, use -n\n"); return 1; } p = strchr(fullhostname, '.'); if (p != NULL) *p = 0; STRNCPY(g_hostname, fullhostname, sizeof(g_hostname)); } if (g_keymapname[0] == 0) { if (locale && xkeymap_from_locale(locale)) { fprintf(stderr, "Autoselected keyboard map %s\n", g_keymapname); } else { STRNCPY(g_keymapname, "en-us", sizeof(g_keymapname)); } } if (locale) xfree(locale); if (prompt_password && read_password(password, sizeof(password))) flags |= RDP_LOGON_AUTO; if (g_title[0] == 0) { strcpy(g_title, "rdesktop - "); strncat(g_title, server, sizeof(g_title) - sizeof("rdesktop - ")); } #ifdef RDP2VNC rdp2vnc_connect(server, flags, domain, password, shell, directory); return 0; #else if (!ui_init()) return 1; #ifdef WITH_RDPSND if (g_rdpsnd) { if (!rdpsnd_init(rdpsnd_optarg)) { warning("Initializing sound-support failed!\n"); } } #endif if (g_lspci_enabled) lspci_init(); rdpdr_init(); while (run_count < 2 && continue_connect) /* add support for Session Directory; only reconnect once */ { if (run_count == 0) { if (!rdp_connect(server, flags, domain, password, shell, directory)) return 1; } else if (!rdp_reconnect (server, flags, domain, password, shell, directory, g_redirect_cookie)) return 1; /* By setting encryption to False here, we have an encrypted login packet but unencrypted transfer of other packets */ if (!g_packet_encryption) g_encryption = False; DEBUG(("Connection successful.\n")); memset(password, 0, sizeof(password)); if (run_count == 0) if (!ui_create_window()) continue_connect = False; if (continue_connect) rdp_main_loop(&deactivated, &ext_disc_reason); DEBUG(("Disconnecting...\n")); rdp_disconnect(); if ((g_redirect == True) && (run_count == 0)) /* Support for Session Directory */ { /* reset state of major globals */ rdesktop_reset_state(); STRNCPY(domain, g_redirect_domain, sizeof(domain)); STRNCPY(g_username, g_redirect_username, sizeof(g_username)); STRNCPY(password, g_redirect_password, sizeof(password)); STRNCPY(server, g_redirect_server, sizeof(server)); flags |= RDP_LOGON_AUTO; g_redirect = False; } else { continue_connect = False; ui_destroy_window(); break; } run_count++; } cache_save_state(); ui_deinit(); if (ext_disc_reason >= 2) print_disconnect_reason(ext_disc_reason); if (deactivated) { /* clean disconnect */ return 0; } else { if (ext_disc_reason == exDiscReasonAPIInitiatedDisconnect || ext_disc_reason == exDiscReasonAPIInitiatedLogoff) { /* not so clean disconnect, but nothing to worry about */ return 0; } else { /* return error */ return 2; } } #endif }
/* * Process the compiler options into options suitable for passing to the * preprocessor and the real compiler. The preprocessor options don't include * -E; this is added later. Returns true on success, otherwise false. */ bool armcc_process_args(struct args *orig_args, struct args **preprocessor_args, struct args **compiler_args) { int i; bool found_c_opt = false; bool found_S_opt = false; bool found_pch = false; bool found_fpch_preprocess = false; const char *actual_language; /* Language to actually use. */ const char *input_charset = NULL; struct stat st; /* is the dependency makefile name overridden with --depend? */ bool dependency_filename_specified = false; /* is the dependency makefile target name specified ? */ bool dependency_target_specified = false; char *dep_file = NULL, *dep_dir = NULL; struct args *stripped_args = NULL, *dep_args = NULL; int argc = orig_args->argc; char **argv = orig_args->argv; bool result = true; /* 0: Choose preprocessor type by the file extension. * 1: Use c preprocessor. * 2: Use c++ preprocessor.*/ unsigned force_preprocessor_type = 0; stripped_args = args_init(0, NULL); dep_args = args_init(0, NULL); args_add(stripped_args, argv[0]); for (i = 1; i < argc; i++) { /* The user knows best: just swallow the next arg */ if (str_eq(argv[i], "--ccache-skip")) { i++; if (i == argc) { cc_log("--ccache-skip lacks an argument"); result = false; goto out; } args_add(stripped_args, argv[i]); continue; } /* Special case for -E. */ if (str_eq(argv[i], "-E")) { stats_update(STATS_PREPROCESSING); result = false; goto out; } /* These are always too hard. */ if (compopt_too_hard(argv[i]) || str_startswith(argv[i], "@") || str_startswith(argv[i], "-fdump-")) { cc_log("Compiler option %s is unsupported", argv[i]); stats_update(STATS_UNSUPPORTED); result = false; goto out; } /* These are too hard in direct mode. */ if (enable_direct) { if (compopt_too_hard_for_direct_mode(argv[i])) { cc_log("Unsupported compiler option for direct mode: %s", argv[i]); enable_direct = false; } } /* we must have -c */ if (str_eq(argv[i], "-c")) { args_add(stripped_args, argv[i]); found_c_opt = true; continue; } /* -S changes the default extension */ if (str_eq(argv[i], "-S")) { args_add(stripped_args, argv[i]); found_S_opt = true; continue; } /* we need to work out where the output was meant to go */ if (str_eq(argv[i], "-o")) { if (i == argc-1) { cc_log("Missing argument to %s", argv[i]); stats_update(STATS_ARGS); result = false; goto out; } output_obj = argv[i+1]; i++; continue; } /* alternate form of -o, with no space */ if (str_startswith(argv[i], "-o")) { output_obj = &argv[i][2]; continue; } /* If multiple source type options are there, the armcc will use the last one. */ if (str_eq(argv[i], "--cpp")) { force_preprocessor_type = 2; continue; } else if (str_eq(argv[i], "--c90") || str_eq(argv[i], "--c99")) { force_preprocessor_type = 1; continue; } if (str_eq(argv[i], "--md")) { generating_dependencies = true; continue; } /* The rvct started supporting --depend_target from 4.0. * And there is a bug when using -E and --depend together with rvct which version is earlier than 4.0_697. * That is too hard to support "--depend" for the earlier version of rvct.*/ if (str_startswith(argv[i], "--depend_dir")) { /* We just concat the dir and the filename and pass the result * to --depend. */ if (i >= argc - 1) { cc_log("Missing argument to %s", argv[i]); stats_update(STATS_ARGS); result = false; goto out; } dep_dir= x_strdup(argv[i+1]); i++; continue; } else if (str_startswith(argv[i], "--depend_target")) { if (i >= argc - 1) { cc_log("Missing argument to %s", argv[i]); stats_update(STATS_ARGS); result = false; goto out; } dependency_target_specified = true; args_add(dep_args, argv[i]); args_add(dep_args, argv[i+1]); i++; continue; } else if (str_startswith(argv[i], "--depend")) { dependency_filename_specified = true; generating_dependencies = true; if (i >= argc - 1) { cc_log("Missing argument to %s", argv[i]); stats_update(STATS_ARGS); result = false; goto out; } dep_file = x_strdup(argv[i + 1]); i++; continue; } /* * Options taking an argument that that we may want to rewrite * to relative paths to get better hit rate. A secondary effect * is that paths in the standard error output produced by the * compiler will be normalized. */ if (compopt_takes_path(argv[i])) { char *relpath; char *pchpath; if (i == argc-1) { cc_log("Missing argument to %s", argv[i]); stats_update(STATS_ARGS); result = false; goto out; } args_add(stripped_args, argv[i]); relpath = make_relative_path(x_strdup(argv[i+1])); args_add(stripped_args, relpath); /* Try to be smart about detecting precompiled headers */ pchpath = format("%s.gch", argv[i+1]); if (stat(pchpath, &st) == 0) { cc_log("Detected use of precompiled header: %s", pchpath); found_pch = true; } free(pchpath); free(relpath); i++; continue; } /* Same as above but options with concatenated argument. */ if (compopt_short(compopt_takes_path, argv[i])) { char *relpath; char *option; relpath = make_relative_path(x_strdup(argv[i] + 2)); option = format("-%c%s", argv[i][1], relpath); args_add(stripped_args, option); free(relpath); free(option); continue; } /* options that take an argument */ if (compopt_takes_arg(argv[i])) { if (i == argc-1) { cc_log("Missing argument to %s", argv[i]); stats_update(STATS_ARGS); result = false; goto out; } args_add(stripped_args, argv[i]); args_add(stripped_args, argv[i+1]); i++; continue; } /* other options */ if (argv[i][0] == '-') { args_add(stripped_args, argv[i]); continue; } /* if an argument isn't a plain file then assume its an option, not an input file. This allows us to cope better with unusual compiler options */ if (stat(argv[i], &st) != 0 || !S_ISREG(st.st_mode)) { cc_log("%s is not a regular file, not considering as input file", argv[i]); args_add(stripped_args, argv[i]); continue; } if (input_file) { if (language_for_file(argv[i])) { cc_log("Multiple input files: %s and %s", input_file, argv[i]); stats_update(STATS_MULTIPLE); } else if (!found_c_opt) { cc_log("Called for link with %s", argv[i]); if (strstr(argv[i], "conftest.")) { stats_update(STATS_CONFTEST); } else { stats_update(STATS_LINK); } } else { cc_log("Unsupported source extension: %s", argv[i]); stats_update(STATS_SOURCELANG); } result = false; goto out; } /* Rewrite to relative to increase hit rate. */ input_file = make_relative_path(x_strdup(argv[i])); } if (!input_file) { cc_log("No input file found"); stats_update(STATS_NOINPUT); result = false; goto out; } if (found_pch || found_fpch_preprocess) { using_precompiled_header = true; if (!(sloppiness & SLOPPY_TIME_MACROS)) { cc_log("You have to specify \"time_macros\" sloppiness when using" " precompiled headers to get direct hits"); cc_log("Disabling direct mode"); stats_update(STATS_CANTUSEPCH); result = false; goto out; } } if(force_preprocessor_type == 0) { actual_language = language_for_file(input_file); } else if(force_preprocessor_type == 2) { actual_language = "c++"; } else { actual_language = "c"; } output_is_precompiled_header = actual_language && strstr(actual_language, "-header") != NULL; if (!found_c_opt && !output_is_precompiled_header) { cc_log("No -c option found"); /* I find that having a separate statistic for autoconf tests is useful, as they are the dominant form of "called for link" in many cases */ if (strstr(input_file, "conftest.")) { stats_update(STATS_CONFTEST); } else { stats_update(STATS_LINK); } result = false; goto out; } if (!actual_language) { cc_log("Unsupported source extension: %s", input_file); stats_update(STATS_SOURCELANG); result = false; goto out; } direct_i_file = language_is_preprocessed(actual_language); if (output_is_precompiled_header) { /* It doesn't work to create the .gch from preprocessed source. */ cc_log("Creating precompiled header; not compiling preprocessed code"); compile_preprocessed_source_code = false; } /* don't try to second guess the compilers heuristics for stdout handling */ if (output_obj && str_eq(output_obj, "-")) { stats_update(STATS_OUTSTDOUT); cc_log("Output file is -"); result = false; goto out; } if (!output_obj) { if (output_is_precompiled_header) { output_obj = format("%s.gch", input_file); } else { char *p; output_obj = x_strdup(input_file); if ((p = strrchr(output_obj, '/'))) { output_obj = p+1; } p = strrchr(output_obj, '.'); if (!p || !p[1]) { cc_log("Badly formed object filename"); stats_update(STATS_ARGS); result = false; goto out; } p[1] = found_S_opt ? 's' : 'o'; p[2] = 0; } } /* cope with -o /dev/null */ if (!str_eq(output_obj,"/dev/null") && stat(output_obj, &st) == 0 && !S_ISREG(st.st_mode)) { cc_log("Not a regular file: %s", output_obj); stats_update(STATS_DEVICE); result = false; goto out; } /* * Some options shouldn't be passed to the real compiler when it compiles * preprocessed code: * * -finput-charset=XXX (otherwise conversion happens twice) * -x XXX (otherwise the wrong language is selected) */ *preprocessor_args = args_copy(stripped_args); if (input_charset) { args_add(*preprocessor_args, input_charset); } if (found_pch) { args_add(*preprocessor_args, "-fpch-preprocess"); } /* * Add flags for dependency generation only to the preprocessor command line. */ if (generating_dependencies) { char *dep_path; if(!dependency_filename_specified) { char *base_name; base_name = remove_extension(output_obj); dep_file = format("%s.d", base_name); free(base_name); } if (!dependency_target_specified) { args_add(dep_args, "--depend_target"); args_add(dep_args, output_obj); } free(output_dep); if(dep_dir) { #ifdef _WIN32 dep_path = make_relative_path(format("%s\\%s", dep_dir, dep_file)); #else dep_path = make_relative_path(format("%s/%s", dep_dir, dep_file)); #endif } else { dep_path = x_strdup(dep_file); } args_add(dep_args, "--depend"); args_add(dep_args, dep_path); /* dep_path will be free in make_relative_path */ output_dep = make_relative_path(x_strdup(dep_path)); } if (compile_preprocessed_source_code) { *compiler_args = args_copy(stripped_args); } else { *compiler_args = args_copy(*preprocessor_args); } i_extension = getenv("CCACHE_EXTENSION"); if (!i_extension) { const char *p_language = p_language_for_language(actual_language); i_extension = extension_for_language(p_language) + 1; } /* Patch for preprocessed file extension for armcc 3.1. * armcc 3.1 cannot recognize "i" or "ii" as the preprocessed source file * without --compile_all_input. */ args_add(*compiler_args, "--compile_all_input"); if (str_eq(i_extension, "ii")) { args_add(*compiler_args, "--cpp"); } /* * Only pass dependency arguments to the preprocesor since Intel's C++ * compiler doesn't produce a correct .d file when compiling preprocessed * source. */ args_extend(*preprocessor_args, dep_args); out: free(dep_file); free(dep_dir); args_free(stripped_args); args_free(dep_args); return result; }
/* * Process the compiler options into options suitable for passing to the * preprocessor and the real compiler. The preprocessor options don't include * -E; this is added later. Returns true on success, otherwise false. */ bool c166_process_args(struct args *orig_args, struct args **preprocessor_args, struct args **compiler_args) { int i; bool found_c_opt = false; bool found_S_opt = false; bool found_H_opt = false; /* 0: Choose preprocessor type by the file extension. * 1: Use c preprocessor. * 2: Use c++ preprocessor.*/ unsigned force_preprocessor_type = 0; const char *actual_language; /* Language to actually use. */ struct stat st; /* is the dependency makefile name overridden with -MF? */ bool dependency_filename_specified = false; /* is the dependency makefile target name specified with -MT or -MQ? */ bool dependency_target_specified = false; struct args *stripped_args = NULL, *dep_args = NULL, *h_args; int argc = orig_args->argc; char **argv = orig_args->argv; bool result = true; stripped_args = args_init(0, NULL); dep_args = args_init(0, NULL); h_args = args_init(0, NULL); args_add(stripped_args, argv[0]); for (i = 1; i < argc; i++) { /* The user knows best: just swallow the next arg */ if (str_eq(argv[i], "--ccache-skip")) { i++; if (i == argc) { cc_log("--ccache-skip lacks an argument"); result = false; goto out; } args_add(stripped_args, argv[i]); continue; } /* Special case for -E. */ if (str_eq(argv[i], "-E")) { stats_update(STATS_PREPROCESSING); result = false; goto out; } /* These are always too hard. */ if (compopt_too_hard(argv[i])) { cc_log("Compiler option %s is unsupported", argv[i]); stats_update(STATS_UNSUPPORTED); result = false; goto out; } /* These are too hard in direct mode. */ if (enable_direct) { if (compopt_too_hard_for_direct_mode(argv[i])) { cc_log("Unsupported compiler option for direct mode: %s", argv[i]); enable_direct = false; } } /* we must have -c */ if (str_eq(argv[i], "-c")) { args_add(stripped_args, argv[i]); found_c_opt = true; continue; } /* -S changes the default extension */ /* TODO: Check this -S out! if (str_eq(argv[i], "-S")) { args_add(stripped_args, argv[i]); found_S_opt = true; continue; } */ /* we need to work out where the output was meant to go */ if (str_eq(argv[i], "-o")) { if (i == argc-1) { cc_log("Missing argument to %s", argv[i]); stats_update(STATS_ARGS); result = false; goto out; } output_obj = argv[i+1]; i++; continue; } /* alternate form of -o, with no space */ if (str_startswith(argv[i], "-o")) { output_obj = &argv[i][2]; continue; } /* debugging is handled specially, so that we know if we can strip line number info */ if (str_startswith(argv[i], "-g")) { args_add(stripped_args, argv[i]); if (enable_unify) { cc_log("%s used; disabling unify mode", argv[i]); enable_unify = false; } continue; } if (str_startswith(argv[i], "-H")) { cc_log("Detected -H %s", argv[i]); args_add(h_args, argv[i]); found_H_opt = true; continue; } /* * Options taking an argument that that we may want to rewrite * to relative paths to get better hit rate. A secondary effect * is that paths in the standard error output produced by the * compiler will be normalized. */ if (compopt_takes_path(argv[i])) { char *relpath; if (i == argc-1) { cc_log("Missing argument to %s", argv[i]); stats_update(STATS_ARGS); result = false; goto out; } args_add(stripped_args, argv[i]); relpath = make_relative_path(x_strdup(argv[i+1])); args_add(stripped_args, relpath); free(relpath); i++; continue; } /* Same as above but options with concatenated argument. */ if (compopt_short(compopt_takes_path, argv[i])) { char *relpath; char *option; relpath = make_relative_path(x_strdup(argv[i] + 2)); option = format("-%c%s", argv[i][1], relpath); args_add(stripped_args, option); free(relpath); free(option); continue; } /* options that take an argument */ if (compopt_takes_arg(argv[i])) { if (i == argc-1) { cc_log("Missing argument to %s", argv[i]); stats_update(STATS_ARGS); result = false; goto out; } args_add(stripped_args, argv[i]); args_add(stripped_args, argv[i+1]); i++; continue; } if (str_eq(argv[i], "-c++")) { force_preprocessor_type = 2; args_add(stripped_args, argv[i]); continue; } if (str_eq(argv[i], "-noc++")) { force_preprocessor_type = 1; args_add(stripped_args, argv[i]); continue; } /* other options */ if (argv[i][0] == '-') { args_add(stripped_args, argv[i]); continue; } /* if an argument isn't a plain file then assume its an option, not an input file. This allows us to cope better with unusual compiler options */ if (stat(argv[i], &st) != 0 || !S_ISREG(st.st_mode)) { cc_log("%s is not a regular file, not considering as input file", argv[i]); args_add(stripped_args, argv[i]); continue; } if (input_file) { if (language_for_file(argv[i])) { cc_log("Multiple input files: %s and %s", input_file, argv[i]); stats_update(STATS_MULTIPLE); } else if (!found_c_opt) { cc_log("Called for link with %s", argv[i]); if (strstr(argv[i], "conftest.")) { stats_update(STATS_CONFTEST); } else { stats_update(STATS_LINK); } } else { cc_log("Unsupported source extension: %s", argv[i]); stats_update(STATS_SOURCELANG); } result = false; goto out; } /* Rewrite to relative to increase hit rate. */ input_file = make_relative_path(x_strdup(argv[i])); } if (!input_file) { cc_log("No input file found"); stats_update(STATS_NOINPUT); result = false; goto out; } if(force_preprocessor_type == 0) { actual_language = language_for_file(input_file); } else if(force_preprocessor_type == 2) { actual_language = "c++"; } else { actual_language = "c"; } output_is_precompiled_header = actual_language && strstr(actual_language, "-header") != NULL; if (!found_c_opt && !output_is_precompiled_header) { cc_log("No -c option found"); /* I find that having a separate statistic for autoconf tests is useful, as they are the dominant form of "called for link" in many cases */ if (strstr(input_file, "conftest.")) { stats_update(STATS_CONFTEST); } else { stats_update(STATS_LINK); } result = false; goto out; } if (!actual_language) { cc_log("Unsupported source extension: %s", input_file); stats_update(STATS_SOURCELANG); result = false; goto out; } direct_i_file = language_is_preprocessed(actual_language); if (output_is_precompiled_header) { /* It doesn't work to create the .gch from preprocessed source. */ cc_log("Creating precompiled header; not compiling preprocessed code"); compile_preprocessed_source_code = false; } i_extension = getenv("CCACHE_EXTENSION"); if (!i_extension) { const char *p_language = p_language_for_language(actual_language); if(str_eq(p_language, "c++-cpp-output")) { /* Dirty fix for preprocessed file extension for cc166. * The cp166 cannot handle cpp files with extension ii.*/ i_extension = "ii.cpp"; } else { i_extension = extension_for_language(p_language) + 1; } } /* don't try to second guess the compilers heuristics for stdout handling */ if (output_obj && str_eq(output_obj, "-")) { stats_update(STATS_OUTSTDOUT); cc_log("Output file is -"); result = false; goto out; } if (!output_obj) { if (output_is_precompiled_header) { output_obj = format("%s.gch", input_file); } else { char *p; output_obj = x_strdup(input_file); if ((p = strrchr(output_obj, '/'))) { output_obj = p+1; } p = strrchr(output_obj, '.'); if (!p || !p[1]) { cc_log("Badly formed object filename"); stats_update(STATS_ARGS); result = false; goto out; } *p = 0; p = output_obj; if(found_S_opt) { output_obj = format("%s.s", p); } else { /*The default extension of object file is obj for c166.*/ output_obj = format("%s.obj", p); } free(p); } } /* cope with -o /dev/null */ if (!str_eq(output_obj,"/dev/null") && stat(output_obj, &st) == 0 && !S_ISREG(st.st_mode)) { cc_log("Not a regular file: %s", output_obj); stats_update(STATS_DEVICE); result = false; goto out; } /* * Some options shouldn't be passed to the real compiler when it compiles * preprocessed code: */ *preprocessor_args = args_copy(stripped_args); /* Args with -H has been already preprocessed. * If it passed to the compiler again, some type redefined error will pop up.*/ if (found_H_opt) { args_extend(*preprocessor_args, h_args); } /* * Add flags for dependency generation only to the preprocessor command line. */ if (generating_dependencies) { if (!dependency_filename_specified) { char *default_depfile_name; char *base_name; base_name = remove_extension(output_obj); default_depfile_name = format("%s.d", base_name); free(base_name); args_add(dep_args, "-MF"); args_add(dep_args, default_depfile_name); output_dep = make_relative_path(x_strdup(default_depfile_name)); } if (!dependency_target_specified) { args_add(dep_args, "-MQ"); args_add(dep_args, output_obj); } } if (compile_preprocessed_source_code) { *compiler_args = args_copy(stripped_args); } else { *compiler_args = args_copy(*preprocessor_args); } /* Due to bugs or cc166 v8.6r3, the behaviours of c/c++ preprocessor * are quite different. * When using cpp preprocessor, the output will be directly send to stdout like gcc. * When using c preprocessor, the output will be written to filename.i even without "-o".*/ if(str_eq(actual_language, "c")) { #ifdef _WIN32 #error Never test this in Windows. #else args_add(*preprocessor_args, "-o/dev/stdout"); #endif } /* * Only pass dependency arguments to the preprocesor since Intel's C++ * compiler doesn't produce a correct .d file when compiling preprocessed * source. */ args_extend(*preprocessor_args, dep_args); out: args_free(stripped_args); args_free(dep_args); args_free(h_args); return result; }
/* returns 0 = done, ok. 1 = not done yet, -1 = error */ static int __netio_http_parse_data(netio_http_conn_t* conn, char *data, int datalen) { /* collect data. */ if (!conn->buf || (conn->buf_len - conn->data_len < datalen)) { int ns = conn->buf_len + datalen + 1024; char *tmp = 0; ASSERT_TRUE(tmp = mallocz(ns+1), err); if (conn->buf) memcpy(tmp, conn->buf, conn->data_len); freez(conn->buf); conn->buf = tmp; conn->buf_len = ns; } if (datalen > 0) { memcpy(conn->buf + conn->data_len, data, datalen); conn->data_len += datalen; } /* check if we have the header, parse url & datalen (if present) */ if (!conn->header_got && strstr(conn->buf, "\r\n\r\n")) { char *line = conn->buf, *le; conn->header_got = 1; conn->header_len = strstr(conn->buf, "\r\n\r\n") - conn->buf + 4; do { le = strstr(line, "\r\n"); if (le == line) break; if (str_startswith(line, "POST") || str_startswith(line, "GET") || str_startswith(line, "OPTIONS") || str_startswith(line, "HEAD") || str_startswith(line, "PUT") || str_startswith(line, "DELETE") || str_startswith(line, "TRACE") || str_startswith(line, "CONNECT")) { /* requests! */ char *tmple; /* store method */ if ((tmple = strchr(line, ' '))) { char *t2; tmple++; freez(conn->url); freez(conn->http_version); if (le) { t2 = le; while ((t2 > tmple) && *t2 != ' ') t2--; } else t2 = strrchr(tmple, ' '); if (t2) { conn->url = strndup(tmple, t2-tmple); conn->http_version = trim(strndup(t2, le-t2)); } else { conn->url = strndup(tmple, le-tmple); } freez(conn->method); conn->method = strndup(line, tmple-line); trim(conn->method); trim(conn->url); } } else if (str_startswith(line, "HTTP")) { /* for responses! */ freez(conn->resp_code_line); conn->resp_code_line = trim(strndup(line, le-line)); if (strchr(line, ' ')) conn->resp_code = atoi(strchr(line, ' ')+1); } else { /* generic parameter */ char *tmple = strchr(line, ':'); if (str_startswith(line, "Content-Length: ")) { conn->content_len = atoi(strchr(line, ' ') + 1); } if (tmple) { char *val = strndup(tmple+1, le-tmple+1); char *key = strndup(line, tmple-line); netio_http_set_header(conn, key, val); freez(val); freez(key); } } if (le) line = le+2; } while (le); } /* process data.. */ if (conn->header_got && ((conn->content_len == -1 && datalen < 1) || (conn->content_len != -1 && (conn->content_len <= (conn->data_len - conn->header_len))))) { if (conn->content_len == -1) { conn->content_len = conn->data_len - conn->header_len; } if (conn->method) { LOG_DEBUG("Got total %d bytes, %d bytes data for %s on http\n", conn->data_len, conn->content_len, conn->url); /* treat multipart & 'normal' posts differently */ if (!strcmp(conn->method, "POST") && str_startswith(netio_http_get_header(conn, "Content-Type"), "multipart")) { char *bound, *ps, *pe; bound = strstr_after(netio_http_get_header(conn, "Content-Type"), "boundary="); /* go through parts one-by-one, parsing name & data */ if (bound) { ps = memmem_after(&conn->buf[conn->header_len], conn->data_len - conn->header_len, bound, strlen(bound)); while (ps) { char *tmp, *name, *tmp2 = 0; pe = (char*)memmem(ps, conn->data_len - (ps-conn->buf), bound, strlen(bound)); if (!pe) { pe = conn->buf + conn->data_len; tmp = 0; } else tmp = pe + strlen(bound); if ((name = strstr(ps, "Content-Disposition: "))) tmp2 = strstr(name, "\r\n"); ps = strstr_after(ps, "\r\n\r\n"); if (ps && name && tmp2) { tmp2[0] = 0; if ((name = strstr_after(name, "name=\"")) && (tmp2 = strchr(name, '"'))) { int datalen = pe-ps-4; ASSERT_ZERO(netio_http_conn_set_param(conn, name, tmp2-name, ps, datalen), err); } } ps = tmp; } } } else { int parsedata = conn->header_len; char *ns; ns = &(conn->buf[parsedata]); /* if get, set parsedata to the url's first ?-char */ if (!strcmp(conn->method, "GET")) { char *params = strchr(conn->url, '?'); if (params) { params[0] = 0; ns = params+1; conn->url_extras = strdup(ns); } } while (ns) { char *tmp = 0, *pe = 0; char *ps = strchr(ns, '='); if (ps) { pe = strchr(ps, '&'); if (!pe) { pe = ps + strlen(ps); tmp = 0; } else tmp = pe+1; } if (ps) { char *k = strndup(ns, ps-ns); char *v = strndup(ps+1, pe-ps-1); if (k && v) { ship_urldecode(k); ship_urldecode(v); ASSERT_ZERO(netio_http_conn_set_param(conn, k, strlen(k), v, strlen(v)), err); } freez(k); freez(v); } ns = tmp; } } } /* ..and we're done! */ if (conn->url) { conn->original_url = conn->url; conn->url = strdup(conn->original_url); ship_urldecode(conn->url); } return 0; } else if (datalen < 1) goto err; return 1; err: return -1; }
static void _open_log_file(_log_iterator *it) { assert(it->state == &state_file); if (_log_file != NO_FILE) { if (_log_file_path == NULL) _log_file_path = getenv("SERVALD_LOG_FILE"); if (_log_file_path == NULL && !cf_limbo) { strbuf sbfile = strbuf_local(_log_file_path_buf, sizeof _log_file_path_buf); strbuf_path_join(sbfile, serval_instancepath(), log_file_directory_path(), NULL); _compute_file_start_time(it); if (config.log.file.path[0]) { strbuf_path_join(sbfile, config.log.file.path, NULL); } else { struct tm tm; (void)localtime_r(&it->file_start_time, &tm); strbuf_append_strftime(sbfile, "/serval-%Y%m%d%H%M%S.log", &tm); } if (strbuf_overrun(sbfile)) { _log_file = NO_FILE; _logs_printf_nl(LOG_LEVEL_ERROR, __HERE__, "Cannot form log file name - buffer overrun"); } else { _log_file_start_time = it->file_start_time; _log_file_path = strbuf_str(sbfile); } } if (!_log_file) { if (_log_file_path == NULL) { if (cf_limbo) return; _log_file = NO_FILE; _logs_printf_nl(serverMode ? LOG_LEVEL_WARN : LOG_LEVEL_INFO, __NOWHERE__, "No log file configured"); } else { // Create the new log file. size_t dirsiz = strlen(_log_file_path) + 1; char _dir[dirsiz]; strcpy(_dir, _log_file_path); const char *dir = dirname(_dir); // modifies _dir[] if (mkdirs(dir, 0700) != -1 && (_log_file = fopen(_log_file_path, "a"))) { setlinebuf(_log_file); memset(it->state, 0, sizeof *it->state); // The first line in every log file must be the starting time stamp. (After that, it is up // to _log_update() to insert other mandatory messages in any suitable order.) _log_current_datetime(it, LOG_LEVEL_INFO); _logs_printf_nl(LOG_LEVEL_INFO, __NOWHERE__, "Logging to %s (fd %d)", _log_file_path, fileno(_log_file)); // Update the log symlink to point to the latest log file. strbuf sbsymlink = strbuf_alloca(400); strbuf_path_join(sbsymlink, serval_instancepath(), "serval.log", NULL); if (strbuf_overrun(sbsymlink)) _logs_printf_nl(LOG_LEVEL_ERROR, __HERE__, "Cannot form log symlink name - buffer overrun"); else { const char *f = _log_file_path; const char *s = strbuf_str(sbsymlink); const char *relpath = f; for (; *f && *f == *s; ++f, ++s) if (*f == '/') relpath = f; while (*relpath == '/') ++relpath; while (*s == '/') ++s; if (strchr(s, '/')) relpath = _log_file_path; unlink(strbuf_str(sbsymlink)); if (symlink(relpath, strbuf_str(sbsymlink)) == -1) _logs_printf_nl(LOG_LEVEL_ERROR, __HERE__, "Cannot symlink %s to %s - %s [errno=%d]", strbuf_str(sbsymlink), relpath, strerror(errno), errno); } // Expire old log files. size_t pathsiz = strlen(_log_file_path) + 1; char path[pathsiz]; while (1) { strcpy(path, _log_file_path); const char *base = basename(path); // modifies path[] DIR *d = opendir(dir); if (!d) { _logs_printf_nl(LOG_LEVEL_ERROR, __HERE__, "Cannot expire log files: opendir(%s) - %s [errno=%d]", dir, strerror(errno), errno); break; } struct dirent oldest; memset(&oldest, 0, sizeof oldest); unsigned count = 0; while (1) { struct dirent ent; struct dirent *ep; int err = readdir_r(d, &ent, &ep); if (err) { _logs_printf_nl(LOG_LEVEL_ERROR, __HERE__, "Cannot expire log files: r_readdir(%s) - %s [errno=%d]", dir, strerror(err), err); break; } if (!ep) break; const char *e; if ( str_startswith(ent.d_name, "serval-", &e) && isdigit(e[0]) && isdigit(e[1]) && isdigit(e[2]) && isdigit(e[3]) // YYYY && isdigit(e[4]) && isdigit(e[5]) // MM && isdigit(e[6]) && isdigit(e[7]) // DD && isdigit(e[8]) && isdigit(e[9]) // HH && isdigit(e[10]) && isdigit(e[11]) // MM && isdigit(e[12]) && isdigit(e[13]) // SS && strcmp(&e[14], ".log") == 0 ) { ++count; if ( strcmp(ent.d_name, base) != 0 && (!oldest.d_name[0] || strcmp(ent.d_name, oldest.d_name) < 0) ) oldest = ent; } } closedir(d); if (count <= config.log.file.rotate || !oldest.d_name[0]) break; strbuf b = strbuf_local(path, pathsiz); strbuf_path_join(b, dir, oldest.d_name, NULL); assert(!strbuf_overrun(b)); _logs_printf_nl(LOG_LEVEL_INFO, __NOWHERE__, "Unlink %s", path); unlink(path); } } else { _log_file = NO_FILE; _logs_printf_nl(LOG_LEVEL_WARN, __HERE__, "Cannot create/append %s - %s [errno=%d]", _log_file_path, strerror(errno), errno); } } } } }
/* Handle one line of output from the lspci subprocess */ static BOOL handle_child_line(const char *line, void *data) { const char *val; char buf[1024]; if (str_startswith(line, "Class:")) { val = line + sizeof("Class:"); /* Skip whitespace and second Class: occurance */ val += strspn(val, " \t") + sizeof("Class"); current_device.klass = strtol(val, NULL, 16); } else if (str_startswith(line, "Vendor:")) { val = line + sizeof("Vendor:"); current_device.vendor = strtol(val, NULL, 16); } else if (str_startswith(line, "Device:")) { val = line + sizeof("Device:"); /* Sigh, there are *two* lines tagged as Device:. We are not interested in the domain/bus/slot/func */ if (!strchr(val, ':')) current_device.device = strtol(val, NULL, 16); } else if (str_startswith(line, "SVendor:")) { val = line + sizeof("SVendor:"); current_device.subvendor = strtol(val, NULL, 16); } else if (str_startswith(line, "SDevice:")) { val = line + sizeof("SDevice:"); current_device.subdevice = strtol(val, NULL, 16); } else if (str_startswith(line, "Rev:")) { val = line + sizeof("Rev:"); current_device.revision = strtol(val, NULL, 16); } else if (str_startswith(line, "ProgIf:")) { val = line + sizeof("ProgIf:"); current_device.progif = strtol(val, NULL, 16); } else if (strspn(line, " \t") == strlen(line)) { /* Blank line. Send collected information over channel */ snprintf(buf, sizeof(buf), "%04x,%04x,%04x,%04x,%04x,%02x,%02x\n", current_device.klass, current_device.vendor, current_device.device, current_device.subvendor, current_device.subdevice, current_device.revision, current_device.progif); lspci_send(buf); memset(¤t_device, 0, sizeof(current_device)); } else { warning("lspci: Unrecoqnized line '%s'\n", line); } return True; }
static RD_BOOL xkeymap_read(char *mapname) { FILE *fp; char line[KEYMAP_MAX_LINE_LENGTH]; unsigned int line_num = 0; unsigned int line_length = 0; char *keyname, *p; char *line_rest; uint8 scancode; uint16 modifiers; fp = xkeymap_open(mapname); if (fp == NULL) { error("Failed to open keymap %s\n", mapname); return False; } /* FIXME: More tolerant on white space */ while (fgets(line, sizeof(line), fp) != NULL) { line_num++; /* Replace the \n with \0 */ p = strchr(line, '\n'); if (p != NULL) *p = 0; line_length = strlen(line); /* Completely empty line */ if (strspn(line, " \t\n\r\f\v") == line_length) { continue; } /* Include */ if (str_startswith(line, "include ")) { if (!xkeymap_read(line + sizeof("include ") - 1)) return False; continue; } /* map */ if (str_startswith(line, "map ")) { g_keylayout = strtoul(line + sizeof("map ") - 1, NULL, 16); DEBUG_KBD(("Keylayout 0x%x\n", g_keylayout)); continue; } /* compose */ if (str_startswith(line, "enable_compose")) { DEBUG_KBD(("Enabling compose handling\n")); g_enable_compose = True; continue; } /* sequence */ if (str_startswith(line, "sequence")) { add_sequence(line + sizeof("sequence") - 1, mapname); continue; } /* keyboard_type */ if (str_startswith(line, "keyboard_type ")) { g_keyboard_type = strtol(line + sizeof("keyboard_type ") - 1, NULL, 16); DEBUG_KBD(("keyboard_type 0x%x\n", g_keyboard_type)); continue; } /* keyboard_subtype */ if (str_startswith(line, "keyboard_subtype ")) { g_keyboard_subtype = strtol(line + sizeof("keyboard_subtype ") - 1, NULL, 16); DEBUG_KBD(("keyboard_subtype 0x%x\n", g_keyboard_subtype)); continue; } /* keyboard_functionkeys */ if (str_startswith(line, "keyboard_functionkeys ")) { g_keyboard_functionkeys = strtol(line + sizeof("keyboard_functionkeys ") - 1, NULL, 16); DEBUG_KBD(("keyboard_functionkeys 0x%x\n", g_keyboard_functionkeys)); continue; } /* Comment */ if (line[0] == '#') { continue; } /* Normal line */ keyname = line; p = strchr(line, ' '); if (p == NULL) { error("Bad line %d in keymap %s\n", line_num, mapname); continue; } else { *p = 0; } /* scancode */ p++; scancode = strtol(p, &line_rest, 16); /* flags */ /* FIXME: Should allow case-insensitive flag names. Fix by using lex+yacc... */ modifiers = 0; if (strstr(line_rest, "altgr")) { MASK_ADD_BITS(modifiers, MapAltGrMask); } if (strstr(line_rest, "shift")) { MASK_ADD_BITS(modifiers, MapLeftShiftMask); } if (strstr(line_rest, "numlock")) { MASK_ADD_BITS(modifiers, MapNumLockMask); } if (strstr(line_rest, "localstate")) { MASK_ADD_BITS(modifiers, MapLocalStateMask); } if (strstr(line_rest, "inhibit")) { MASK_ADD_BITS(modifiers, MapInhibitMask); } add_to_keymap(keyname, scancode, modifiers, mapname); if (strstr(line_rest, "addupper")) { /* Automatically add uppercase key, with same modifiers plus shift */ for (p = keyname; *p; p++) *p = toupper((int) *p); MASK_ADD_BITS(modifiers, MapLeftShiftMask); add_to_keymap(keyname, scancode, modifiers, mapname); } } fclose(fp); return True; }
int main() { printf("=============================================\n"); /* * * * * * * * * str.h tests */ char* s = "test string"; // str_new() char* str_new_ = str_new(s); ass(str_new_ != s, "defferent ptr"); ass_eq(str_new_, s); // str_auto() char* str_auto_ = str_auto(str_new_); ass(str_auto_ != str_new_, "different ptr"); ass_eq(str_auto_, str_new_); // str_cat_new() char* str_cat_new_ = str_cat_new(s, " gnirts tset"); ass(str_cat_new_ != s, "different ptr"); ass_eq(str_cat_new_, "test string gnirts tset"); // str_cat_auto() char* str_cat_auto_ = str_cat_auto(str_cat_new_, "!!"); ass(str_cat_auto_ != str_cat_new_, "dif ptr"); ass_eq(str_cat_auto_, "test string gnirts tset!!"); // str_sub_new() char* str_sub_new_ = str_sub_new(s, 0, 4); ass_eq(str_sub_new_, "test"); // str_sub_auto() char* str_sub_auto_ = str_sub_auto(s, 5, 200); // overalocated? ass_eq(str_sub_auto_, "string"); ass_eq(str_sub_auto(s, 5, 5), ""); ass_eq(str_sub_auto(s, 9, 1), ""); // str_slice_new() char* str_slice_new_ = str_slice_new(s, 0, 4); ass_eq(str_slice_new_, "test"); ass_eq(str_slice_new(s, 0, 0), "test string"); ass_eq(str_slice_new(s, 5, 0), "string"); ass_eq(str_slice_new(s,-6, 0), "string"); // str_slice_auto() ass_eq(str_slice_auto(s,-6,-3), "str"); ass_eq(str_slice_auto(s,-1,-2), ""); ass_eq(str_slice_auto(s, 2, 1), ""); ass_eq(str_slice_auto(s, 5, 200), "string"); // overallocated? // str_input_dest() // str_input_new() // str_input_auto() // str_format_dest() // sprintf // str_format_new() // asprintf // str_format_auto() // str_len() // strlen // str_is_alnum() ass(str_is_alnum("abc123")); ass(! str_is_alnum("(@^*^&")); // str_is_alpha() ass(str_is_alpha("abcdEFG")); ass(! str_is_alpha("!@#$@#$")); // str_from_file_new() char* str_from_file_new_ = str_from_file_new("file.test"); ass_eq(str_from_file_new_, "file.test:test\n"); // str_eq() ass(str_eq("abc", "abc")); ass(str_eq("", "")); // str_endswith() ass(str_endswith(s, "string")); ass(str_endswith(s, "ing")); ass(str_endswith(s, "test string")); //ass(str_endswith(s, "")); //hm... //logs(str_slice_auto(s, -1 * strlen(""), 0)); ass(!str_endswith(s, "swing")); ass(!str_endswith(s, " test string")); // str_startswith() ass(str_startswith(s, "test")); ass(str_startswith(s, "test string")); ass(str_startswith(s, "")); }
/** * Parse arguments, extract ones we care about, and also work out * whether it will be possible to distribute this invocation remotely. * * This is a little hard because the cc argument rules are pretty complex, but * the function still ought to be simpler than it already is. * * This code is called on both the client and the server, though they use the * results differently. * * This function makes a copy of the arguments, modified to ensure that * the arguments include '-o <filename>'. This is returned in *ret_newargv. * The copy is dynamically allocated and the caller is responsible for * deallocating it. * * If @p forced_cpp_ext is non NULL, it is filled it with the extension that * is forced by a -x language directive. The caller should not free this * value. * * @returns 0 if it's ok to distribute this compilation, or an error code. **/ int dcc_scan_args(char *argv[], char **input_file, char **output_file, char ***ret_newargv, const char **forced_cpp_ext) { int seen_opt_c = 0, seen_opt_s = 0; int i; char *a, *optx_lang; const char *optx_ext = NULL; int ret; /* allow for -o foo.o */ if ((ret = dcc_copy_argv(argv, ret_newargv, 2)) != 0) return ret; argv = *ret_newargv; /* FIXME: new copy of argv is leaked */ dcc_trace_argv("scanning arguments", argv); #ifdef XCODE_INTEGRATION /* Xcode invokes the distcc client as "distcc --host-info HOST" to gather * info about HOST. When the request is transmitted to the distccd server, * it will see only "--host-info" and no other arguments in argv. */ if (argv[0] && !strcmp(argv[0], "--host-info")) { return 0; } #endif /* XCODE_INTEGRATION */ /* Things like "distcc -c hello.c" with an implied compiler are * handled earlier on by inserting a compiler name. At this * point, argv[0] should always be a compiler name. */ if (argv[0] && argv[0][0] == '-') { rs_log_error("unrecognized distcc option: %s", argv[0]); exit(EXIT_BAD_ARGUMENTS); } *input_file = *output_file = NULL; for (i = 0; (a = argv[i]); i++) { if (a[0] == '-') { if (!strcmp(a, "-E")) { rs_trace("-E call for cpp must be local"); return EXIT_DISTCC_FAILED; } else if (!strcmp(a, "-MD") || !strcmp(a, "-MMD")) { /* These two generate dependencies as a side effect. They * should work with the way we call cpp. */ } else if (!strcmp(a, "-MG") || !strcmp(a, "-MP")) { /* These just modify the behaviour of other -M* options and do * nothing by themselves. */ } else if (!strcmp(a, "-MF") || !strcmp(a, "-MT") || !strcmp(a, "-MQ")) { /* As above but with extra argument. */ i++; } else if (!strncmp(a, "-MF", 3) || !strncmp(a, "-MT", 3) || !strncmp(a, "-MQ", 3)) { /* As above, without extra argument. */ } else if (a[1] == 'M') { /* -M(anything else) causes the preprocessor to produce a list of make-style dependencies on header files, either to stdout or to a local file. It implies -E, so only the preprocessor is run, not the compiler. There would be no point trying to distribute it even if we could. */ rs_trace("%s implies -E (maybe) and must be local", a); return EXIT_DISTCC_FAILED; } else if (!strcmp(a, "-march=native")) { rs_trace("-march=native generates code for local machine; " "must be local"); return EXIT_DISTCC_FAILED; } else if (!strcmp(a, "-mtune=native")) { rs_trace("-mtune=native optimizes for local machine; " "must be local"); return EXIT_DISTCC_FAILED; } else if (str_startswith("-Wa,", a)) { /* Look for assembler options that would produce output * files and must be local. * * Writing listings to stdout could be supported but it might * be hard to parse reliably. */ if (strstr(a, ",-a") || strstr(a, "--MD")) { rs_trace("%s must be local", a); return EXIT_DISTCC_FAILED; } } else if (str_startswith("-specs=", a)) { rs_trace("%s must be local", a); return EXIT_DISTCC_FAILED; } else if (!strcmp(a, "-S")) { seen_opt_s = 1; } else if (!strcmp(a, "-fprofile-arcs") || !strcmp(a, "-ftest-coverage")) { rs_log_info("compiler will emit profile info; must be local"); return EXIT_DISTCC_FAILED; } else if (!strcmp(a, "-frepo")) { rs_log_info("compiler will emit .rpo files; must be local"); return EXIT_DISTCC_FAILED; } else if (!strcmp("-x", a)) { optx_lang = argv[++i]; if (!optx_lang || !strlen(optx_lang)) { rs_log_info("-x requires an argument; running locally"); return EXIT_DISTCC_FAILED; } if (*input_file) { rs_log_info("-x must precede source file; running locally"); return EXIT_DISTCC_FAILED; } if (optx_ext) { rs_log_info("at most one -x supported; running locally"); return EXIT_DISTCC_FAILED; } optx_ext = dcc_optx_ext_lookup(optx_lang); if (!optx_ext) { rs_log_info("unsupported -x language; running locally"); return EXIT_DISTCC_FAILED; } } else if (str_startswith("-x", a)) { /* Handling -xlanguage is possible, but it makes some of the * command rewriting (over in remote.c) much harder, so it * isn't supported at this time. */ rs_log_info("-xlanguage unsupported, use -x language instead; " "running locally"); return EXIT_DISTCC_FAILED; } else if (str_startswith("-dr", a)) { rs_log_info("gcc's debug option %s may write extra files; " "running locally", a); return EXIT_DISTCC_FAILED; } else if (!strcmp(a, "-c")) { seen_opt_c = 1; } else if (!strcmp(a, "-o")) { /* Whatever follows must be the output */ a = argv[++i]; goto GOT_OUTPUT; } else if (str_startswith("-o", a)) { a += 2; /* skip "-o" */ goto GOT_OUTPUT; } } else { if (dcc_is_source(a)) { rs_trace("found input file \"%s\"", a); if (*input_file) { rs_log_info("do we have two inputs? i give up"); return EXIT_DISTCC_FAILED; } *input_file = a; } else if (str_endswith(".o", a)) { GOT_OUTPUT: rs_trace("found object/output file \"%s\"", a); if (*output_file) { rs_log_info("called for link? i give up"); return EXIT_DISTCC_FAILED; } *output_file = a; } } } /* TODO: ccache has the heuristic of ignoring arguments that are not * extant files when looking for the input file; that's possibly * worthwile. Of course we can't do that on the server. */ if (!seen_opt_c && !seen_opt_s) { rs_log_info("compiler apparently called not for compile"); return EXIT_DISTCC_FAILED; } if (!*input_file) { rs_log_info("no visible input file"); return EXIT_DISTCC_FAILED; } if (dcc_source_needs_local(*input_file)) return EXIT_DISTCC_FAILED; if (!*output_file) { /* This is a commandline like "gcc -c hello.c". They want * hello.o, but they don't say so. For example, the Ethereal * makefile does this. * * Note: this doesn't handle a.out, the other implied * filename, but that doesn't matter because it would already * be excluded by not having -c or -S. */ char *ofile; /* -S takes precedence over -c, because it means "stop after * preprocessing" rather than "stop after compilation." */ if (seen_opt_s) { if (dcc_output_from_source(*input_file, ".s", &ofile)) return EXIT_DISTCC_FAILED; } else if (seen_opt_c) { if (dcc_output_from_source(*input_file, ".o", &ofile)) return EXIT_DISTCC_FAILED; } else { rs_log_crit("this can't be happening(%d)!", __LINE__); return EXIT_DISTCC_FAILED; } rs_log_info("no visible output file, going to add \"-o %s\" at end", ofile); dcc_argv_append(argv, strdup("-o")); dcc_argv_append(argv, ofile); *output_file = ofile; } dcc_note_compiled(*input_file, *output_file); if (strcmp(*output_file, "-") == 0) { /* Different compilers may treat "-o -" as either "write to * stdout", or "write to a file called '-'". We can't know, * so we just always run it locally. Hopefully this is a * pretty rare case. */ rs_log_info("output to stdout? running locally"); return EXIT_DISTCC_FAILED; } if (forced_cpp_ext) *forced_cpp_ext = optx_ext; return 0; }