static void mfs_fsinit (void *userdata, struct fuse_conn_info *conn) { int *piped = (int*)userdata; char s; conn->max_write = 131072; conn->max_readahead = 131072; #if defined(FUSE_CAP_BIG_WRITES) || defined(FUSE_CAP_DONT_MASK) || defined(FUSE_CAP_FLOCK_LOCKS) || defined(FUSE_CAP_POSIX_LOCKS) conn->want = 0; #endif #ifdef FUSE_CAP_BIG_WRITES conn->want |= FUSE_CAP_BIG_WRITES; #endif #ifdef FUSE_CAP_DONT_MASK conn->want |= FUSE_CAP_DONT_MASK; #endif #ifdef FUSE_CAP_FLOCK_LOCKS if (mfsopts.nobsdlocks==0) { conn->want |= FUSE_CAP_FLOCK_LOCKS; } #endif #ifdef FUSE_CAP_POSIX_LOCKS if (mfsopts.noposixlocks==0) { conn->want |= FUSE_CAP_POSIX_LOCKS; } #endif if (piped[1]>=0) { s=0; if (write(piped[1],&s,1)!=1) { syslog(LOG_ERR,"pipe write error: %s",strerr(errno)); } close(piped[1]); } }
void get_diskinfo(struct disk_info *dsk, int i) { char path = DEVICE; path[strlen(path) - 1] = '0' + i; dsk->fd = open(path, O_RDONLY); if (dsk->fd < 0) { LOG_INFO("Error Opening %s. Error Code %X\n", path, strerr()); break; } strcpy(dsk->device_file, path); dsk->sector_size = SECTOR_SIZE }
/* * caller must zero or otherwise initialise *rp, * other than ax, bx, dx, si & ds. */ static int biosdiskcall(Ureg *up, uchar op, ulong bx, ulong dx, ulong si) { int s; uchar err; s = splhi(); /* don't let the bios call be interrupted */ up->ax = op << 8; up->bx = bx; up->dx = dx; /* often drive id */ /* * ensure that dap addr fits in a short. */ if((si & 0xffff0000) != 0) print("biosdiskcall: dap address %#lux not a short\n", si); /* assume si is in first 64K */ if((si & 0xffff0000) != ((si + 512 - 1) & 0xffff0000)) print("biosdiskcall: dap address %#lux too near segment boundary\n", si); up->si = si; /* ds:si forms data access packet addr */ up->ds = 0; up->di = 0; /* * *up is copied into low memory (realmoderegs) and thence into * the machine registers before the BIOS call, and the registers are * copied into realmoderegs and thence into *up after. * * realmode loads these registers: di, si, ax, bx, cx, dx, ds, es. */ realmode(0x13, up); splx(s); if (up->flags & CF) { if (Debug && dx == Baseid) { err = up->ax >> 8; print("\nbiosdiskcall: int 0x13 op %#ux drive %#lux " "failed, ah error code %#ux (%s)\n", op, dx, err, strerr(err)); } return -1; }
int get_ndisks() { int fd, ndisks = 0; char dev_file = DEVICE; do { fd = open(path, O_RDONLY); if (fd < 0) { LOG_INFO("Error Opening %s. Error Code %X\n", path, strerr()); break; } close(fd); ndisks++; path[strlen(path) - 1] = (char)('0' + ndisks); } while (fd > 0); return ndisks; }
int mainloop(struct fuse_args *args,const char* mp,int mt,int fg) { struct fuse_session *se; struct fuse_chan *ch; struct rlimit rls; int piped[2]; char s; int err; int i; md5ctx ctx; uint8_t md5pass[16]; if (mfsopts.passwordask && mfsopts.password==NULL && mfsopts.md5pass==NULL) { mfsopts.password = getpass("MFS Password:"******"bad md5 definition (md5 should be given as 32 hex digits)\n"); return 1; } p++; if (*p>='0' && *p<='9') { md5pass[i]+=(*p-'0'); } else if (*p>='a' && *p<='f') { md5pass[i]+=(*p-'a'+10); } else if (*p>='A' && *p<='F') { md5pass[i]+=(*p-'A'+10); } else { fprintf(stderr,"bad md5 definition (md5 should be given as 32 hex digits)\n"); return 1; } p++; } if (*p) { fprintf(stderr,"bad md5 definition (md5 should be given as 32 hex digits)\n"); return 1; } memset(mfsopts.md5pass,0,strlen(mfsopts.md5pass)); } if (mfsopts.delayedinit) { fs_init_master_connection(mfsopts.bindhost,mfsopts.masterhost,mfsopts.masterport,mfsopts.meta,mp,mfsopts.subfolder,(mfsopts.password||mfsopts.md5pass)?md5pass:NULL,mfsopts.donotrememberpassword,1); } else { if (fs_init_master_connection(mfsopts.bindhost,mfsopts.masterhost,mfsopts.masterport,mfsopts.meta,mp,mfsopts.subfolder,(mfsopts.password||mfsopts.md5pass)?md5pass:NULL,mfsopts.donotrememberpassword,0)<0) { return 1; } } memset(md5pass,0,16); if (fg==0) { openlog(STR(APPNAME), LOG_PID | LOG_NDELAY , LOG_DAEMON); } else { #if defined(LOG_PERROR) openlog(STR(APPNAME), LOG_PID | LOG_NDELAY | LOG_PERROR, LOG_USER); #else openlog(STR(APPNAME), LOG_PID | LOG_NDELAY, LOG_USER); #endif } i = mfsopts.nofile; while (1) { rls.rlim_cur = i; rls.rlim_max = i; if (setrlimit(RLIMIT_NOFILE,&rls)<0) { i /= 2; if (i<1000) { break; } } else { break; } } if (i != (int)(mfsopts.nofile)) { fprintf(stderr,"can't set open file limit to %d\n",mfsopts.nofile); if (i>=1000) { fprintf(stderr,"open file limit set to: %d\n",i); } } setpriority(PRIO_PROCESS,getpid(),mfsopts.nice); #ifdef MFS_USE_MEMLOCK if (mfsopts.memlock) { rls.rlim_cur = RLIM_INFINITY; rls.rlim_max = RLIM_INFINITY; if (setrlimit(RLIMIT_MEMLOCK,&rls)<0) { mfsopts.memlock=0; } } #endif piped[0] = piped[1] = -1; if (fg==0) { if (pipe(piped)<0) { fprintf(stderr,"pipe error\n"); return 1; } err = fork(); if (err<0) { fprintf(stderr,"fork error\n"); return 1; } else if (err>0) { close(piped[1]); err = read(piped[0],&s,1); if (err==0) { s=1; } return s; } close(piped[0]); s=1; } #ifdef MFS_USE_MEMLOCK if (mfsopts.memlock) { if (mlockall(MCL_CURRENT|MCL_FUTURE)==0) { syslog(LOG_NOTICE,"process memory was successfully locked in RAM"); } } #endif /* glibc malloc tuning */ #ifdef MFS_USE_MALLOPT if (mfsopts.limitarenas) { if (!getenv("MALLOC_ARENA_MAX")) { syslog(LOG_NOTICE,"setting glibc malloc arena max to 8"); mallopt(M_ARENA_MAX, mfsopts.limitarenas); } if (!getenv("MALLOC_ARENA_TEST")) { syslog(LOG_NOTICE,"setting glibc malloc arena test to 1"); mallopt(M_ARENA_TEST, 1); } } else { syslog(LOG_NOTICE,"setting glibc malloc arenas turned off"); } #endif /* glibc malloc tuning */ syslog(LOG_NOTICE,"monotonic clock function: %s",monotonic_method()); syslog(LOG_NOTICE,"monotonic clock speed: %"PRIu32" ops / 10 mili seconds",monotonic_speed()); conncache_init(200); chunkloc_cache_init(); symlink_cache_init(); negentry_cache_init(mfsopts.negentrycacheto); // dir_cache_init(); fs_init_threads(mfsopts.ioretries); if (masterproxy_init(mfsopts.proxyhost)<0) { fs_term(); // dir_cache_term(); negentry_cache_term(); symlink_cache_term(); chunkloc_cache_term(); return 1; } // fs_term(); // negentry_cache_term(); // symlink_cache_term(); // chunkloc_cache_term(); // return 1; if (mfsopts.meta==0) { csdb_init(); delay_init(); read_data_init(mfsopts.readaheadsize*1024*1024,mfsopts.readaheadleng,mfsopts.readaheadtrigger,mfsopts.ioretries); write_data_init(mfsopts.writecachesize*1024*1024,mfsopts.ioretries); } ch = fuse_mount(mp, args); if (ch==NULL) { fprintf(stderr,"error in fuse_mount\n"); if (piped[1]>=0) { if (write(piped[1],&s,1)!=1) { fprintf(stderr,"pipe write error\n"); } close(piped[1]); } if (mfsopts.meta==0) { write_data_term(); read_data_term(); delay_term(); csdb_term(); } masterproxy_term(); fs_term(); // dir_cache_term(); negentry_cache_term(); symlink_cache_term(); chunkloc_cache_term(); return 1; } if (mfsopts.meta) { mfs_meta_init(mfsopts.debug,mfsopts.entrycacheto,mfsopts.attrcacheto); se = fuse_lowlevel_new(args, &mfs_meta_oper, sizeof(mfs_meta_oper), (void*)piped); } else { mfs_init(mfsopts.debug,mfsopts.keepcache,mfsopts.direntrycacheto,mfsopts.entrycacheto,mfsopts.attrcacheto,mfsopts.xattrcacheto,mfsopts.groupscacheto,mfsopts.mkdircopysgid,mfsopts.sugidclearmode,1,mfsopts.fsyncbeforeclose,mfsopts.noxattrs,mfsopts.noposixlocks,mfsopts.nobsdlocks); //mfsopts.xattraclsupport); se = fuse_lowlevel_new(args, &mfs_oper, sizeof(mfs_oper), (void*)piped); } if (se==NULL) { fuse_unmount(mp,ch); fprintf(stderr,"error in fuse_lowlevel_new\n"); portable_usleep(100000); // time for print other error messages by FUSE if (piped[1]>=0) { if (write(piped[1],&s,1)!=1) { fprintf(stderr,"pipe write error\n"); } close(piped[1]); } if (mfsopts.meta==0) { write_data_term(); read_data_term(); delay_term(); csdb_term(); } masterproxy_term(); fs_term(); // dir_cache_term(); negentry_cache_term(); symlink_cache_term(); chunkloc_cache_term(); return 1; } // fprintf(stderr,"check\n"); fuse_session_add_chan(se, ch); if (fuse_set_signal_handlers(se)<0) { fprintf(stderr,"error in fuse_set_signal_handlers\n"); fuse_session_remove_chan(ch); fuse_session_destroy(se); fuse_unmount(mp,ch); if (piped[1]>=0) { if (write(piped[1],&s,1)!=1) { fprintf(stderr,"pipe write error\n"); } close(piped[1]); } if (mfsopts.meta==0) { write_data_term(); read_data_term(); delay_term(); csdb_term(); } masterproxy_term(); fs_term(); // dir_cache_term(); negentry_cache_term(); symlink_cache_term(); chunkloc_cache_term(); return 1; } if (mfsopts.debug==0 && fg==0) { setsid(); setpgid(0,getpid()); if ((i = open("/dev/null", O_RDWR, 0)) != -1) { (void)dup2(i, STDIN_FILENO); (void)dup2(i, STDOUT_FILENO); (void)dup2(i, STDERR_FILENO); if (i>2) close (i); } } if (mt) { err = fuse_session_loop_mt(se); } else { err = fuse_session_loop(se); } if (err) { if (piped[1]>=0) { if (write(piped[1],&s,1)!=1) { syslog(LOG_ERR,"pipe write error: %s",strerr(errno)); } close(piped[1]); } } fuse_remove_signal_handlers(se); fuse_session_remove_chan(ch); fuse_session_destroy(se); fuse_unmount(mp,ch); if (mfsopts.meta==0) { write_data_term(); read_data_term(); delay_term(); csdb_term(); } masterproxy_term(); fs_term(); // dir_cache_term(); negentry_cache_term(); symlink_cache_term(); chunkloc_cache_term(); return err ? 1 : 0; }
void mainloop() { uint32_t prevtime = 0; struct timeval tv; pollentry *pollit; struct pollfd pdesc[MFSMAXFILES]; timeentry *timeit; uint32_t ndesc; int i; while (!exiting){ ndesc=0; for (pollit = pollhead ; pollit != NULL ; pollit = pollit->next) { pollit->desc(pdesc,&ndesc); } i = poll(pdesc,ndesc,50); gettimeofday(&tv,NULL); usecnow = tv.tv_sec; usecnow *= 1000000; usecnow += tv.tv_usec; now = tv.tv_sec; if (i<0) { if (errno==EAGAIN) { syslog(LOG_WARNING,"poll returned EAGAIN"); usleep(100000); continue; } if (errno!=EINTR) { syslog(LOG_WARNING,"poll error: %s",strerr(errno)); break; } } else { for (pollit = pollhead ; pollit != NULL ; pollit = pollit->next) { pollit->serve(pdesc); } } if (now<prevtime) { // time went backward !!! - recalculate "nextevent" time // adding previous_time_to_run prevents from running next event too soon. for (timeit = timehead ; timeit != NULL ; timeit = timeit->next) { uint32_t previous_time_to_run = timeit->nextevent - prevtime; if (previous_time_to_run > timeit->seconds) { previous_time_to_run = timeit->seconds; } timeit->nextevent = ((now / timeit->seconds) * timeit->seconds) + timeit->offset; while (timeit->nextevent <= now+previous_time_to_run) { timeit->nextevent += timeit->seconds; } } } else if (now>prevtime+3600) { // time went forward !!! - just recalculate "nextevent" time for (timeit = timehead ; timeit != NULL ; timeit = timeit->next) { timeit->nextevent = ((now / timeit->seconds) * timeit->seconds) + timeit->offset; while (now >= timeit->nextevent) { timeit->nextevent += timeit->seconds; } } } for (timeit = timehead ; timeit != NULL ; timeit = timeit->next) { if (now >= timeit->nextevent) { if (timeit->mode == TIMEMODE_RUN_LATE) { while (now >= timeit->nextevent) { timeit->nextevent += timeit->seconds; } timeit->fun(); } else { /* timeit->mode == TIMEMODE_SKIP_LATE */ if (now == timeit->nextevent) { timeit->fun(); } while (now >= timeit->nextevent) { timeit->nextevent += timeit->seconds; } } } } prevtime = now; } }
void makedaemon() { int f; uint8_t pipebuff[1000]; ssize_t r; size_t happy; int piped[2]; fflush(stdout); fflush(stderr); if (pipe(piped)<0) { fprintf(stderr,"pipe error\n"); exit(1); } f = fork(); if (f<0) { syslog(LOG_ERR,"first fork error: %s",strerr(errno)); exit(1); } if (f>0) { wait(&f); // just get child status - prevents child from being zombie during initialization stage if (f) { fprintf(stderr,"Child status: %d\n",f); exit(1); } close(piped[1]); // printf("Starting daemon ...\n"); while ((r=read(piped[0],pipebuff,1000))) { if (r>0) { if (pipebuff[r-1]==0) { // zero as a last char in the pipe means error if (r>1) { happy = fwrite(pipebuff,1,r-1,stderr); (void)happy; } exit(1); } happy = fwrite(pipebuff,1,r,stderr); (void)happy; } else { fprintf(stderr,"Error reading pipe: %s\n",strerr(errno)); exit(1); } } exit(0); } setsid(); setpgid(0,getpid()); f = fork(); if (f<0) { syslog(LOG_ERR,"second fork error: %s",strerr(errno)); if (write(piped[1],"fork error\n",11)!=11) { syslog(LOG_ERR,"pipe write error: %s",strerr(errno)); } close(piped[1]); exit(1); } if (f>0) { exit(0); } set_signal_handlers(1); close(STDIN_FILENO); sassert(open("/dev/null", O_RDWR, 0)==STDIN_FILENO); close(STDOUT_FILENO); sassert(dup(STDIN_FILENO)==STDOUT_FILENO); close(STDERR_FILENO); sassert(dup(piped[1])==STDERR_FILENO); close(piped[1]); // setvbuf(stderr,(char *)NULL,_IOLBF,0); }
void mainloop() { uint32_t prevtime = 0; struct timeval tv; pollentry *pollit; eloopentry *eloopit; timeentry *timeit; ceentry *ceit; weentry *weit; rlentry *rlit; struct pollfd pdesc[MFSMAXFILES]; uint32_t ndesc; int i; int t,r; t = 0; r = 0; while (t!=3) { ndesc=1; pdesc[0].fd = signalpipe[0]; pdesc[0].events = POLLIN; pdesc[0].revents = 0; for (pollit = pollhead ; pollit != NULL ; pollit = pollit->next) { pollit->desc(pdesc,&ndesc); } i = poll(pdesc,ndesc,50); gettimeofday(&tv,NULL); usecnow = tv.tv_sec; usecnow *= 1000000; usecnow += tv.tv_usec; now = tv.tv_sec; if (i<0) { if (errno==EAGAIN) { syslog(LOG_WARNING,"poll returned EAGAIN"); usleep(100000); continue; } if (errno!=EINTR) { syslog(LOG_WARNING,"poll error: %s",strerr(errno)); break; } } else { if ((pdesc[0].revents)&POLLIN) { uint8_t sigid; if (read(signalpipe[0],&sigid,1)==1) { if (sigid=='\001' && t==0) { syslog(LOG_NOTICE,"terminate signal received"); t = 1; } else if (sigid=='\002') { syslog(LOG_NOTICE,"reloading config files"); r = 1; } } } for (pollit = pollhead ; pollit != NULL ; pollit = pollit->next) { pollit->serve(pdesc); } } for (eloopit = eloophead ; eloopit != NULL ; eloopit = eloopit->next) { eloopit->fun(); } if (now<prevtime) { // time went backward !!! - recalculate "nextevent" time // adding previous_time_to_run prevents from running next event too soon. for (timeit = timehead ; timeit != NULL ; timeit = timeit->next) { uint32_t previous_time_to_run = timeit->nextevent - prevtime; if (previous_time_to_run > timeit->seconds) { previous_time_to_run = timeit->seconds; } timeit->nextevent = ((now / timeit->seconds) * timeit->seconds) + timeit->offset; while (timeit->nextevent <= now+previous_time_to_run) { timeit->nextevent += timeit->seconds; } } } else if (now>prevtime+3600) { // time went forward !!! - just recalculate "nextevent" time for (timeit = timehead ; timeit != NULL ; timeit = timeit->next) { timeit->nextevent = ((now / timeit->seconds) * timeit->seconds) + timeit->offset; while (now >= timeit->nextevent) { timeit->nextevent += timeit->seconds; } } } for (timeit = timehead ; timeit != NULL ; timeit = timeit->next) { if (now >= timeit->nextevent) { if (timeit->mode == TIMEMODE_RUN_LATE) { while (now >= timeit->nextevent) { timeit->nextevent += timeit->seconds; } timeit->fun(); } else { /* timeit->mode == TIMEMODE_SKIP_LATE */ if (now == timeit->nextevent) { timeit->fun(); } while (now >= timeit->nextevent) { timeit->nextevent += timeit->seconds; } } } } prevtime = now; if (t==0 && r) { cfg_reload(); for (rlit = rlhead ; rlit!=NULL ; rlit=rlit->next ) { rlit->fun(); } r = 0; } if (t==1) { for (weit = wehead ; weit!=NULL ; weit=weit->next ) { weit->fun(); } t = 2; } if (t==2) { i = 1; for (ceit = cehead ; ceit!=NULL && i ; ceit=ceit->next ) { if (ceit->fun()==0) { i=0; } } if (i) { t = 3; } } } }
parse() {int i,j,found,current, someread; char c; hash_init(); routinit(); line_init(); someread = 0; /* indicates haven't read part of a routine */ empseek(0); endbuf = getline(&endline, &endchar, &endcom, & comchar); if (progress && endbuf != -1) fprintf(stderr,"parsing\n"); while(endbuf != -1) /* getline returns -1 when no more input */ { someread = 1; if (progress > 0) { for (i = begline; i <= endline; i++) if (!(i % progress)) fprintf(stderr,"parsing line %d\n",i); } current = 0; for (i = 0; i < endbuf; i++) { c = buffer[i]; if(c != '~') { found = 0; if ( (current < 0 || current >= snum) && current != ABORT) { strerr("in parsing:","",""); fprintf(stderr,"line %d of file, parser in invalid state", begline,current); fprintf(stderr,"treating it as straight line code\n"); current = ABORT; } else for (j = match[current]; j < match[current + 1]; j++) { if ((symclass[j] == 0 && c == symbol[j]) || (symclass[j] != 0 && classmatch(c,symclass[j]) )) {found = 1; break; } } if (!found) { error("in syntax:","",""); fprintf(stderr,"between lines %d and %d of file\n",begline, endline); if (debug) fprintf(stderr,"symbol '%c' does not match entries for state %d\n",c,current); fprintf(stderr,"treating it as straight line code\n"); current = ABORT; } else if (!action[j]) current = newstate[j]; else { current = act(action[j],c,i); if (current == nulls) current = newstate[j]; } if (current == ABORT) break; if (current == endrt) { return(1); } } } line_init(); endbuf = getline(&endline, &endchar, &endcom,&comchar); } if (someread) return(1); else return(0); }
struct list * read_config(const char *filename) { APP_DEBUG_FNAME; struct list *beg_cmd; struct list *beg_var; struct list *l; FILE *in; char *line; size_t len; ssize_t read_len; beg_cmd = NULL; beg_var = NULL; len = CONF_LINE_MAXLENGTH; line = alloc_string_size(len); in = fopen(filename, "r"); if (in == NULL) { ERR("fopen('%s'): %s", filename, strerr()); myabort(); } else { while ((read_len = getline(&line, &len, in)) != -1) { // remove \n from the end if (read_len > 0) line[read_len - 1] = '\0'; switch (check_line(line)) { case LINE_VARIABLE: l = malloc(sizeof (struct list)); l->next = beg_var; l->item = create_var(line, beg_var); beg_var = l; break; case LINE_COMMAND: l = malloc(sizeof (struct list)); l->next = beg_cmd; l->item = create_cmd(line, beg_var); beg_cmd = l; break; case LINE_BAD: WARN("bad line structure '%s'", line); break; case LINE_IGNORE: DEBUG("ignoring line '%s'", line); break; } l = NULL; } if (ferror(in)) WARN("ferror while reading '%s', try to continue", filename); fclose(in); print_cfg(beg_var, beg_cmd); } free(line); delete_list(&beg_var); return (beg_cmd); }
// Runs the interactive loop and all file transfers. // Returns: exit status int main(void) { // Used to control DNS resolution requests: struct addrinfo hints; memset(&hints, 0, sizeof hints); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_DGRAM; // Bind to an ephemeral network port: struct addrinfo *server = NULL; int sfd = openudp(0); if(sfd < 0) handle_error("bind()"); // Allocate (small) space to store user input: char *buf = malloc(1); size_t cap = 1; char *cmd; // First word of buf size_t len; // Length of cmd // Main input loop, which normally only breaks upon a GFO: do { // Keep prompting until the user brings us back something good: do { printf("%s", SHL_PS1); readin(&buf, &cap); } while(homog(buf, ' ')); // Cleave off the command (first word): cmd = strtok(buf, " "); len = strlen(cmd); if(strncmp(cmd, CMD_CON, len) == 0) { // Read the arguments: const char *hostname = strtok(NULL, " "); const char *tmp = strtok(NULL, " "); in_port_t port = PORT_UNPRIVILEGED; if(tmp) port = atoi(tmp); // Ensure a hostname or IP has been provided: if(!hostname) { usage(CMD_CON, "hostname", "port"); continue; } // Avoid leaking any existing address: if(server) { freeaddrinfo(server); server = NULL; } // Try to resolve the requested hostname: if(getaddrinfo(hostname, NULL, &hints, &server)) { fprintf(stderr, "Unable to resolve hostname\n"); freeaddrinfo(server); server = NULL; continue; } ((struct sockaddr_in *)server->ai_addr)->sin_port = htons(port); } else if(strncmp(cmd, CMD_GET, len) == 0 || strncmp(cmd, CMD_PUT, len) == 0) { bool putting = strncmp(cmd, CMD_PUT, 1) == 0; // Ensure we're already connected to a server: if(!server) { noconn(cmd); continue; } // Make sure we were given a path argument: char *pathname = strtok(NULL, ""); if(!pathname) { usage(putting ? CMD_PUT : CMD_GET, "pathname", NULL); continue; } // Since basename() might modify pathname, copy it: char filename[strlen(pathname)+1]; memcpy(filename, pathname, sizeof filename); int fd; if(putting) { // Try opening the file for reading: if((fd = open(pathname, O_RDONLY)) < 0) { fprintf(stderr, "local: Unable to read specified file\n"); continue; } // Send a request and record the port used to acknowledge: struct sockaddr_in dest_addr; sendreq(sfd, basename(filename), OPC_WRQ, server->ai_addr); uint8_t *rmtack = recvpkta(sfd, &dest_addr); if(iserr(rmtack)) { fprintf(stderr, "remote: %s\n", strerr(rmtack)); free(rmtack); continue; } free(rmtack); // Transmit the file: sendfile(sfd, fd, &dest_addr); } else // getting { // Try opening a file of that name for writing: if((fd = open(basename(filename), O_WRONLY|O_CREAT|O_EXCL, 0666)) < 0) { fprintf(stderr, "local: Unable to create the new file\n"); continue; } // Send a request and await the incoming file: sendreq(sfd, pathname, OPC_RRQ, server->ai_addr); const char *res = recvfile(sfd, fd); if(res) { fprintf(stderr, "remote: %s\n", res); close(fd); fd = -1; unlink(basename(filename)); } } if(fd >= 0) close(fd); } else if(strncmp(cmd, CMD_HLP, len) == 0) { printf("Commands may be abbreviated. Commands are:\n\n"); printf("%s\t\tconnect to remote tftp\n", CMD_CON); printf("%s\t\tsend file\n", CMD_PUT); printf("%s\t\treceive file\n", CMD_GET); printf("%s\t\texit tftp\n", CMD_GFO); printf("%s\t\tprint help information\n", CMD_HLP); } else if(strncmp(cmd, CMD_GFO, len) != 0) { fprintf(stderr, "%s: unknown directive\n", cmd); fprintf(stderr, "Try ? for help.\n"); } } while(strncmp(cmd, CMD_GFO, len) != 0); free(buf); if(server) freeaddrinfo(server); return 0; }