Annotation of cci/usr/src/etc/tftpd.c, revision 1.1

1.1     ! root        1: #ifndef lint
        !             2: static char sccsid[] = "@(#)tftpd.c    4.11 (Berkeley) 7/2/83";
        !             3: #endif
        !             4: 
        !             5: /*
        !             6:  * Trivial file transfer protocol server.
        !             7:  */
        !             8: #include <sys/types.h>
        !             9: #include <sys/socket.h>
        !            10: #include <sys/ioctl.h>
        !            11: #include <sys/wait.h>
        !            12: #include <sys/stat.h>
        !            13: 
        !            14: #include <netinet/in.h>
        !            15: 
        !            16: #include <arpa/tftp.h>
        !            17: 
        !            18: #include <signal.h>
        !            19: #include <stdio.h>
        !            20: #include <errno.h>
        !            21: #include <ctype.h>
        !            22: #include <netdb.h>
        !            23: #include <setjmp.h>
        !            24: 
        !            25: #define        TIMEOUT         5
        !            26: 
        !            27: extern int errno;
        !            28: extern int sys_nerr;
        !            29: extern char *sys_errlist[];
        !            30: 
        !            31: struct in_addr my_machine_addr;
        !            32: struct sockaddr_in sin = { AF_INET };
        !            33: int    f;
        !            34: int    rexmtval = TIMEOUT;
        !            35: int    maxtimeout = 5*TIMEOUT;
        !            36: char   buf[BUFSIZ];
        !            37: int    reapchild();
        !            38: 
        !            39: char   *inet_ntoa();
        !            40: /*---------------------------------------------------------
        !            41:  * Changes
        !            42:  *
        !            43:  *     . change declaration of tftp header for compiler independence.
        !            44:  *
        !            45:  *      . truncate the file after file transfer completes.
        !            46:  *
        !            47:  *      . the daemon keeps its master socket; it creates a new socket
        !            48:  *       and hands this socket to its children. In the old implementation,
        !            49:  *       the daemon hands the socket to its child, and creates a new socket;
        !            50:  *       therefore, requests queued at old socket will be discarded, and
        !            51:  *       requests arriving before the daemon successfully creates a new
        !            52:  *       socket are also discarded.
        !            53:  *
        !            54:  *     . change userid and groupid to -2 before verifying the access
        !            55:  *       rights. Temporary Fix Until An Official Policy Is Established.
        !            56:  *
        !            57:  *     . change perror() to macro PERROR() to ensure that error messages
        !            58:  *       come to the console.
        !            59:  *
        !            60:  *     . let the system assign address to the child daemon.
        !            61:  *--------------------------------------------------------*/
        !            62: #define        PERROR(X) {                                                     \
        !            63:                        int     cfd;                                    \
        !            64:                        if ((cfd=open("/dev/console",2)) >=0) {         \
        !            65:                                write(cfd,X,strlen(X));                 \
        !            66:                                write(cfd,": ", 2);                     \
        !            67:                                if (errno >=0 && errno <sys_nerr)       \
        !            68:                                        write(cfd,sys_errlist[errno],   \
        !            69:                                                strlen(sys_errlist[errno]));\
        !            70:                                write(cfd,"\n",1);                      \
        !            71:                                close(cfd);                             \
        !            72:                        }                                               \
        !            73:                }
        !            74:        
        !            75: main(argc, argv)
        !            76:        char *argv[];
        !            77: {
        !            78:        struct sockaddr_in from;
        !            79:        register struct tftphdr *tp;
        !            80:        register int n;
        !            81:        int     bindstat = -1;
        !            82:        struct servent *sp;
        !            83: 
        !            84:        get_myaddrs();
        !            85: 
        !            86:        sp = getservbyname("tftp", "udp");
        !            87:        if (sp == 0) {
        !            88:                fprintf(stderr, "tftpd: udp/tftp: unknown service\n");
        !            89:                exit(1);
        !            90:        }
        !            91:        sin.sin_port = sp->s_port;
        !            92: #ifndef DEBUG
        !            93:        if (fork())
        !            94:                exit(0);
        !            95:        for (f = 0; f < 10; f++)
        !            96:                (void) close(f);
        !            97:        (void) open("/", 0);
        !            98:        (void) dup2(0, 1);
        !            99:        (void) dup2(0, 2);
        !           100:        { int t = open("/dev/tty", 2);
        !           101:          if (t >= 0) {
        !           102:                ioctl(t, TIOCNOTTY, (char *)0);
        !           103:                (void) close(t);
        !           104:          }
        !           105:        }
        !           106: #endif
        !           107:        signal(SIGCHLD, reapchild);
        !           108:        do {
        !           109:                f = socket(AF_INET, SOCK_DGRAM, 0);
        !           110:                if (f < 0) {
        !           111:                        PERROR("tftpd: socket");
        !           112:                        sleep(5);
        !           113:                }
        !           114:        } while (f<0);
        !           115:        if (setsockopt(f, SOL_SOCKET, SO_REUSEADDR, 0, 0) < 0)
        !           116:                PERROR("tftpd: setsockopt (SO_REUSEADDR)");
        !           117:        for (n = 0; n<25; n++) {
        !           118:                if ((bindstat = bind(f, (caddr_t)&sin, sizeof (sin), 0))>= 0) {
        !           119:                        break;
        !           120:                }
        !           121:                else {
        !           122:                        PERROR("tftpd: bind");
        !           123:                        sleep(5);
        !           124:                }
        !           125:        }
        !           126:        if (bindstat <0) {
        !           127:                PERROR("tftpd: unable to bind. Terminated.\n");
        !           128:                exit(1);
        !           129:        }
        !           130: 
        !           131:        for (;;) {
        !           132:                int fromlen;
        !           133: 
        !           134:                do {
        !           135:                        
        !           136:                        fromlen = sizeof (from);
        !           137:                        from.sin_family = AF_INET;
        !           138:                        n = recvfrom(f, buf, sizeof (buf), 0,
        !           139:                            (caddr_t)&from, &fromlen);
        !           140: #ifdef DEBUG
        !           141:                        fprintf(stderr,"tftpd: got request fr %s %d.\n",
        !           142:                                inet_ntoa(from.sin_addr), from.sin_port);
        !           143: #endif
        !           144:                } while (n <= 0);
        !           145: 
        !           146:                tp = (struct tftphdr *)buf;
        !           147:                tp->th_opcode = ntohs(tp->th_opcode);
        !           148:                if (tp->th_opcode == RRQ || tp->th_opcode == WRQ) {
        !           149: #ifdef DEBUG
        !           150:                        fprintf(stderr,"tftpd: fork a child.\n");
        !           151: #endif
        !           152:                        if (fork() == 0) {
        !           153:                                close(f);
        !           154:                                do {
        !           155:                                        f = socket(AF_INET, SOCK_DGRAM, 0);
        !           156:                                        if (f < 0) {
        !           157:                                                PERROR("tftpd: socket(child)");
        !           158:                                                sleep(5);
        !           159:                                        }
        !           160:                                } while (f<0);
        !           161: 
        !           162:                                if (setsockopt(f, SOL_SOCKET, 
        !           163:                                                SO_REUSEADDR, 0, 0) < 0)
        !           164:                                        PERROR("tftpd: setsockopt(REUSEADDR)");
        !           165: 
        !           166:                                /* let the system assign the address */
        !           167:                                sin.sin_addr.s_addr = 0;
        !           168:                                sin.sin_port = 0;
        !           169:                                while (bind(f, 
        !           170:                                        (caddr_t)&sin, sizeof (sin), 0) < 0) {
        !           171:                                        PERROR("tftpd: bind (child)");
        !           172:                                        sleep(5);
        !           173:                                }
        !           174:                                tftp(&from, tp, n);
        !           175:                        }
        !           176:                }
        !           177:        }
        !           178: }
        !           179: 
        !           180: reapchild()
        !           181: {
        !           182:        union wait status;
        !           183: 
        !           184:        while (wait3(&status, WNOHANG, 0) > 0)
        !           185:                ;
        !           186: }
        !           187: 
        !           188: int    validate_access();
        !           189: int    sendfile(), recvfile();
        !           190: 
        !           191: struct formats {
        !           192:        char    *f_mode;
        !           193:        int     (*f_validate)();
        !           194:        int     (*f_send)();
        !           195:        int     (*f_recv)();
        !           196: } formats[] = {
        !           197:        { "netascii",   validate_access,        sendfile,       recvfile },
        !           198:        { "octet",      validate_access,        sendfile,       recvfile },
        !           199: #ifdef notdef
        !           200:        { "mail",       validate_user,          sendmail,       recvmail },
        !           201: #endif
        !           202:        { 0 }
        !           203: };
        !           204: 
        !           205: FILE   *fd;                    /* file being transferred */
        !           206: 
        !           207: /*
        !           208:  * Handle initial connection protocol.
        !           209:  */
        !           210: tftp(client, tp, size)
        !           211:        struct sockaddr_in *client;
        !           212:        struct tftphdr *tp;
        !           213:        int size;
        !           214: {
        !           215:        register char *cp;
        !           216:        int first = 1, ecode;
        !           217:        register struct formats *pf;
        !           218:        char *filename, *mode;
        !           219: 
        !           220: #ifdef DEBUG
        !           221:        fprintf(stderr,"tftpd:sockfd %d, connect to %s %d\n",
        !           222:                f, inet_ntoa(client->sin_addr), client->sin_port);
        !           223: #endif
        !           224:        if (connect(f, (caddr_t)client, sizeof (*client), 0) < 0) {
        !           225:                PERROR("tftpd:connect");
        !           226:                exit(1);
        !           227:        }
        !           228: #ifdef DEBUG
        !           229:        {
        !           230:        struct sockaddr_in myname;
        !           231:        struct sockaddr_in peername;
        !           232:        int     t;
        !           233:        int     err = 0;
        !           234: 
        !           235:        myname.sin_family = AF_INET;
        !           236:        t = sizeof(myname);
        !           237:        if (getsockname(f, (caddr_t)&myname, &t) < 0) {
        !           238:                PERROR("tftpd:getsockname");
        !           239:                err = 1;
        !           240:        }
        !           241:        if (err!= 1)
        !           242:                fprintf(stderr,"tftpd:myname is %s %d\n",
        !           243:                        inet_ntoa(myname.sin_addr),
        !           244:                        myname.sin_port);
        !           245: 
        !           246:        peername.sin_family = AF_INET;
        !           247:        t = sizeof(peername);
        !           248:        if (getpeername(f, (caddr_t)&peername, &t) < 0) {
        !           249:                PERROR("tftpd:getpeername");
        !           250:                err = 2;
        !           251:        }
        !           252:        if (err!=2)
        !           253:                fprintf(stderr,"tftpd:peername is %s %d\n",
        !           254:                        inet_ntoa(peername.sin_addr),
        !           255:                        peername.sin_port);
        !           256:        if (err)
        !           257:                exit(1);
        !           258:        }
        !           259: #endif
        !           260:        filename = cp = tp->th_stuff;
        !           261: again:
        !           262:        while (cp < buf + size) {
        !           263:                if (*cp == '\0')
        !           264:                        break;
        !           265:                cp++;
        !           266:        }
        !           267:        if (*cp != '\0') {
        !           268:                nak(EBADOP);
        !           269:                exit(1);
        !           270:        }
        !           271:        if (first) {
        !           272:                mode = ++cp;
        !           273:                first = 0;
        !           274:                goto again;
        !           275:        }
        !           276:        for (cp = mode; *cp; cp++)
        !           277:                if (isupper(*cp))
        !           278:                        *cp = tolower(*cp);
        !           279:        for (pf = formats; pf->f_mode; pf++)
        !           280:                if (strcmp(pf->f_mode, mode) == 0)
        !           281:                        break;
        !           282:        if (pf->f_mode == 0) {
        !           283:                nak(EBADOP);
        !           284:                exit(1);
        !           285:        }
        !           286:        ecode = (*pf->f_validate)(filename, client, tp->th_opcode);
        !           287:        if (ecode) {
        !           288:                nak(ecode);
        !           289:                exit(1);
        !           290:        }
        !           291:        if (tp->th_opcode == WRQ)
        !           292:                (*pf->f_recv)(pf);
        !           293:        else
        !           294:                (*pf->f_send)(pf);
        !           295:        exit(0);
        !           296: }
        !           297: 
        !           298: /*
        !           299:  * Validate file access.  Since we
        !           300:  * have no uid or gid, for now require
        !           301:  * file to exist and be publicly
        !           302:  * readable/writable.
        !           303:  * Note also, full path name must be
        !           304:  * given as we have no login directory.
        !           305:  */
        !           306: validate_access(file, client, mode)
        !           307:        char *file;
        !           308:        struct sockaddr_in *client;
        !           309:        int mode;
        !           310: {
        !           311:        struct stat stbuf;
        !           312: 
        !           313:        if (*file != '/')
        !           314:                return (EACCESS);
        !           315: 
        !           316:        /* temporary fix */
        !           317:        if (setuid(-2) <0 ||
        !           318:            setgid(-2) <0) {
        !           319:                PERROR("tftpd: cannot setuid or setpid");
        !           320:        }
        !           321: 
        !           322:        if (stat(file, &stbuf) < 0)
        !           323:                return (errno == ENOENT ? ENOTFOUND : EACCESS);
        !           324:        if (mode == RRQ) {
        !           325:                if ((stbuf.st_mode&(S_IREAD >> 6)) == 0)
        !           326:                        return (EACCESS);
        !           327:        } else {
        !           328:                if ((stbuf.st_mode&(S_IWRITE >> 6)) == 0)
        !           329:                        return (EACCESS);
        !           330:        }
        !           331:        fd = fopen(file, mode == RRQ ? "r" : "w");
        !           332:        if (!fd)
        !           333:                return (errno + 100);
        !           334:        if (mode == WRQ) {
        !           335:                if ((ftruncate(fileno(fd),0))== -1) {
        !           336:                        PERROR("tftpd : truncate ");
        !           337:                        return(errno + 100);
        !           338:                        }
        !           339:        }
        !           340:        return (0);
        !           341: }
        !           342: 
        !           343: int    timeout;
        !           344: jmp_buf        timeoutbuf;
        !           345: 
        !           346: timer()
        !           347: {
        !           348: 
        !           349:        timeout += rexmtval;
        !           350:        if (timeout >= maxtimeout)
        !           351:                exit(1);
        !           352:        longjmp(timeoutbuf, 1);
        !           353: }
        !           354: 
        !           355: /*
        !           356:  * Send the requested file.
        !           357:  */
        !           358: sendfile(pf)
        !           359:        struct format *pf;
        !           360: {
        !           361:        register struct tftphdr *tp;
        !           362:        register int block = 1, size, n;
        !           363:        int     fsize;
        !           364: 
        !           365:        signal(SIGALRM, timer);
        !           366:        tp = (struct tftphdr *)buf;
        !           367:        do {
        !           368:                size = tftpread(fd, tp->th_data, SEGSIZE, &fsize);
        !           369:                if (size < 0) {
        !           370:                        nak(errno + 100);
        !           371:                        goto abort;
        !           372:                }
        !           373:                tp->th_opcode = htons((u_short)DATA);
        !           374:                tp->th_block = htons((u_short)block);
        !           375:                timeout = 0;
        !           376:                (void) setjmp(timeoutbuf);
        !           377:                if (write(f, buf, size + 4) != size + 4) {
        !           378:                        PERROR("tftpd: write");
        !           379:                        goto abort;
        !           380:                }
        !           381:                do {
        !           382:                        alarm(rexmtval);
        !           383:                        n = read(f, buf, sizeof (buf));
        !           384:                        alarm(0);
        !           385:                        if (n < 0) {
        !           386:                                PERROR("tftpd: read");
        !           387:                                goto abort;
        !           388:                        }
        !           389:                        tp->th_opcode = ntohs((u_short)tp->th_opcode);
        !           390:                        tp->th_block = ntohs((u_short)tp->th_block);
        !           391:                        if (tp->th_opcode == ERROR)
        !           392:                                goto abort;
        !           393:                } while (tp->th_opcode != ACK || tp->th_block != block);
        !           394:                block++;
        !           395:        } while (size == SEGSIZE);
        !           396: abort:
        !           397:        (void) fclose(fd);
        !           398: }
        !           399: 
        !           400: /*
        !           401:  * Receive a file.
        !           402:  */
        !           403: recvfile(pf)
        !           404:        struct format *pf;
        !           405: {
        !           406:        register struct tftphdr *tp;
        !           407:        register int block = 0, n, size;
        !           408:        int     fsize;
        !           409: 
        !           410:        signal(SIGALRM, timer);
        !           411:        tp = (struct tftphdr *)buf;
        !           412:        do {
        !           413:                timeout = 0;
        !           414:                tp->th_opcode = htons((u_short)ACK);
        !           415:                tp->th_block = htons((u_short)block);
        !           416:                block++;
        !           417:                (void) setjmp(timeoutbuf);
        !           418:                if (write(f, buf, 4) != 4) {
        !           419:                        PERROR("tftpd: write");
        !           420:                        goto abort;
        !           421:                }
        !           422:                do {
        !           423:                        alarm(rexmtval);
        !           424:                        n = read(f, buf, sizeof (buf));
        !           425:                        alarm(0);
        !           426:                        if (n < 0) {
        !           427:                                PERROR("tftpd: read");
        !           428:                                goto abort;
        !           429:                        }
        !           430:                        tp->th_opcode = ntohs((u_short)tp->th_opcode);
        !           431:                        tp->th_block = ntohs((u_short)tp->th_block);
        !           432:                        if (tp->th_opcode == ERROR)
        !           433:                                goto abort;
        !           434:                } while (tp->th_opcode != DATA || block != tp->th_block);
        !           435:                size = n -4;
        !           436:                n = tftpwrite(fd, tp->th_data, size, &fsize);
        !           437:                if (n < 0) {
        !           438:                        nak(errno + 100);
        !           439:                        goto abort;
        !           440:                }
        !           441:        } while (size == SEGSIZE);
        !           442: abort:
        !           443:        tp->th_opcode = htons((u_short)ACK);
        !           444:        tp->th_block = htons((u_short)(block));
        !           445:        (void) write(f, buf, 4);
        !           446:        (void) fclose(fd);
        !           447: }
        !           448: 
        !           449: struct errmsg {
        !           450:        int     e_code;
        !           451:        char    *e_msg;
        !           452: } errmsgs[] = {
        !           453:        { EUNDEF,       "Undefined error code" },
        !           454:        { ENOTFOUND,    "File not found" },
        !           455:        { EACCESS,      "Access violation" },
        !           456:        { ENOSPACE,     "Disk full or allocation exceeded" },
        !           457:        { EBADOP,       "Illegal TFTP operation" },
        !           458:        { EBADID,       "Unknown transfer ID" },
        !           459:        { EEXISTS,      "File already exists" },
        !           460:        { ENOUSER,      "No such user" },
        !           461:        { -1,           0 }
        !           462: };
        !           463: 
        !           464: /*
        !           465:  * Send a nak packet (error message).
        !           466:  * Error code passed in is one of the
        !           467:  * standard TFTP codes, or a UNIX errno
        !           468:  * offset by 100.
        !           469:  */
        !           470: nak(error)
        !           471:        int error;
        !           472: {
        !           473:        register struct tftphdr *tp;
        !           474:        int length;
        !           475:        register struct errmsg *pe;
        !           476: 
        !           477:        tp = (struct tftphdr *)buf;
        !           478:        tp->th_opcode = htons((u_short)ERROR);
        !           479:        tp->th_code = htons((u_short)error);
        !           480:        for (pe = errmsgs; pe->e_code >= 0; pe++)
        !           481:                if (pe->e_code == error)
        !           482:                        break;
        !           483:        if (pe->e_code < 0)
        !           484:                pe->e_msg = sys_errlist[error - 100];
        !           485:        strcpy(tp->th_msg, pe->e_msg);
        !           486:        length = strlen(pe->e_msg);
        !           487:        tp->th_msg[length] = '\0';
        !           488:        length += 5;
        !           489:        if (write(f, buf, length) != length)
        !           490:                PERROR("tftpd:nak");
        !           491: }
        !           492: get_myaddrs()
        !           493: {
        !           494:     struct hostent *hp;
        !           495:     char       my_machine_name[BUFSIZ];
        !           496: 
        !           497:     /* look up the address of the local host */
        !           498:     if (gethostname(my_machine_name, sizeof(my_machine_name)) <0) {
        !           499:        perror("tftpd:cannot get this host name");
        !           500:        exit(-1);
        !           501:     }
        !           502: 
        !           503:     hp = gethostbyname(my_machine_name);
        !           504:     if (hp == (struct hostent *) 0) {
        !           505:        fprintf(stderr,"tftpd:cannot get host address");
        !           506:        exit(-2);
        !           507:     }
        !           508: 
        !           509:     if (hp->h_addrtype != AF_INET) {
        !           510:        fprintf(stderr,"Protocal mix up with local machine address\n");
        !           511:        exit(-1);
        !           512:     }
        !           513: 
        !           514:     bcopy(hp->h_addr, (char *)&my_machine_addr, hp->h_length);
        !           515: }
        !           516: 
        !           517: bcopy(fr, to, size)
        !           518: register char  *fr;
        !           519: register char  *to;
        !           520: register int   size;
        !           521: {
        !           522:        while (size-->0)
        !           523:                *to++ = *fr++;
        !           524: }
        !           525: 
        !           526: #include <stdio.h>
        !           527: 
        !           528: /*-----------------------------------------
        !           529:   >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
        !           530:   >>>>>>>>>>>> NOTE >>>>>>>>>>>>> Must be identical to those in "tftp"
        !           531:   >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
        !           532:   read from local file and transform lines ending with '\n' to lines
        !           533:   ending with '\r' and '\n'; also transform '\r' to '\r' and '\0'
        !           534:   ----------------------------------------*/
        !           535: tftpread(fd, buf, bufsize, fsize)
        !           536: FILE   *fd;
        !           537: register char  *buf;
        !           538: int    bufsize;
        !           539: int    *fsize;                 /* count # bytes read from file */
        !           540: {
        !           541: 
        !           542:        register char   *p;
        !           543:        int     i;
        !           544: 
        !           545:        /* oldc is to indicate if the transformation is unfinished in the
        !           546:           last block */
        !           547:        static  char    oldc;
        !           548: 
        !           549:        *fsize = 0;
        !           550:        for (p=buf; p < buf+bufsize;) {
        !           551:                switch(oldc) {
        !           552:                case '\n':
        !           553:                        *p++ = '\n';            /* already output '\r' */
        !           554:                        oldc = '\0';
        !           555:                        break;
        !           556:                case '\r':
        !           557:                        *p++ = '\0';            /* already output '\r' */
        !           558:                        oldc = '\0';
        !           559:                        break;
        !           560:                default:
        !           561:                        i = fread(&oldc, sizeof(oldc), 1, fd);
        !           562:                        if (i<0)
        !           563:                                return(i);
        !           564:                        if (i==0)
        !           565:                                goto endit;
        !           566: 
        !           567:                        ++(*fsize);
        !           568:                        switch(oldc) {
        !           569:                        case '\n':
        !           570:                        case '\r':
        !           571:                                *p++ = '\r';
        !           572:                                /* will complete the transformation in next
        !           573:                                   ... loop iteration */
        !           574:                                break;
        !           575:                        default:
        !           576:                                *p++ = oldc;
        !           577:                                break;
        !           578:                        }
        !           579:                }
        !           580: 
        !           581:        }
        !           582: endit:
        !           583:        return(p-buf);
        !           584: }
        !           585: /*-----------------------------------------
        !           586:   >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
        !           587:   >>>>>>>>>>>>>>>> NOTE >>>>>>>>> Must be identical to those "tftp"
        !           588:   >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
        !           589:   write to local file and transform lines ending with '\r''\n' to lines
        !           590:   ending with and '\n'; also transform '\r' '\0' to '\r'.
        !           591:   ----------------------------------------*/
        !           592: tftpwrite(fd, buf, bufsize, fsize)
        !           593: FILE   *fd;
        !           594: register char  *buf;
        !           595: int    bufsize;
        !           596: int    *fsize;                 /* count # of bytes write to file */
        !           597: {
        !           598:        register char   *p;
        !           599:        char    c;
        !           600:        int     i;
        !           601: 
        !           602:        /* oldc is to indicate if the transformation is unfinished in the
        !           603:           last block */
        !           604:        static  char    oldc;
        !           605: 
        !           606:        *fsize = 0;
        !           607:        for  (p=buf; p<buf + bufsize; p++) {
        !           608:                c = *p;
        !           609:                if (oldc == '\r') {
        !           610:                        char    writethisc;
        !           611: 
        !           612:                        switch(c) {
        !           613:                        case '\0':
        !           614:                                writethisc = oldc;
        !           615:                                break;
        !           616:                        case '\n':
        !           617:                                writethisc = '\n';
        !           618:                                break;
        !           619:                        default:
        !           620:                                writethisc = oldc;
        !           621:                                break;
        !           622:                        }
        !           623:                        i = fwrite(&writethisc, sizeof(writethisc), 1, fd);
        !           624:                        if (i!=1)
        !           625:                                return(-1);
        !           626:                        ++(*fsize);
        !           627:                        if (c=='\0' ||
        !           628:                            c=='\n') {
        !           629:                                oldc = '\0';
        !           630:                                continue;
        !           631:                        }
        !           632:                }
        !           633:                if ((oldc = c) == '\r')
        !           634:                        continue;
        !           635:                i = fwrite(&c, sizeof(c), 1, fd);
        !           636:                if (i!=1)
        !           637:                        return(-1);
        !           638:                ++(*fsize);
        !           639:        }
        !           640:        return(*fsize);
        !           641: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.