📄 sysdep.c
字号:
} else { return closesocket(s); }}/* read a line, up to lf/crlf terminator, from the socket, and return it. Internal backslashes are removed, unless doubled. If the line ends with an unescaped backslash, replace by newline, and append the next line. If there is an error or end of file before seeing a terminator, NULL is returned. At present, error includes reading a partial line. The returned string is valid until the next call of get_line. This is the internal function implementing the next two; the second arg says whether the first is int or SOCKET.*/static char *_get_line(int fd,int is_socket) { int length,i,j; int offset=0; static char *buffer = NULL; static size_t buffer_size = 0; while ( 1 ) { while ( 1 ) { while (offset+1 >= (int)buffer_size) { /* +1 to keep some space for '\0' */ buffer_size = (buffer_size == 0) ? 1024 : (2 * buffer_size); buffer = realloc(buffer, buffer_size); if (!buffer) { perror("get_line"); exit(-1); } } length = (is_socket ? (skt_reader ? skt_reader((void *)fd,buffer+offset,1) : #ifdef WIN32 recv(fd,buffer+offset,1,0)#else read(fd,buffer+offset,1)#endif ) : read(fd,buffer+offset,1)); if ((length <= 0) || (buffer[offset] == '\n')) break; offset += length; } if ( offset == 0 ) return NULL; if ( length <= 0 ) { fprintf(stderr,"get_line read partial line"); return NULL; } offset += length; buffer[offset] = '\0'; /* now check for newline */ if ( buffer[offset-1] == '\n' ) { if ( buffer[offset-2] == '\r' && buffer[offset-3] == '\\' ) { /* zap the CR */ buffer[offset-2] = '\n'; buffer[offset-1] = '\0'; offset -= 1; /* and go onto next clause */ } if ( buffer[offset-2] == '\\' ) { /* we have to decide whether this is an escaped backslash */ int j = 1,k=offset-3; while ( k >= 0 && buffer[k--] == '\\' ) j++; if ( j & 1 ) { /* odd number, not escaped */ buffer[offset-2] = '\n' ; buffer[--offset] = '\0' ; /* read another line */ } else break; /* return this line */ } else break; /* return this line */ } /* no newline, keep going */ } /* now remove internal backslashes */ for ( i = j = 0; 1; i++, j++ ) { if ( buffer[j] == '\\' ) { j++; } buffer[i] = buffer[j]; if ( !buffer[i] ) break; } return buffer;}char *get_line(SOCKET fd) { /* are we actually being asked to read from stdout? Then read from stdin */ if ( fd == STDOUT_FILENO ) return _get_line(STDIN_FILENO,0); return _get_line((int)fd,1);}char *fd_get_line(int fd) { return _get_line(fd,0);}static int _put_line_aux(int fd, char* line, int length, int is_socket) { int n; if ( is_socket ) { n = skt_writer ? skt_writer((void *)fd,line,length) :#ifdef WIN32 send(fd,line,length,0)#else write(fd,line,length)#endif ; } else { n = write(fd,line,length); } if ( n < length ) { perror("put_line: write failed"); return -1; } return n;}/* write a line (which is assumed to have any terminator included) to the given socket. Return -1 on error, length of line on success. Replace internal newlines by backslash CRLF and write as lines. Double all internal backslashes. Third arg says whether first arg is really an int, or a SOCKET. This is the internal function implemented the next two.*/static int _put_line(int fd,char *line,int is_socket) { int length,n; static char *buffer = NULL; static size_t buf_size = 0; int i,j; /* the backslash/newline escaping can at worst treble the size of the input */ length = strlen(line) + 1; /* include null */ while ( (int)buf_size <= 3*length ) { buf_size = buf_size ? 2*buf_size : 1024; buffer = realloc(buffer,buf_size); } /* FIXME: should retry if only write partial line */ i = j = 0; while ( *line ) { if ( *line == '\\' ) { buffer[i++] = '\\' ; } if ( *line == '\n' && *(line+1) ) { buffer[i++] = '\\' ; buffer[i++] = '\r' ; buffer[i++] = *(line++) ; n = _put_line_aux(fd,buffer,i,is_socket); if ( n < 0 ) { return -1 ; } i = 0; } else { buffer[i++] = *(line++); } } return _put_line_aux(fd,buffer,i,is_socket);}int put_line(SOCKET fd,char *line) { /* are we asked to write to stdout? */ if ( fd == STDOUT_FILENO ) return _put_line(STDOUT_FILENO,line,0); return _put_line((int)fd,line,1);}int fd_put_line(int fd,char *line) { return _put_line(fd,line,0);}/* random integer from 0 to top inclusive */static int seed = 0;unsigned int rand_index(int top) { if ( seed == 0 ) { /* seed the generator */ rand_seed(0); } return (unsigned int)((1.0+top)*rand()/(RAND_MAX+1.0));}/* and seed it */void rand_seed(int s) { if ( s == 0 ) s = time(NULL); srand(seed = s);}/* feed a command to the system to be started in background. No fancy argument processing, just pass to shell or equiv. Return 1 on success, 0 on failure. */int start_background_program(const char *cmd) { char buf[1024];# ifdef WIN32 int res; STARTUPINFO si; PROCESS_INFORMATION pi; strncpy(buf,cmd,1023); buf[1023] = 0; memset((void *)&si,0,sizeof(STARTUPINFO)); si.cb = sizeof(STARTUPINFO); res = CreateProcess(NULL,buf,NULL,NULL, 0,DETACHED_PROCESS,NULL,NULL,&si,&pi); if ( res ) { CloseHandle(pi.hProcess); CloseHandle(pi.hThread); } else { warn("Failed to start process %s",cmd); } return res;# else strcpy(buf,cmd); strcat(buf," &");# endif return ! system(buf);}/* unfortunately we need a slightly more sophisticated one where we can get at the output. This passes out a write handle for the new process's stdin, and a read handle for its stdout */#ifndef WIN32int start_background_program_with_io(const char *cmd,int *childin, int *childout){ int tochild[2], fromchild[2]; int cpid; if ( pipe(tochild) < 0 ) { perror("Unable to create pipe"); return 0; } if ( pipe(fromchild) < 0 ) { perror("Unable to create pipe: %s"); return 0; } cpid = fork(); if ( cpid < 0 ) { perror("Unable to fork: %s"); } if ( cpid ) { /* parent */ close(tochild[0]); close(fromchild[1]); *childin = tochild[1]; *childout = fromchild[0]; return 1; } else { close(tochild[1]); close(fromchild[0]); dup2(tochild[0],0); close(tochild[0]); dup2(fromchild[1],1); close(fromchild[1]); execl("/bin/sh","sh","-c",cmd,NULL); /* what can we do if we get here? Not a lot... */ perror("Exec of child failed"); exit(1); } return 0;}#else/* This windows version is loosely based on the example Creating a Child Process with Redirected Input and Output from the MSDN Library. See that example for all the comments explaining what's going on. In fact it's (a) easier than that, since instead of saving, setting and inheriting handles, we can put the pipes into the startup info of the CreateProcess call. (Thanks to somebody on Usenet, no thanks to Microsoft!); (b) harder, because we need to pass back C-style file descriptors, not Windows handles. Hence the mystic call to _open_osfhandle. */int start_background_program_with_io(const char *cmd,int *childin, int *childout){ int res; char buf[1024]; STARTUPINFO si; PROCESS_INFORMATION pi; SECURITY_ATTRIBUTES sa; HANDLE tochildr, tochildw, tochildw2, fromchildr, fromchildr2, fromchildw; sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.bInheritHandle = TRUE; sa.lpSecurityDescriptor = NULL; if ( ! CreatePipe(&fromchildr,&fromchildw,&sa,0 ) ) { perror("couldn't create pipe"); return 0; } DuplicateHandle(GetCurrentProcess(), fromchildr,GetCurrentProcess(),&fromchildr2,0, FALSE, DUPLICATE_SAME_ACCESS); CloseHandle(fromchildr); if ( ! CreatePipe(&tochildr,&tochildw,&sa,0 ) ) { perror("couldn't create pipe"); return 0; } DuplicateHandle(GetCurrentProcess(), tochildw,GetCurrentProcess(),&tochildw2,0, FALSE, DUPLICATE_SAME_ACCESS); CloseHandle(tochildw); strncpy(buf,cmd,1023); buf[1023] = 0; memset((void *)&si,0,sizeof(STARTUPINFO)); si.cb = sizeof(STARTUPINFO); si.dwFlags = STARTF_USESTDHANDLES; si.hStdOutput = fromchildw; si.hStdInput = tochildr; si.hStdError = 0; res = CreateProcess(NULL,buf,NULL,NULL, TRUE,DETACHED_PROCESS,NULL,NULL,&si,&pi); if ( res ) { CloseHandle(pi.hProcess); CloseHandle(pi.hThread); } else { warn("Failed to start process %s",cmd); } /* I think the mingw has the wrong type for _open_osfhandle ? */ *childin = _open_osfhandle((int)tochildw2,_O_WRONLY); *childout = _open_osfhandle((int)fromchildr2,_O_RDONLY); /* do we, as in unix, close our versions of the handles we don't want? */ if ( 1 ) { CloseHandle(tochildr); CloseHandle(fromchildw); } return res;}#endif/* return a home directory */char *get_homedir(void) { char *p;# ifdef WIN32 static char buf[512]; buf[0] = 0; if ( (p = getenv("HOMEDRIVE")) ) strcpy(buf,p); if ( (p = getenv("HOMEPATH")) ) strcat(buf,p); if ( buf[0] ) return buf; return NULL;# else struct passwd *pw; if ( (p = getenv("HOME")) ) return p; if ( (pw = getpwuid(getuid())) ) return pw->pw_dir; return NULL;# endif}/* stuff for Windows */#ifdef WIN32int gettimeofday(struct timeval *tv, void *tz UNUSED) { long sec, usec; LONGLONG ll; FILETIME ft; GetSystemTimeAsFileTime(&ft); ll = ft.dwHighDateTime; ll <<= 32; ll |= ft.dwLowDateTime; /* this magic number comes from Microsoft's knowledge base ' */ ll -= 116447360000000000; /* 100 nanoseconds since 1970 */ ll /= 10; /* microseconds since 1970 */ sec = (long)(ll / 1000000); usec = (long)(ll - 1000000*((LONGLONG) sec)); if ( tv ) { tv->tv_sec = sec; tv->tv_usec = usec; } return 0;}char *getlogin(void) { static char buf[128]; DWORD len = 128; buf[0] = 0; GetUserName(buf,&len); return buf;} int getpid(void) { return GetCurrentProcessId();}int unlink(const char *f) { return DeleteFile(f); }unsigned int sleep(unsigned int t) { Sleep(1000*t); return 0; }/* I don't think we really need submillisecond resolution ... */unsigned int usleep(unsigned int t) { Sleep(t/1000); return 0; }/* fake (v)snprintf, by just ignoring the size argument */int vsnprintf(char *str, size_t size, const char *format, va_list ap) { if ( size == 0 ) return 0; return vsprintf(str,format,ap);}int snprintf(char *str, size_t size, const char *format, ...) { int n; va_list args; va_start(args,format); if ( size == 0 ) return 0; n = vsprintf(str,format,args); va_end(args); return n;}#endif /* WIN32 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -